From dfc636764760fb65e7351ec9112f1004c9955a04 Mon Sep 17 00:00:00 2001 From: Thomas Feuvrier <thomas.feuvrier@c-s.fr> Date: Mon, 21 Jan 2008 10:31:02 +0000 Subject: [PATCH] Add FLTK library in OTB/Utilities directory --- Utilities/CMakeLists.txt | 4 + Utilities/FLTK/.cvsignore | 9 + Utilities/FLTK/ANNOUNCEMENT | 349 + Utilities/FLTK/CHANGES | 3049 ++++ .../CMake/CheckFunctionWithHeaderExists.cmake | 54 + Utilities/FLTK/CMake/FLTKConfig.cmake.in | 39 + Utilities/FLTK/CMake/FLTKUse.cmake | 68 + Utilities/FLTK/CMake/PlatformTests.cxx | 81 + Utilities/FLTK/CMakeLists.txt | 410 + Utilities/FLTK/COPYING | 528 + Utilities/FLTK/CREDITS | 53 + Utilities/FLTK/DartConfig.cmake | 38 + Utilities/FLTK/FL/Enumerations.H | 428 + Utilities/FLTK/FL/Fl.H | 280 + Utilities/FLTK/FL/Fl_Adjuster.H | 55 + Utilities/FLTK/FL/Fl_BMP_Image.H | 43 + Utilities/FLTK/FL/Fl_Bitmap.H | 64 + Utilities/FLTK/FL/Fl_Box.H | 51 + Utilities/FLTK/FL/Fl_Browser.H | 132 + Utilities/FLTK/FL/Fl_Browser_.H | 153 + Utilities/FLTK/FL/Fl_Button.H | 78 + Utilities/FLTK/FL/Fl_Chart.H | 93 + Utilities/FLTK/FL/Fl_Check_Browser.H | 98 + Utilities/FLTK/FL/Fl_Check_Button.H | 42 + Utilities/FLTK/FL/Fl_Choice.H | 48 + Utilities/FLTK/FL/Fl_Clock.H | 75 + Utilities/FLTK/FL/Fl_Color_Chooser.H | 104 + Utilities/FLTK/FL/Fl_Counter.H | 76 + Utilities/FLTK/FL/Fl_Dial.H | 67 + Utilities/FLTK/FL/Fl_Double_Window.H | 54 + Utilities/FLTK/FL/Fl_Export.H | 49 + Utilities/FLTK/FL/Fl_File_Browser.H | 81 + Utilities/FLTK/FL/Fl_File_Chooser.H | 186 + Utilities/FLTK/FL/Fl_File_Icon.H | 115 + Utilities/FLTK/FL/Fl_File_Input.H | 68 + Utilities/FLTK/FL/Fl_Fill_Dial.H | 43 + Utilities/FLTK/FL/Fl_Fill_Slider.H | 43 + Utilities/FLTK/FL/Fl_Float_Input.H | 43 + Utilities/FLTK/FL/Fl_FormsBitmap.H | 48 + Utilities/FLTK/FL/Fl_FormsPixmap.H | 48 + Utilities/FLTK/FL/Fl_Free.H | 66 + Utilities/FLTK/FL/Fl_GIF_Image.H | 43 + Utilities/FLTK/FL/Fl_Gl_Window.H | 96 + Utilities/FLTK/FL/Fl_Group.H | 107 + Utilities/FLTK/FL/Fl_Help_Dialog.H | 93 + Utilities/FLTK/FL/Fl_Help_View.H | 195 + Utilities/FLTK/FL/Fl_Hold_Browser.H | 43 + Utilities/FLTK/FL/Fl_Hor_Fill_Slider.H | 42 + Utilities/FLTK/FL/Fl_Hor_Nice_Slider.H | 43 + Utilities/FLTK/FL/Fl_Hor_Slider.H | 43 + Utilities/FLTK/FL/Fl_Hor_Value_Slider.H | 43 + Utilities/FLTK/FL/Fl_Image.H | 112 + Utilities/FLTK/FL/Fl_Input.H | 48 + Utilities/FLTK/FL/Fl_Input_.H | 145 + Utilities/FLTK/FL/Fl_Input_Choice.H | 154 + Utilities/FLTK/FL/Fl_Int_Input.H | 43 + Utilities/FLTK/FL/Fl_JPEG_Image.H | 43 + Utilities/FLTK/FL/Fl_Light_Button.H | 45 + Utilities/FLTK/FL/Fl_Line_Dial.H | 43 + Utilities/FLTK/FL/Fl_Menu.H | 33 + Utilities/FLTK/FL/Fl_Menu_.H | 102 + Utilities/FLTK/FL/Fl_Menu_Bar.H | 46 + Utilities/FLTK/FL/Fl_Menu_Button.H | 48 + Utilities/FLTK/FL/Fl_Menu_Item.H | 167 + Utilities/FLTK/FL/Fl_Menu_Window.H | 54 + Utilities/FLTK/FL/Fl_Multi_Browser.H | 43 + Utilities/FLTK/FL/Fl_Multi_Label.H | 47 + Utilities/FLTK/FL/Fl_Multiline_Input.H | 43 + Utilities/FLTK/FL/Fl_Multiline_Output.H | 43 + Utilities/FLTK/FL/Fl_Nice_Slider.H | 42 + Utilities/FLTK/FL/Fl_Object.H | 36 + Utilities/FLTK/FL/Fl_Output.H | 43 + Utilities/FLTK/FL/Fl_Overlay_Window.H | 56 + Utilities/FLTK/FL/Fl_PNG_Image.H | 43 + Utilities/FLTK/FL/Fl_PNM_Image.H | 43 + Utilities/FLTK/FL/Fl_Pack.H | 51 + Utilities/FLTK/FL/Fl_Pixmap.H | 80 + Utilities/FLTK/FL/Fl_Positioner.H | 77 + Utilities/FLTK/FL/Fl_Preferences.H | 169 + Utilities/FLTK/FL/Fl_Progress.H | 70 + Utilities/FLTK/FL/Fl_Radio_Button.H | 43 + Utilities/FLTK/FL/Fl_Radio_Light_Button.H | 42 + Utilities/FLTK/FL/Fl_Radio_Round_Button.H | 43 + Utilities/FLTK/FL/Fl_Repeat_Button.H | 49 + Utilities/FLTK/FL/Fl_Return_Button.H | 45 + Utilities/FLTK/FL/Fl_Roller.H | 47 + Utilities/FLTK/FL/Fl_Round_Button.H | 42 + Utilities/FLTK/FL/Fl_Round_Clock.H | 43 + Utilities/FLTK/FL/Fl_Scroll.H | 79 + Utilities/FLTK/FL/Fl_Scrollbar.H | 60 + Utilities/FLTK/FL/Fl_Secret_Input.H | 43 + Utilities/FLTK/FL/Fl_Select_Browser.H | 43 + Utilities/FLTK/FL/Fl_Shared_Image.H | 99 + Utilities/FLTK/FL/Fl_Simple_Counter.H | 43 + Utilities/FLTK/FL/Fl_Single_Window.H | 49 + Utilities/FLTK/FL/Fl_Slider.H | 75 + Utilities/FLTK/FL/Fl_Spinner.H | 171 + Utilities/FLTK/FL/Fl_Sys_Menu_Bar.H | 56 + Utilities/FLTK/FL/Fl_Tabs.H | 56 + Utilities/FLTK/FL/Fl_Text_Buffer.H | 259 + Utilities/FLTK/FL/Fl_Text_Display.H | 298 + Utilities/FLTK/FL/Fl_Text_Editor.H | 110 + Utilities/FLTK/FL/Fl_Tile.H | 45 + Utilities/FLTK/FL/Fl_Tiled_Image.H | 59 + Utilities/FLTK/FL/Fl_Timer.H | 65 + Utilities/FLTK/FL/Fl_Toggle_Button.H | 43 + Utilities/FLTK/FL/Fl_Toggle_Light_Button.H | 37 + Utilities/FLTK/FL/Fl_Toggle_Round_Button.H | 37 + Utilities/FLTK/FL/Fl_Tooltip.H | 77 + Utilities/FLTK/FL/Fl_Valuator.H | 86 + Utilities/FLTK/FL/Fl_Value_Input.H | 65 + Utilities/FLTK/FL/Fl_Value_Output.H | 58 + Utilities/FLTK/FL/Fl_Value_Slider.H | 52 + Utilities/FLTK/FL/Fl_Widget.H | 220 + Utilities/FLTK/FL/Fl_Window.H | 135 + Utilities/FLTK/FL/Fl_Wizard.H | 62 + Utilities/FLTK/FL/Fl_XBM_Image.H | 43 + Utilities/FLTK/FL/Fl_XPM_Image.H | 43 + Utilities/FLTK/FL/Makefile.in | 64 + Utilities/FLTK/FL/dirent.h | 33 + Utilities/FLTK/FL/filename.H | 138 + Utilities/FLTK/FL/fl_ask.H | 81 + Utilities/FLTK/FL/fl_draw.H | 200 + Utilities/FLTK/FL/fl_message.H | 32 + Utilities/FLTK/FL/fl_show_colormap.H | 37 + Utilities/FLTK/FL/fl_show_input.H | 32 + Utilities/FLTK/FL/forms.H | 844 ++ Utilities/FLTK/FL/gl.h | 87 + Utilities/FLTK/FL/gl2opengl.h | 35 + Utilities/FLTK/FL/gl_draw.H | 35 + Utilities/FLTK/FL/glut.H | 476 + Utilities/FLTK/FL/mac.H | 135 + Utilities/FLTK/FL/mac.r | 13 + Utilities/FLTK/FL/math.h | 72 + Utilities/FLTK/FL/win32.H | 151 + Utilities/FLTK/FL/x.H | 147 + Utilities/FLTK/GL/glut.h | 30 + Utilities/FLTK/README | 29 + Utilities/FLTK/configh.cmake.in | 265 + Utilities/FLTK/configh.in | 284 + Utilities/FLTK/configure | 12583 ++++++++++++++++ Utilities/FLTK/configure.in | 1005 ++ Utilities/FLTK/fltk-config.in | 308 + Utilities/FLTK/fltk.list.in | 404 + Utilities/FLTK/fltk.spec | 143 + Utilities/FLTK/fltk.spec.in | 143 + Utilities/FLTK/fltk.xpm | 225 + Utilities/FLTK/fluid/CMakeLists.txt | 30 + Utilities/FLTK/fluid/CodeEditor.cxx | 411 + Utilities/FLTK/fluid/CodeEditor.h | 77 + Utilities/FLTK/fluid/Fl_Function_Type.cxx | 1091 ++ Utilities/FLTK/fluid/Fl_Group_Type.cxx | 307 + Utilities/FLTK/fluid/Fl_Menu_Type.cxx | 578 + Utilities/FLTK/fluid/Fl_Type.cxx | 866 ++ Utilities/FLTK/fluid/Fl_Type.h | 764 + Utilities/FLTK/fluid/Fl_Widget_Type.cxx | 2537 ++++ Utilities/FLTK/fluid/Fl_Widget_Type.h | 42 + Utilities/FLTK/fluid/Fl_Window_Type.cxx | 1504 ++ Utilities/FLTK/fluid/Fluid_Image.cxx | 229 + Utilities/FLTK/fluid/Fluid_Image.h | 66 + Utilities/FLTK/fluid/Makefile | 137 + Utilities/FLTK/fluid/Shortcut_Button.h | 41 + Utilities/FLTK/fluid/about_panel.cxx | 308 + Utilities/FLTK/fluid/about_panel.fl | 74 + Utilities/FLTK/fluid/about_panel.h | 44 + Utilities/FLTK/fluid/align_widget.cxx | 541 + Utilities/FLTK/fluid/alignment_panel.cxx | 506 + Utilities/FLTK/fluid/alignment_panel.fl | 411 + Utilities/FLTK/fluid/alignment_panel.h | 105 + Utilities/FLTK/fluid/code.cxx | 578 + Utilities/FLTK/fluid/comments.h | 82 + Utilities/FLTK/fluid/factory.cxx | 1202 ++ Utilities/FLTK/fluid/file.cxx | 643 + .../FLTK/fluid/fluid.app/Contents/Info.plist | 68 + .../FLTK/fluid/fluid.app/Contents/PkgInfo | 1 + .../fluid.app/Contents/Resources/fluid.icns | Bin 0 -> 34579 bytes Utilities/FLTK/fluid/fluid.cxx | 2240 +++ Utilities/FLTK/fluid/fluid.desktop | 11 + Utilities/FLTK/fluid/function_panel.cxx | 933 ++ Utilities/FLTK/fluid/function_panel.fl | 752 + Utilities/FLTK/fluid/function_panel.h | 111 + Utilities/FLTK/fluid/icons/fluid-128.png | Bin 0 -> 10179 bytes Utilities/FLTK/fluid/icons/fluid-16.png | Bin 0 -> 706 bytes Utilities/FLTK/fluid/icons/fluid-16i.png | Bin 0 -> 278 bytes Utilities/FLTK/fluid/icons/fluid-256.png | Bin 0 -> 23785 bytes Utilities/FLTK/fluid/icons/fluid-32.png | Bin 0 -> 1587 bytes Utilities/FLTK/fluid/icons/fluid-32.xpm | 67 + Utilities/FLTK/fluid/icons/fluid-32i.png | Bin 0 -> 450 bytes Utilities/FLTK/fluid/icons/fluid-48.png | Bin 0 -> 2763 bytes Utilities/FLTK/fluid/icons/fluid-64.png | Bin 0 -> 3942 bytes Utilities/FLTK/fluid/icons/fluid-96.xpm | 131 + Utilities/FLTK/fluid/icons/fluid.ico | Bin 0 -> 1078 bytes Utilities/FLTK/fluid/icons/fluid.xcf.gz | Bin 0 -> 22490 bytes Utilities/FLTK/fluid/makedepend | 327 + Utilities/FLTK/fluid/makefile.wat | 76 + Utilities/FLTK/fluid/pixmaps/.cvsignore | 1 + Utilities/FLTK/fluid/pixmaps/flAdjuster.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flBox.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flBrowser.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flButton.xpm | 29 + .../FLTK/fluid/pixmaps/flCheckBrowser.xpm | 29 + .../FLTK/fluid/pixmaps/flCheckButton.xpm | 30 + Utilities/FLTK/fluid/pixmaps/flChoice.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flClass.xpm | 27 + Utilities/FLTK/fluid/pixmaps/flClock.xpm | 28 + Utilities/FLTK/fluid/pixmaps/flCode.xpm | 27 + Utilities/FLTK/fluid/pixmaps/flCodeBlock.xpm | 27 + Utilities/FLTK/fluid/pixmaps/flComment.xpm | 27 + Utilities/FLTK/fluid/pixmaps/flCounter.xpm | 29 + .../FLTK/fluid/pixmaps/flDeclaration.xpm | 27 + .../FLTK/fluid/pixmaps/flDeclarationBlock.xpm | 27 + Utilities/FLTK/fluid/pixmaps/flDial.xpm | 28 + .../FLTK/fluid/pixmaps/flFileBrowser.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flFileInput.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flFunction.xpm | 27 + Utilities/FLTK/fluid/pixmaps/flGroup.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flHelp.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flInput.xpm | 29 + .../FLTK/fluid/pixmaps/flLightButton.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flMenuButton.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flMenubar.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flMenuitem.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flOutput.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flPack.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flProgress.xpm | 29 + .../FLTK/fluid/pixmaps/flRepeatButton.xpm | 29 + .../FLTK/fluid/pixmaps/flReturnButton.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flRoller.xpm | 29 + .../FLTK/fluid/pixmaps/flRoundButton.xpm | 30 + Utilities/FLTK/fluid/pixmaps/flScroll.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flScrollBar.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flSlider.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flSpinner.xpm | 25 + Utilities/FLTK/fluid/pixmaps/flSubmenu.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flTabs.xpm | 29 + .../FLTK/fluid/pixmaps/flTextDisplay.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flTextEdit.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flTile.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flValueInput.xpm | 29 + .../FLTK/fluid/pixmaps/flValueOutput.xpm | 29 + .../FLTK/fluid/pixmaps/flValueSlider.xpm | 29 + .../FLTK/fluid/pixmaps/flWidgetClass.xpm | 31 + Utilities/FLTK/fluid/pixmaps/flWindow.xpm | 29 + Utilities/FLTK/fluid/pixmaps/flWizard.xpm | 29 + Utilities/FLTK/fluid/pixmaps/lock.xpm | 29 + Utilities/FLTK/fluid/pixmaps/print_color.xpm | 44 + Utilities/FLTK/fluid/pixmaps/print_gray.xpm | 44 + Utilities/FLTK/fluid/print_panel.cxx | 591 + Utilities/FLTK/fluid/print_panel.fl | 370 + Utilities/FLTK/fluid/print_panel.h | 71 + Utilities/FLTK/fluid/template_panel.cxx | 260 + Utilities/FLTK/fluid/template_panel.fl | 244 + Utilities/FLTK/fluid/template_panel.h | 56 + Utilities/FLTK/fluid/undo.cxx | 189 + Utilities/FLTK/fluid/undo.h | 46 + Utilities/FLTK/fluid/widget_panel.cxx | 764 + Utilities/FLTK/fluid/widget_panel.fl | 549 + Utilities/FLTK/fluid/widget_panel.h | 119 + Utilities/FLTK/fluid/x-fluid.desktop | 8 + Utilities/FLTK/forms.h | 3 + Utilities/FLTK/jpeg/CMakeLists.txt | 36 + Utilities/FLTK/jpeg/Makefile | 116 + Utilities/FLTK/jpeg/README | 385 + Utilities/FLTK/jpeg/coderules.doc | 118 + Utilities/FLTK/jpeg/filelist.doc | 210 + Utilities/FLTK/jpeg/jcapimin.c | 280 + Utilities/FLTK/jpeg/jcapistd.c | 161 + Utilities/FLTK/jpeg/jccoefct.c | 449 + Utilities/FLTK/jpeg/jccolor.c | 459 + Utilities/FLTK/jpeg/jcdctmgr.c | 387 + Utilities/FLTK/jpeg/jchuff.c | 909 ++ Utilities/FLTK/jpeg/jchuff.h | 47 + Utilities/FLTK/jpeg/jcinit.c | 72 + Utilities/FLTK/jpeg/jcmainct.c | 293 + Utilities/FLTK/jpeg/jcmarker.c | 664 + Utilities/FLTK/jpeg/jcmaster.c | 590 + Utilities/FLTK/jpeg/jcomapi.c | 106 + Utilities/FLTK/jpeg/jconfig.doc | 155 + Utilities/FLTK/jpeg/jconfig.h | 50 + Utilities/FLTK/jpeg/jcparam.c | 610 + Utilities/FLTK/jpeg/jcphuff.c | 833 + Utilities/FLTK/jpeg/jcprepct.c | 354 + Utilities/FLTK/jpeg/jcsample.c | 519 + Utilities/FLTK/jpeg/jctrans.c | 388 + Utilities/FLTK/jpeg/jdapimin.c | 395 + Utilities/FLTK/jpeg/jdapistd.c | 275 + Utilities/FLTK/jpeg/jdatadst.c | 151 + Utilities/FLTK/jpeg/jdatasrc.c | 212 + Utilities/FLTK/jpeg/jdcoefct.c | 736 + Utilities/FLTK/jpeg/jdcolor.c | 396 + Utilities/FLTK/jpeg/jdct.h | 176 + Utilities/FLTK/jpeg/jddctmgr.c | 269 + Utilities/FLTK/jpeg/jdhuff.c | 651 + Utilities/FLTK/jpeg/jdhuff.h | 201 + Utilities/FLTK/jpeg/jdinput.c | 381 + Utilities/FLTK/jpeg/jdmainct.c | 512 + Utilities/FLTK/jpeg/jdmarker.c | 1360 ++ Utilities/FLTK/jpeg/jdmaster.c | 557 + Utilities/FLTK/jpeg/jdmerge.c | 400 + Utilities/FLTK/jpeg/jdphuff.c | 668 + Utilities/FLTK/jpeg/jdpostct.c | 290 + Utilities/FLTK/jpeg/jdsample.c | 478 + Utilities/FLTK/jpeg/jdtrans.c | 143 + Utilities/FLTK/jpeg/jerror.c | 253 + Utilities/FLTK/jpeg/jerror.h | 291 + Utilities/FLTK/jpeg/jfdctflt.c | 168 + Utilities/FLTK/jpeg/jfdctfst.c | 224 + Utilities/FLTK/jpeg/jfdctint.c | 283 + Utilities/FLTK/jpeg/jidctflt.c | 242 + Utilities/FLTK/jpeg/jidctfst.c | 368 + Utilities/FLTK/jpeg/jidctint.c | 389 + Utilities/FLTK/jpeg/jidctred.c | 398 + Utilities/FLTK/jpeg/jinclude.h | 91 + Utilities/FLTK/jpeg/jmemmgr.c | 1118 ++ Utilities/FLTK/jpeg/jmemnobs.c | 109 + Utilities/FLTK/jpeg/jmemsys.h | 198 + Utilities/FLTK/jpeg/jmorecfg.h | 316 + Utilities/FLTK/jpeg/jpegint.h | 392 + Utilities/FLTK/jpeg/jpeglib.h | 1096 ++ Utilities/FLTK/jpeg/jquant1.c | 856 ++ Utilities/FLTK/jpeg/jquant2.c | 1310 ++ Utilities/FLTK/jpeg/jutils.c | 179 + Utilities/FLTK/jpeg/jversion.h | 14 + Utilities/FLTK/jpeg/libjpeg.doc | 3006 ++++ Utilities/FLTK/jpeg/makedepend | 94 + Utilities/FLTK/jpeg/makefile.wat | 67 + Utilities/FLTK/jpeg/structure.doc | 948 ++ Utilities/FLTK/jpeg/usage.doc | 562 + Utilities/FLTK/jpeg/wizard.doc | 211 + Utilities/FLTK/lib/README.lib | 16 + Utilities/FLTK/png/ANNOUNCE | 28 + Utilities/FLTK/png/CHANGES | 1373 ++ Utilities/FLTK/png/CMakeLists.txt | 30 + Utilities/FLTK/png/INSTALL | 167 + Utilities/FLTK/png/KNOWNBUG | 11 + Utilities/FLTK/png/LICENSE | 109 + Utilities/FLTK/png/Makefile | 107 + Utilities/FLTK/png/README | 260 + Utilities/FLTK/png/TODO | 24 + Utilities/FLTK/png/Y2KINFO | 55 + Utilities/FLTK/png/libpng.3 | 4016 +++++ Utilities/FLTK/png/libpng.txt | 2958 ++++ Utilities/FLTK/png/libpngpf.3 | 1096 ++ Utilities/FLTK/png/makedepend | 17 + Utilities/FLTK/png/makefile.wat | 64 + Utilities/FLTK/png/png.5 | 74 + Utilities/FLTK/png/png.c | 826 + Utilities/FLTK/png/png.h | 3361 +++++ Utilities/FLTK/png/pngconf.h | 1376 ++ Utilities/FLTK/png/pngerror.c | 295 + Utilities/FLTK/png/pngget.c | 934 ++ Utilities/FLTK/png/pngmem.c | 595 + Utilities/FLTK/png/pngpread.c | 1573 ++ Utilities/FLTK/png/pngread.c | 1453 ++ Utilities/FLTK/png/pngrio.c | 161 + Utilities/FLTK/png/pngrtran.c | 4177 +++++ Utilities/FLTK/png/pngrutil.c | 3124 ++++ Utilities/FLTK/png/pngset.c | 1219 ++ Utilities/FLTK/png/pngtrans.c | 644 + Utilities/FLTK/png/pngwio.c | 228 + Utilities/FLTK/png/pngwrite.c | 1464 ++ Utilities/FLTK/png/pngwtran.c | 563 + Utilities/FLTK/png/pngwutil.c | 2726 ++++ Utilities/FLTK/src/CMakeLists.txt | 217 + Utilities/FLTK/src/Fl.cxx | 1203 ++ Utilities/FLTK/src/Fl_Adjuster.cxx | 171 + Utilities/FLTK/src/Fl_BMP_Image.cxx | 496 + Utilities/FLTK/src/Fl_Bitmap.cxx | 518 + Utilities/FLTK/src/Fl_Box.cxx | 44 + Utilities/FLTK/src/Fl_Browser.cxx | 551 + Utilities/FLTK/src/Fl_Browser_.cxx | 807 + Utilities/FLTK/src/Fl_Browser_load.cxx | 57 + Utilities/FLTK/src/Fl_Button.cxx | 164 + Utilities/FLTK/src/Fl_Chart.cxx | 390 + Utilities/FLTK/src/Fl_Check_Browser.cxx | 272 + Utilities/FLTK/src/Fl_Check_Button.cxx | 40 + Utilities/FLTK/src/Fl_Choice.cxx | 162 + Utilities/FLTK/src/Fl_Clock.cxx | 173 + Utilities/FLTK/src/Fl_Color_Chooser.cxx | 529 + Utilities/FLTK/src/Fl_Counter.cxx | 197 + Utilities/FLTK/src/Fl_Dial.cxx | 140 + Utilities/FLTK/src/Fl_Double_Window.cxx | 368 + Utilities/FLTK/src/Fl_File_Browser.cxx | 636 + Utilities/FLTK/src/Fl_File_Chooser.cxx | 445 + Utilities/FLTK/src/Fl_File_Chooser.fl | 422 + Utilities/FLTK/src/Fl_File_Chooser2.cxx | 1251 ++ Utilities/FLTK/src/Fl_File_Icon.cxx | 485 + Utilities/FLTK/src/Fl_File_Icon2.cxx | 1015 ++ Utilities/FLTK/src/Fl_File_Input.cxx | 283 + Utilities/FLTK/src/Fl_Font.H | 107 + Utilities/FLTK/src/Fl_GIF_Image.cxx | 384 + Utilities/FLTK/src/Fl_Gl_Choice.H | 132 + Utilities/FLTK/src/Fl_Gl_Choice.cxx | 452 + Utilities/FLTK/src/Fl_Gl_Overlay.cxx | 250 + Utilities/FLTK/src/Fl_Gl_Window.cxx | 427 + Utilities/FLTK/src/Fl_Group.cxx | 612 + Utilities/FLTK/src/Fl_Help_Dialog.cxx | 321 + Utilities/FLTK/src/Fl_Help_Dialog.fl | 269 + Utilities/FLTK/src/Fl_Help_View.cxx | 2924 ++++ Utilities/FLTK/src/Fl_Image.cxx | 439 + Utilities/FLTK/src/Fl_Input.cxx | 467 + Utilities/FLTK/src/Fl_Input_.cxx | 882 ++ Utilities/FLTK/src/Fl_JPEG_Image.cxx | 198 + Utilities/FLTK/src/Fl_Light_Button.cxx | 152 + Utilities/FLTK/src/Fl_Menu.cxx | 853 ++ Utilities/FLTK/src/Fl_Menu_.cxx | 232 + Utilities/FLTK/src/Fl_Menu_Bar.cxx | 78 + Utilities/FLTK/src/Fl_Menu_Button.cxx | 108 + Utilities/FLTK/src/Fl_Menu_Window.cxx | 104 + Utilities/FLTK/src/Fl_Menu_add.cxx | 268 + Utilities/FLTK/src/Fl_Menu_global.cxx | 50 + Utilities/FLTK/src/Fl_Multi_Label.cxx | 80 + Utilities/FLTK/src/Fl_Overlay_Window.cxx | 156 + Utilities/FLTK/src/Fl_PNG_Image.cxx | 156 + Utilities/FLTK/src/Fl_PNM_Image.cxx | 182 + Utilities/FLTK/src/Fl_Pack.cxx | 147 + Utilities/FLTK/src/Fl_Pixmap.cxx | 495 + Utilities/FLTK/src/Fl_Positioner.cxx | 147 + Utilities/FLTK/src/Fl_Preferences.cxx | 1127 ++ Utilities/FLTK/src/Fl_Progress.cxx | 115 + Utilities/FLTK/src/Fl_Repeat_Button.cxx | 68 + Utilities/FLTK/src/Fl_Return_Button.cxx | 72 + Utilities/FLTK/src/Fl_Roller.cxx | 180 + Utilities/FLTK/src/Fl_Round_Button.cxx | 44 + Utilities/FLTK/src/Fl_Scroll.cxx | 297 + Utilities/FLTK/src/Fl_Scrollbar.cxx | 257 + Utilities/FLTK/src/Fl_Shared_Image.cxx | 467 + Utilities/FLTK/src/Fl_Single_Window.cxx | 41 + Utilities/FLTK/src/Fl_Slider.cxx | 295 + Utilities/FLTK/src/Fl_Sys_Menu_Bar.cxx | 329 + Utilities/FLTK/src/Fl_Tabs.cxx | 353 + Utilities/FLTK/src/Fl_Text_Buffer.cxx | 2524 ++++ Utilities/FLTK/src/Fl_Text_Display.cxx | 3239 ++++ Utilities/FLTK/src/Fl_Text_Editor.cxx | 485 + Utilities/FLTK/src/Fl_Tile.cxx | 203 + Utilities/FLTK/src/Fl_Tiled_Image.cxx | 139 + Utilities/FLTK/src/Fl_Tooltip.cxx | 262 + Utilities/FLTK/src/Fl_Valuator.cxx | 149 + Utilities/FLTK/src/Fl_Value_Input.cxx | 133 + Utilities/FLTK/src/Fl_Value_Output.cxx | 103 + Utilities/FLTK/src/Fl_Value_Slider.cxx | 82 + Utilities/FLTK/src/Fl_Widget.cxx | 283 + Utilities/FLTK/src/Fl_Window.cxx | 176 + Utilities/FLTK/src/Fl_Window_fullscreen.cxx | 99 + Utilities/FLTK/src/Fl_Window_hotspot.cxx | 90 + Utilities/FLTK/src/Fl_Window_iconize.cxx | 49 + Utilities/FLTK/src/Fl_Wizard.cxx | 210 + Utilities/FLTK/src/Fl_XBM_Image.cxx | 106 + Utilities/FLTK/src/Fl_XColor.H | 46 + Utilities/FLTK/src/Fl_XPM_Image.cxx | 131 + Utilities/FLTK/src/Fl_abort.cxx | 102 + Utilities/FLTK/src/Fl_add_idle.cxx | 100 + Utilities/FLTK/src/Fl_arg.cxx | 424 + Utilities/FLTK/src/Fl_compose.cxx | 167 + Utilities/FLTK/src/Fl_display.cxx | 54 + Utilities/FLTK/src/Fl_get_key.cxx | 69 + Utilities/FLTK/src/Fl_get_key_mac.cxx | 107 + Utilities/FLTK/src/Fl_get_key_win32.cxx | 138 + Utilities/FLTK/src/Fl_get_system_colors.cxx | 348 + Utilities/FLTK/src/Fl_grab.cxx | 108 + Utilities/FLTK/src/Fl_lock.cxx | 211 + Utilities/FLTK/src/Fl_mac.cxx | 2244 +++ Utilities/FLTK/src/Fl_own_colormap.cxx | 85 + Utilities/FLTK/src/Fl_visual.cxx | 123 + Utilities/FLTK/src/Fl_win32.cxx | 1664 ++ Utilities/FLTK/src/Fl_x.cxx | 1354 ++ Utilities/FLTK/src/allfiles.xbm | 6 + Utilities/FLTK/src/cmap.cxx | 179 + Utilities/FLTK/src/d1.xbm | 6 + Utilities/FLTK/src/d1_mask.xbm | 6 + Utilities/FLTK/src/dump_compose.c | 26 + Utilities/FLTK/src/ew.xbm | 8 + Utilities/FLTK/src/ew_mask.xbm | 8 + Utilities/FLTK/src/fastarrow.h | 6 + Utilities/FLTK/src/filename_absolute.cxx | 197 + Utilities/FLTK/src/filename_expand.cxx | 110 + Utilities/FLTK/src/filename_ext.cxx | 47 + Utilities/FLTK/src/filename_isdir.cxx | 77 + Utilities/FLTK/src/filename_list.cxx | 108 + Utilities/FLTK/src/filename_match.cxx | 106 + Utilities/FLTK/src/filename_setext.cxx | 46 + Utilities/FLTK/src/fl_arc.cxx | 86 + Utilities/FLTK/src/fl_arci.cxx | 119 + Utilities/FLTK/src/fl_ask.cxx | 357 + Utilities/FLTK/src/fl_boxtype.cxx | 311 + Utilities/FLTK/src/fl_call_main.c | 107 + Utilities/FLTK/src/fl_cmap.h | 256 + Utilities/FLTK/src/fl_color.cxx | 389 + Utilities/FLTK/src/fl_color_mac.cxx | 115 + Utilities/FLTK/src/fl_color_win32.cxx | 255 + Utilities/FLTK/src/fl_cursor.cxx | 326 + Utilities/FLTK/src/fl_curve.cxx | 106 + Utilities/FLTK/src/fl_diamond_box.cxx | 80 + Utilities/FLTK/src/fl_dnd.cxx | 38 + Utilities/FLTK/src/fl_dnd_mac.cxx | 91 + Utilities/FLTK/src/fl_dnd_win32.cxx | 404 + Utilities/FLTK/src/fl_dnd_x.cxx | 201 + Utilities/FLTK/src/fl_draw.cxx | 332 + Utilities/FLTK/src/fl_draw_image.cxx | 578 + Utilities/FLTK/src/fl_draw_image_mac.cxx | 271 + Utilities/FLTK/src/fl_draw_image_win32.cxx | 265 + Utilities/FLTK/src/fl_draw_pixmap.cxx | 343 + Utilities/FLTK/src/fl_engraved_label.cxx | 93 + Utilities/FLTK/src/fl_file_dir.cxx | 160 + Utilities/FLTK/src/fl_font.cxx | 60 + Utilities/FLTK/src/fl_font_mac.cxx | 307 + Utilities/FLTK/src/fl_font_win32.cxx | 169 + Utilities/FLTK/src/fl_font_x.cxx | 264 + Utilities/FLTK/src/fl_font_xft.cxx | 265 + Utilities/FLTK/src/fl_images_core.cxx | 103 + Utilities/FLTK/src/fl_labeltype.cxx | 133 + Utilities/FLTK/src/fl_line_style.cxx | 165 + Utilities/FLTK/src/fl_oval_box.cxx | 66 + Utilities/FLTK/src/fl_overlay.cxx | 81 + Utilities/FLTK/src/fl_overlay_visual.cxx | 107 + Utilities/FLTK/src/fl_plastic.cxx | 381 + Utilities/FLTK/src/fl_read_image.cxx | 425 + Utilities/FLTK/src/fl_read_image_mac.cxx | 129 + Utilities/FLTK/src/fl_read_image_win32.cxx | 72 + Utilities/FLTK/src/fl_rect.cxx | 677 + Utilities/FLTK/src/fl_round_box.cxx | 122 + Utilities/FLTK/src/fl_rounded_box.cxx | 99 + Utilities/FLTK/src/fl_scroll_area.cxx | 143 + Utilities/FLTK/src/fl_set_font.cxx | 88 + Utilities/FLTK/src/fl_set_fonts.cxx | 46 + Utilities/FLTK/src/fl_set_fonts_mac.cxx | 214 + Utilities/FLTK/src/fl_set_fonts_win32.cxx | 149 + Utilities/FLTK/src/fl_set_fonts_x.cxx | 350 + Utilities/FLTK/src/fl_set_fonts_xft.cxx | 361 + Utilities/FLTK/src/fl_shadow_box.cxx | 56 + Utilities/FLTK/src/fl_shortcut.cxx | 221 + Utilities/FLTK/src/fl_show_colormap.cxx | 162 + Utilities/FLTK/src/fl_symbols.cxx | 700 + Utilities/FLTK/src/fl_vertex.cxx | 326 + Utilities/FLTK/src/flstring.c | 105 + Utilities/FLTK/src/flstring.h | 115 + Utilities/FLTK/src/forms_bitmap.cxx | 52 + Utilities/FLTK/src/forms_compatability.cxx | 211 + Utilities/FLTK/src/forms_free.cxx | 81 + Utilities/FLTK/src/forms_fselect.cxx | 67 + Utilities/FLTK/src/forms_pixmap.cxx | 52 + Utilities/FLTK/src/forms_timer.cxx | 169 + Utilities/FLTK/src/gl_draw.cxx | 232 + Utilities/FLTK/src/gl_start.cxx | 136 + Utilities/FLTK/src/glut_compatability.cxx | 421 + Utilities/FLTK/src/glut_font.cxx | 62 + Utilities/FLTK/src/makefile.wat | 226 + Utilities/FLTK/src/mediumarrow.h | 6 + Utilities/FLTK/src/new.xbm | 6 + Utilities/FLTK/src/ns.xbm | 8 + Utilities/FLTK/src/ns_mask.xbm | 8 + Utilities/FLTK/src/numericsort.c | 112 + Utilities/FLTK/src/scandir.c | 124 + Utilities/FLTK/src/scandir_win32.c | 115 + Utilities/FLTK/src/screen_xywh.cxx | 242 + Utilities/FLTK/src/slowarrow.h | 6 + Utilities/FLTK/src/tile.xpm | 91 + Utilities/FLTK/src/up.xbm | 6 + Utilities/FLTK/src/vsnprintf.c | 271 + Utilities/FLTK/zlib/CMakeLists.txt | 15 + Utilities/FLTK/zlib/ChangeLog | 722 + Utilities/FLTK/zlib/FAQ | 100 + Utilities/FLTK/zlib/INDEX | 48 + Utilities/FLTK/zlib/Makefile | 107 + Utilities/FLTK/zlib/README | 126 + Utilities/FLTK/zlib/adler32.c | 74 + Utilities/FLTK/zlib/algorithm.txt | 209 + Utilities/FLTK/zlib/compress.c | 79 + Utilities/FLTK/zlib/crc32.c | 311 + Utilities/FLTK/zlib/crc32.h | 441 + Utilities/FLTK/zlib/deflate.c | 1502 ++ Utilities/FLTK/zlib/deflate.h | 326 + Utilities/FLTK/zlib/gzio.c | 1005 ++ Utilities/FLTK/zlib/inffast.c | 305 + Utilities/FLTK/zlib/inffast.h | 11 + Utilities/FLTK/zlib/inffixed.h | 94 + Utilities/FLTK/zlib/inflate.c | 1270 ++ Utilities/FLTK/zlib/inflate.h | 117 + Utilities/FLTK/zlib/inftrees.c | 321 + Utilities/FLTK/zlib/inftrees.h | 55 + Utilities/FLTK/zlib/makedepend | 13 + Utilities/FLTK/zlib/makefile.wat | 60 + Utilities/FLTK/zlib/trees.c | 1215 ++ Utilities/FLTK/zlib/trees.h | 128 + Utilities/FLTK/zlib/uncompr.c | 61 + Utilities/FLTK/zlib/zconf.h | 323 + Utilities/FLTK/zlib/zlib.3 | 159 + Utilities/FLTK/zlib/zlib.h | 1200 ++ Utilities/FLTK/zlib/zutil.c | 319 + Utilities/FLTK/zlib/zutil.h | 258 + 590 files changed, 186605 insertions(+) create mode 100644 Utilities/FLTK/.cvsignore create mode 100644 Utilities/FLTK/ANNOUNCEMENT create mode 100644 Utilities/FLTK/CHANGES create mode 100644 Utilities/FLTK/CMake/CheckFunctionWithHeaderExists.cmake create mode 100644 Utilities/FLTK/CMake/FLTKConfig.cmake.in create mode 100644 Utilities/FLTK/CMake/FLTKUse.cmake create mode 100644 Utilities/FLTK/CMake/PlatformTests.cxx create mode 100644 Utilities/FLTK/CMakeLists.txt create mode 100644 Utilities/FLTK/COPYING create mode 100644 Utilities/FLTK/CREDITS create mode 100644 Utilities/FLTK/DartConfig.cmake create mode 100644 Utilities/FLTK/FL/Enumerations.H create mode 100644 Utilities/FLTK/FL/Fl.H create mode 100644 Utilities/FLTK/FL/Fl_Adjuster.H create mode 100644 Utilities/FLTK/FL/Fl_BMP_Image.H create mode 100644 Utilities/FLTK/FL/Fl_Bitmap.H create mode 100644 Utilities/FLTK/FL/Fl_Box.H create mode 100644 Utilities/FLTK/FL/Fl_Browser.H create mode 100644 Utilities/FLTK/FL/Fl_Browser_.H create mode 100644 Utilities/FLTK/FL/Fl_Button.H create mode 100644 Utilities/FLTK/FL/Fl_Chart.H create mode 100644 Utilities/FLTK/FL/Fl_Check_Browser.H create mode 100644 Utilities/FLTK/FL/Fl_Check_Button.H create mode 100644 Utilities/FLTK/FL/Fl_Choice.H create mode 100644 Utilities/FLTK/FL/Fl_Clock.H create mode 100644 Utilities/FLTK/FL/Fl_Color_Chooser.H create mode 100644 Utilities/FLTK/FL/Fl_Counter.H create mode 100644 Utilities/FLTK/FL/Fl_Dial.H create mode 100644 Utilities/FLTK/FL/Fl_Double_Window.H create mode 100644 Utilities/FLTK/FL/Fl_Export.H create mode 100644 Utilities/FLTK/FL/Fl_File_Browser.H create mode 100644 Utilities/FLTK/FL/Fl_File_Chooser.H create mode 100644 Utilities/FLTK/FL/Fl_File_Icon.H create mode 100644 Utilities/FLTK/FL/Fl_File_Input.H create mode 100644 Utilities/FLTK/FL/Fl_Fill_Dial.H create mode 100644 Utilities/FLTK/FL/Fl_Fill_Slider.H create mode 100644 Utilities/FLTK/FL/Fl_Float_Input.H create mode 100644 Utilities/FLTK/FL/Fl_FormsBitmap.H create mode 100644 Utilities/FLTK/FL/Fl_FormsPixmap.H create mode 100644 Utilities/FLTK/FL/Fl_Free.H create mode 100644 Utilities/FLTK/FL/Fl_GIF_Image.H create mode 100644 Utilities/FLTK/FL/Fl_Gl_Window.H create mode 100644 Utilities/FLTK/FL/Fl_Group.H create mode 100644 Utilities/FLTK/FL/Fl_Help_Dialog.H create mode 100644 Utilities/FLTK/FL/Fl_Help_View.H create mode 100644 Utilities/FLTK/FL/Fl_Hold_Browser.H create mode 100644 Utilities/FLTK/FL/Fl_Hor_Fill_Slider.H create mode 100644 Utilities/FLTK/FL/Fl_Hor_Nice_Slider.H create mode 100644 Utilities/FLTK/FL/Fl_Hor_Slider.H create mode 100644 Utilities/FLTK/FL/Fl_Hor_Value_Slider.H create mode 100644 Utilities/FLTK/FL/Fl_Image.H create mode 100644 Utilities/FLTK/FL/Fl_Input.H create mode 100644 Utilities/FLTK/FL/Fl_Input_.H create mode 100644 Utilities/FLTK/FL/Fl_Input_Choice.H create mode 100644 Utilities/FLTK/FL/Fl_Int_Input.H create mode 100644 Utilities/FLTK/FL/Fl_JPEG_Image.H create mode 100644 Utilities/FLTK/FL/Fl_Light_Button.H create mode 100644 Utilities/FLTK/FL/Fl_Line_Dial.H create mode 100644 Utilities/FLTK/FL/Fl_Menu.H create mode 100644 Utilities/FLTK/FL/Fl_Menu_.H create mode 100644 Utilities/FLTK/FL/Fl_Menu_Bar.H create mode 100644 Utilities/FLTK/FL/Fl_Menu_Button.H create mode 100644 Utilities/FLTK/FL/Fl_Menu_Item.H create mode 100644 Utilities/FLTK/FL/Fl_Menu_Window.H create mode 100644 Utilities/FLTK/FL/Fl_Multi_Browser.H create mode 100644 Utilities/FLTK/FL/Fl_Multi_Label.H create mode 100644 Utilities/FLTK/FL/Fl_Multiline_Input.H create mode 100644 Utilities/FLTK/FL/Fl_Multiline_Output.H create mode 100644 Utilities/FLTK/FL/Fl_Nice_Slider.H create mode 100644 Utilities/FLTK/FL/Fl_Object.H create mode 100644 Utilities/FLTK/FL/Fl_Output.H create mode 100644 Utilities/FLTK/FL/Fl_Overlay_Window.H create mode 100644 Utilities/FLTK/FL/Fl_PNG_Image.H create mode 100644 Utilities/FLTK/FL/Fl_PNM_Image.H create mode 100644 Utilities/FLTK/FL/Fl_Pack.H create mode 100644 Utilities/FLTK/FL/Fl_Pixmap.H create mode 100644 Utilities/FLTK/FL/Fl_Positioner.H create mode 100644 Utilities/FLTK/FL/Fl_Preferences.H create mode 100644 Utilities/FLTK/FL/Fl_Progress.H create mode 100644 Utilities/FLTK/FL/Fl_Radio_Button.H create mode 100644 Utilities/FLTK/FL/Fl_Radio_Light_Button.H create mode 100644 Utilities/FLTK/FL/Fl_Radio_Round_Button.H create mode 100644 Utilities/FLTK/FL/Fl_Repeat_Button.H create mode 100644 Utilities/FLTK/FL/Fl_Return_Button.H create mode 100644 Utilities/FLTK/FL/Fl_Roller.H create mode 100644 Utilities/FLTK/FL/Fl_Round_Button.H create mode 100644 Utilities/FLTK/FL/Fl_Round_Clock.H create mode 100644 Utilities/FLTK/FL/Fl_Scroll.H create mode 100644 Utilities/FLTK/FL/Fl_Scrollbar.H create mode 100644 Utilities/FLTK/FL/Fl_Secret_Input.H create mode 100644 Utilities/FLTK/FL/Fl_Select_Browser.H create mode 100644 Utilities/FLTK/FL/Fl_Shared_Image.H create mode 100644 Utilities/FLTK/FL/Fl_Simple_Counter.H create mode 100644 Utilities/FLTK/FL/Fl_Single_Window.H create mode 100644 Utilities/FLTK/FL/Fl_Slider.H create mode 100644 Utilities/FLTK/FL/Fl_Spinner.H create mode 100644 Utilities/FLTK/FL/Fl_Sys_Menu_Bar.H create mode 100644 Utilities/FLTK/FL/Fl_Tabs.H create mode 100644 Utilities/FLTK/FL/Fl_Text_Buffer.H create mode 100644 Utilities/FLTK/FL/Fl_Text_Display.H create mode 100644 Utilities/FLTK/FL/Fl_Text_Editor.H create mode 100644 Utilities/FLTK/FL/Fl_Tile.H create mode 100644 Utilities/FLTK/FL/Fl_Tiled_Image.H create mode 100644 Utilities/FLTK/FL/Fl_Timer.H create mode 100644 Utilities/FLTK/FL/Fl_Toggle_Button.H create mode 100644 Utilities/FLTK/FL/Fl_Toggle_Light_Button.H create mode 100644 Utilities/FLTK/FL/Fl_Toggle_Round_Button.H create mode 100644 Utilities/FLTK/FL/Fl_Tooltip.H create mode 100644 Utilities/FLTK/FL/Fl_Valuator.H create mode 100644 Utilities/FLTK/FL/Fl_Value_Input.H create mode 100644 Utilities/FLTK/FL/Fl_Value_Output.H create mode 100644 Utilities/FLTK/FL/Fl_Value_Slider.H create mode 100644 Utilities/FLTK/FL/Fl_Widget.H create mode 100644 Utilities/FLTK/FL/Fl_Window.H create mode 100644 Utilities/FLTK/FL/Fl_Wizard.H create mode 100644 Utilities/FLTK/FL/Fl_XBM_Image.H create mode 100644 Utilities/FLTK/FL/Fl_XPM_Image.H create mode 100644 Utilities/FLTK/FL/Makefile.in create mode 100644 Utilities/FLTK/FL/dirent.h create mode 100644 Utilities/FLTK/FL/filename.H create mode 100644 Utilities/FLTK/FL/fl_ask.H create mode 100644 Utilities/FLTK/FL/fl_draw.H create mode 100644 Utilities/FLTK/FL/fl_message.H create mode 100644 Utilities/FLTK/FL/fl_show_colormap.H create mode 100644 Utilities/FLTK/FL/fl_show_input.H create mode 100644 Utilities/FLTK/FL/forms.H create mode 100644 Utilities/FLTK/FL/gl.h create mode 100644 Utilities/FLTK/FL/gl2opengl.h create mode 100644 Utilities/FLTK/FL/gl_draw.H create mode 100644 Utilities/FLTK/FL/glut.H create mode 100644 Utilities/FLTK/FL/mac.H create mode 100644 Utilities/FLTK/FL/mac.r create mode 100644 Utilities/FLTK/FL/math.h create mode 100644 Utilities/FLTK/FL/win32.H create mode 100644 Utilities/FLTK/FL/x.H create mode 100644 Utilities/FLTK/GL/glut.h create mode 100755 Utilities/FLTK/README create mode 100644 Utilities/FLTK/configh.cmake.in create mode 100644 Utilities/FLTK/configh.in create mode 100755 Utilities/FLTK/configure create mode 100644 Utilities/FLTK/configure.in create mode 100755 Utilities/FLTK/fltk-config.in create mode 100644 Utilities/FLTK/fltk.list.in create mode 100644 Utilities/FLTK/fltk.spec create mode 100644 Utilities/FLTK/fltk.spec.in create mode 100644 Utilities/FLTK/fltk.xpm create mode 100644 Utilities/FLTK/fluid/CMakeLists.txt create mode 100644 Utilities/FLTK/fluid/CodeEditor.cxx create mode 100644 Utilities/FLTK/fluid/CodeEditor.h create mode 100644 Utilities/FLTK/fluid/Fl_Function_Type.cxx create mode 100644 Utilities/FLTK/fluid/Fl_Group_Type.cxx create mode 100644 Utilities/FLTK/fluid/Fl_Menu_Type.cxx create mode 100644 Utilities/FLTK/fluid/Fl_Type.cxx create mode 100644 Utilities/FLTK/fluid/Fl_Type.h create mode 100644 Utilities/FLTK/fluid/Fl_Widget_Type.cxx create mode 100644 Utilities/FLTK/fluid/Fl_Widget_Type.h create mode 100644 Utilities/FLTK/fluid/Fl_Window_Type.cxx create mode 100644 Utilities/FLTK/fluid/Fluid_Image.cxx create mode 100644 Utilities/FLTK/fluid/Fluid_Image.h create mode 100644 Utilities/FLTK/fluid/Makefile create mode 100644 Utilities/FLTK/fluid/Shortcut_Button.h create mode 100644 Utilities/FLTK/fluid/about_panel.cxx create mode 100644 Utilities/FLTK/fluid/about_panel.fl create mode 100644 Utilities/FLTK/fluid/about_panel.h create mode 100644 Utilities/FLTK/fluid/align_widget.cxx create mode 100644 Utilities/FLTK/fluid/alignment_panel.cxx create mode 100644 Utilities/FLTK/fluid/alignment_panel.fl create mode 100644 Utilities/FLTK/fluid/alignment_panel.h create mode 100644 Utilities/FLTK/fluid/code.cxx create mode 100644 Utilities/FLTK/fluid/comments.h create mode 100644 Utilities/FLTK/fluid/factory.cxx create mode 100644 Utilities/FLTK/fluid/file.cxx create mode 100644 Utilities/FLTK/fluid/fluid.app/Contents/Info.plist create mode 100644 Utilities/FLTK/fluid/fluid.app/Contents/PkgInfo create mode 100644 Utilities/FLTK/fluid/fluid.app/Contents/Resources/fluid.icns create mode 100644 Utilities/FLTK/fluid/fluid.cxx create mode 100644 Utilities/FLTK/fluid/fluid.desktop create mode 100644 Utilities/FLTK/fluid/function_panel.cxx create mode 100644 Utilities/FLTK/fluid/function_panel.fl create mode 100644 Utilities/FLTK/fluid/function_panel.h create mode 100644 Utilities/FLTK/fluid/icons/fluid-128.png create mode 100644 Utilities/FLTK/fluid/icons/fluid-16.png create mode 100644 Utilities/FLTK/fluid/icons/fluid-16i.png create mode 100644 Utilities/FLTK/fluid/icons/fluid-256.png create mode 100644 Utilities/FLTK/fluid/icons/fluid-32.png create mode 100644 Utilities/FLTK/fluid/icons/fluid-32.xpm create mode 100644 Utilities/FLTK/fluid/icons/fluid-32i.png create mode 100644 Utilities/FLTK/fluid/icons/fluid-48.png create mode 100644 Utilities/FLTK/fluid/icons/fluid-64.png create mode 100644 Utilities/FLTK/fluid/icons/fluid-96.xpm create mode 100644 Utilities/FLTK/fluid/icons/fluid.ico create mode 100644 Utilities/FLTK/fluid/icons/fluid.xcf.gz create mode 100644 Utilities/FLTK/fluid/makedepend create mode 100644 Utilities/FLTK/fluid/makefile.wat create mode 100644 Utilities/FLTK/fluid/pixmaps/.cvsignore create mode 100644 Utilities/FLTK/fluid/pixmaps/flAdjuster.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flBox.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flBrowser.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flButton.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flCheckBrowser.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flCheckButton.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flChoice.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flClass.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flClock.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flCode.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flCodeBlock.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flComment.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flCounter.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flDeclaration.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flDeclarationBlock.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flDial.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flFileBrowser.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flFileInput.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flFunction.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flGroup.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flHelp.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flInput.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flLightButton.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flMenuButton.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flMenubar.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flMenuitem.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flOutput.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flPack.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flProgress.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flRepeatButton.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flReturnButton.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flRoller.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flRoundButton.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flScroll.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flScrollBar.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flSlider.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flSpinner.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flSubmenu.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flTabs.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flTextDisplay.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flTextEdit.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flTile.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flValueInput.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flValueOutput.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flValueSlider.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flWidgetClass.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flWindow.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/flWizard.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/lock.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/print_color.xpm create mode 100644 Utilities/FLTK/fluid/pixmaps/print_gray.xpm create mode 100644 Utilities/FLTK/fluid/print_panel.cxx create mode 100644 Utilities/FLTK/fluid/print_panel.fl create mode 100644 Utilities/FLTK/fluid/print_panel.h create mode 100644 Utilities/FLTK/fluid/template_panel.cxx create mode 100644 Utilities/FLTK/fluid/template_panel.fl create mode 100644 Utilities/FLTK/fluid/template_panel.h create mode 100644 Utilities/FLTK/fluid/undo.cxx create mode 100644 Utilities/FLTK/fluid/undo.h create mode 100644 Utilities/FLTK/fluid/widget_panel.cxx create mode 100644 Utilities/FLTK/fluid/widget_panel.fl create mode 100644 Utilities/FLTK/fluid/widget_panel.h create mode 100644 Utilities/FLTK/fluid/x-fluid.desktop create mode 100644 Utilities/FLTK/forms.h create mode 100644 Utilities/FLTK/jpeg/CMakeLists.txt create mode 100644 Utilities/FLTK/jpeg/Makefile create mode 100644 Utilities/FLTK/jpeg/README create mode 100644 Utilities/FLTK/jpeg/coderules.doc create mode 100644 Utilities/FLTK/jpeg/filelist.doc create mode 100644 Utilities/FLTK/jpeg/jcapimin.c create mode 100644 Utilities/FLTK/jpeg/jcapistd.c create mode 100644 Utilities/FLTK/jpeg/jccoefct.c create mode 100644 Utilities/FLTK/jpeg/jccolor.c create mode 100644 Utilities/FLTK/jpeg/jcdctmgr.c create mode 100644 Utilities/FLTK/jpeg/jchuff.c create mode 100644 Utilities/FLTK/jpeg/jchuff.h create mode 100644 Utilities/FLTK/jpeg/jcinit.c create mode 100644 Utilities/FLTK/jpeg/jcmainct.c create mode 100644 Utilities/FLTK/jpeg/jcmarker.c create mode 100644 Utilities/FLTK/jpeg/jcmaster.c create mode 100644 Utilities/FLTK/jpeg/jcomapi.c create mode 100644 Utilities/FLTK/jpeg/jconfig.doc create mode 100644 Utilities/FLTK/jpeg/jconfig.h create mode 100644 Utilities/FLTK/jpeg/jcparam.c create mode 100644 Utilities/FLTK/jpeg/jcphuff.c create mode 100644 Utilities/FLTK/jpeg/jcprepct.c create mode 100644 Utilities/FLTK/jpeg/jcsample.c create mode 100644 Utilities/FLTK/jpeg/jctrans.c create mode 100644 Utilities/FLTK/jpeg/jdapimin.c create mode 100644 Utilities/FLTK/jpeg/jdapistd.c create mode 100644 Utilities/FLTK/jpeg/jdatadst.c create mode 100644 Utilities/FLTK/jpeg/jdatasrc.c create mode 100644 Utilities/FLTK/jpeg/jdcoefct.c create mode 100644 Utilities/FLTK/jpeg/jdcolor.c create mode 100644 Utilities/FLTK/jpeg/jdct.h create mode 100644 Utilities/FLTK/jpeg/jddctmgr.c create mode 100644 Utilities/FLTK/jpeg/jdhuff.c create mode 100644 Utilities/FLTK/jpeg/jdhuff.h create mode 100644 Utilities/FLTK/jpeg/jdinput.c create mode 100644 Utilities/FLTK/jpeg/jdmainct.c create mode 100644 Utilities/FLTK/jpeg/jdmarker.c create mode 100644 Utilities/FLTK/jpeg/jdmaster.c create mode 100644 Utilities/FLTK/jpeg/jdmerge.c create mode 100644 Utilities/FLTK/jpeg/jdphuff.c create mode 100644 Utilities/FLTK/jpeg/jdpostct.c create mode 100644 Utilities/FLTK/jpeg/jdsample.c create mode 100644 Utilities/FLTK/jpeg/jdtrans.c create mode 100644 Utilities/FLTK/jpeg/jerror.c create mode 100644 Utilities/FLTK/jpeg/jerror.h create mode 100644 Utilities/FLTK/jpeg/jfdctflt.c create mode 100644 Utilities/FLTK/jpeg/jfdctfst.c create mode 100644 Utilities/FLTK/jpeg/jfdctint.c create mode 100644 Utilities/FLTK/jpeg/jidctflt.c create mode 100644 Utilities/FLTK/jpeg/jidctfst.c create mode 100644 Utilities/FLTK/jpeg/jidctint.c create mode 100644 Utilities/FLTK/jpeg/jidctred.c create mode 100644 Utilities/FLTK/jpeg/jinclude.h create mode 100644 Utilities/FLTK/jpeg/jmemmgr.c create mode 100644 Utilities/FLTK/jpeg/jmemnobs.c create mode 100644 Utilities/FLTK/jpeg/jmemsys.h create mode 100644 Utilities/FLTK/jpeg/jmorecfg.h create mode 100644 Utilities/FLTK/jpeg/jpegint.h create mode 100644 Utilities/FLTK/jpeg/jpeglib.h create mode 100644 Utilities/FLTK/jpeg/jquant1.c create mode 100644 Utilities/FLTK/jpeg/jquant2.c create mode 100644 Utilities/FLTK/jpeg/jutils.c create mode 100644 Utilities/FLTK/jpeg/jversion.h create mode 100644 Utilities/FLTK/jpeg/libjpeg.doc create mode 100644 Utilities/FLTK/jpeg/makedepend create mode 100644 Utilities/FLTK/jpeg/makefile.wat create mode 100644 Utilities/FLTK/jpeg/structure.doc create mode 100644 Utilities/FLTK/jpeg/usage.doc create mode 100644 Utilities/FLTK/jpeg/wizard.doc create mode 100644 Utilities/FLTK/lib/README.lib create mode 100644 Utilities/FLTK/png/ANNOUNCE create mode 100644 Utilities/FLTK/png/CHANGES create mode 100644 Utilities/FLTK/png/CMakeLists.txt create mode 100644 Utilities/FLTK/png/INSTALL create mode 100644 Utilities/FLTK/png/KNOWNBUG create mode 100644 Utilities/FLTK/png/LICENSE create mode 100644 Utilities/FLTK/png/Makefile create mode 100644 Utilities/FLTK/png/README create mode 100644 Utilities/FLTK/png/TODO create mode 100644 Utilities/FLTK/png/Y2KINFO create mode 100644 Utilities/FLTK/png/libpng.3 create mode 100644 Utilities/FLTK/png/libpng.txt create mode 100644 Utilities/FLTK/png/libpngpf.3 create mode 100644 Utilities/FLTK/png/makedepend create mode 100644 Utilities/FLTK/png/makefile.wat create mode 100644 Utilities/FLTK/png/png.5 create mode 100644 Utilities/FLTK/png/png.c create mode 100644 Utilities/FLTK/png/png.h create mode 100644 Utilities/FLTK/png/pngconf.h create mode 100644 Utilities/FLTK/png/pngerror.c create mode 100644 Utilities/FLTK/png/pngget.c create mode 100644 Utilities/FLTK/png/pngmem.c create mode 100644 Utilities/FLTK/png/pngpread.c create mode 100644 Utilities/FLTK/png/pngread.c create mode 100644 Utilities/FLTK/png/pngrio.c create mode 100644 Utilities/FLTK/png/pngrtran.c create mode 100644 Utilities/FLTK/png/pngrutil.c create mode 100644 Utilities/FLTK/png/pngset.c create mode 100644 Utilities/FLTK/png/pngtrans.c create mode 100644 Utilities/FLTK/png/pngwio.c create mode 100644 Utilities/FLTK/png/pngwrite.c create mode 100644 Utilities/FLTK/png/pngwtran.c create mode 100644 Utilities/FLTK/png/pngwutil.c create mode 100644 Utilities/FLTK/src/CMakeLists.txt create mode 100644 Utilities/FLTK/src/Fl.cxx create mode 100644 Utilities/FLTK/src/Fl_Adjuster.cxx create mode 100644 Utilities/FLTK/src/Fl_BMP_Image.cxx create mode 100644 Utilities/FLTK/src/Fl_Bitmap.cxx create mode 100644 Utilities/FLTK/src/Fl_Box.cxx create mode 100644 Utilities/FLTK/src/Fl_Browser.cxx create mode 100644 Utilities/FLTK/src/Fl_Browser_.cxx create mode 100644 Utilities/FLTK/src/Fl_Browser_load.cxx create mode 100644 Utilities/FLTK/src/Fl_Button.cxx create mode 100644 Utilities/FLTK/src/Fl_Chart.cxx create mode 100644 Utilities/FLTK/src/Fl_Check_Browser.cxx create mode 100644 Utilities/FLTK/src/Fl_Check_Button.cxx create mode 100644 Utilities/FLTK/src/Fl_Choice.cxx create mode 100644 Utilities/FLTK/src/Fl_Clock.cxx create mode 100644 Utilities/FLTK/src/Fl_Color_Chooser.cxx create mode 100644 Utilities/FLTK/src/Fl_Counter.cxx create mode 100644 Utilities/FLTK/src/Fl_Dial.cxx create mode 100644 Utilities/FLTK/src/Fl_Double_Window.cxx create mode 100644 Utilities/FLTK/src/Fl_File_Browser.cxx create mode 100644 Utilities/FLTK/src/Fl_File_Chooser.cxx create mode 100644 Utilities/FLTK/src/Fl_File_Chooser.fl create mode 100644 Utilities/FLTK/src/Fl_File_Chooser2.cxx create mode 100644 Utilities/FLTK/src/Fl_File_Icon.cxx create mode 100644 Utilities/FLTK/src/Fl_File_Icon2.cxx create mode 100644 Utilities/FLTK/src/Fl_File_Input.cxx create mode 100644 Utilities/FLTK/src/Fl_Font.H create mode 100644 Utilities/FLTK/src/Fl_GIF_Image.cxx create mode 100644 Utilities/FLTK/src/Fl_Gl_Choice.H create mode 100644 Utilities/FLTK/src/Fl_Gl_Choice.cxx create mode 100644 Utilities/FLTK/src/Fl_Gl_Overlay.cxx create mode 100644 Utilities/FLTK/src/Fl_Gl_Window.cxx create mode 100644 Utilities/FLTK/src/Fl_Group.cxx create mode 100644 Utilities/FLTK/src/Fl_Help_Dialog.cxx create mode 100644 Utilities/FLTK/src/Fl_Help_Dialog.fl create mode 100644 Utilities/FLTK/src/Fl_Help_View.cxx create mode 100644 Utilities/FLTK/src/Fl_Image.cxx create mode 100644 Utilities/FLTK/src/Fl_Input.cxx create mode 100644 Utilities/FLTK/src/Fl_Input_.cxx create mode 100644 Utilities/FLTK/src/Fl_JPEG_Image.cxx create mode 100644 Utilities/FLTK/src/Fl_Light_Button.cxx create mode 100644 Utilities/FLTK/src/Fl_Menu.cxx create mode 100644 Utilities/FLTK/src/Fl_Menu_.cxx create mode 100644 Utilities/FLTK/src/Fl_Menu_Bar.cxx create mode 100644 Utilities/FLTK/src/Fl_Menu_Button.cxx create mode 100644 Utilities/FLTK/src/Fl_Menu_Window.cxx create mode 100644 Utilities/FLTK/src/Fl_Menu_add.cxx create mode 100644 Utilities/FLTK/src/Fl_Menu_global.cxx create mode 100644 Utilities/FLTK/src/Fl_Multi_Label.cxx create mode 100644 Utilities/FLTK/src/Fl_Overlay_Window.cxx create mode 100644 Utilities/FLTK/src/Fl_PNG_Image.cxx create mode 100644 Utilities/FLTK/src/Fl_PNM_Image.cxx create mode 100644 Utilities/FLTK/src/Fl_Pack.cxx create mode 100644 Utilities/FLTK/src/Fl_Pixmap.cxx create mode 100644 Utilities/FLTK/src/Fl_Positioner.cxx create mode 100644 Utilities/FLTK/src/Fl_Preferences.cxx create mode 100644 Utilities/FLTK/src/Fl_Progress.cxx create mode 100644 Utilities/FLTK/src/Fl_Repeat_Button.cxx create mode 100644 Utilities/FLTK/src/Fl_Return_Button.cxx create mode 100644 Utilities/FLTK/src/Fl_Roller.cxx create mode 100644 Utilities/FLTK/src/Fl_Round_Button.cxx create mode 100644 Utilities/FLTK/src/Fl_Scroll.cxx create mode 100644 Utilities/FLTK/src/Fl_Scrollbar.cxx create mode 100644 Utilities/FLTK/src/Fl_Shared_Image.cxx create mode 100644 Utilities/FLTK/src/Fl_Single_Window.cxx create mode 100644 Utilities/FLTK/src/Fl_Slider.cxx create mode 100644 Utilities/FLTK/src/Fl_Sys_Menu_Bar.cxx create mode 100644 Utilities/FLTK/src/Fl_Tabs.cxx create mode 100644 Utilities/FLTK/src/Fl_Text_Buffer.cxx create mode 100644 Utilities/FLTK/src/Fl_Text_Display.cxx create mode 100644 Utilities/FLTK/src/Fl_Text_Editor.cxx create mode 100644 Utilities/FLTK/src/Fl_Tile.cxx create mode 100644 Utilities/FLTK/src/Fl_Tiled_Image.cxx create mode 100644 Utilities/FLTK/src/Fl_Tooltip.cxx create mode 100644 Utilities/FLTK/src/Fl_Valuator.cxx create mode 100644 Utilities/FLTK/src/Fl_Value_Input.cxx create mode 100644 Utilities/FLTK/src/Fl_Value_Output.cxx create mode 100644 Utilities/FLTK/src/Fl_Value_Slider.cxx create mode 100644 Utilities/FLTK/src/Fl_Widget.cxx create mode 100644 Utilities/FLTK/src/Fl_Window.cxx create mode 100644 Utilities/FLTK/src/Fl_Window_fullscreen.cxx create mode 100644 Utilities/FLTK/src/Fl_Window_hotspot.cxx create mode 100644 Utilities/FLTK/src/Fl_Window_iconize.cxx create mode 100644 Utilities/FLTK/src/Fl_Wizard.cxx create mode 100644 Utilities/FLTK/src/Fl_XBM_Image.cxx create mode 100644 Utilities/FLTK/src/Fl_XColor.H create mode 100644 Utilities/FLTK/src/Fl_XPM_Image.cxx create mode 100644 Utilities/FLTK/src/Fl_abort.cxx create mode 100644 Utilities/FLTK/src/Fl_add_idle.cxx create mode 100644 Utilities/FLTK/src/Fl_arg.cxx create mode 100644 Utilities/FLTK/src/Fl_compose.cxx create mode 100644 Utilities/FLTK/src/Fl_display.cxx create mode 100644 Utilities/FLTK/src/Fl_get_key.cxx create mode 100644 Utilities/FLTK/src/Fl_get_key_mac.cxx create mode 100755 Utilities/FLTK/src/Fl_get_key_win32.cxx create mode 100644 Utilities/FLTK/src/Fl_get_system_colors.cxx create mode 100644 Utilities/FLTK/src/Fl_grab.cxx create mode 100644 Utilities/FLTK/src/Fl_lock.cxx create mode 100644 Utilities/FLTK/src/Fl_mac.cxx create mode 100644 Utilities/FLTK/src/Fl_own_colormap.cxx create mode 100644 Utilities/FLTK/src/Fl_visual.cxx create mode 100644 Utilities/FLTK/src/Fl_win32.cxx create mode 100644 Utilities/FLTK/src/Fl_x.cxx create mode 100644 Utilities/FLTK/src/allfiles.xbm create mode 100644 Utilities/FLTK/src/cmap.cxx create mode 100644 Utilities/FLTK/src/d1.xbm create mode 100644 Utilities/FLTK/src/d1_mask.xbm create mode 100644 Utilities/FLTK/src/dump_compose.c create mode 100644 Utilities/FLTK/src/ew.xbm create mode 100644 Utilities/FLTK/src/ew_mask.xbm create mode 100644 Utilities/FLTK/src/fastarrow.h create mode 100644 Utilities/FLTK/src/filename_absolute.cxx create mode 100644 Utilities/FLTK/src/filename_expand.cxx create mode 100644 Utilities/FLTK/src/filename_ext.cxx create mode 100644 Utilities/FLTK/src/filename_isdir.cxx create mode 100644 Utilities/FLTK/src/filename_list.cxx create mode 100644 Utilities/FLTK/src/filename_match.cxx create mode 100644 Utilities/FLTK/src/filename_setext.cxx create mode 100644 Utilities/FLTK/src/fl_arc.cxx create mode 100644 Utilities/FLTK/src/fl_arci.cxx create mode 100644 Utilities/FLTK/src/fl_ask.cxx create mode 100644 Utilities/FLTK/src/fl_boxtype.cxx create mode 100644 Utilities/FLTK/src/fl_call_main.c create mode 100644 Utilities/FLTK/src/fl_cmap.h create mode 100644 Utilities/FLTK/src/fl_color.cxx create mode 100644 Utilities/FLTK/src/fl_color_mac.cxx create mode 100644 Utilities/FLTK/src/fl_color_win32.cxx create mode 100644 Utilities/FLTK/src/fl_cursor.cxx create mode 100644 Utilities/FLTK/src/fl_curve.cxx create mode 100644 Utilities/FLTK/src/fl_diamond_box.cxx create mode 100644 Utilities/FLTK/src/fl_dnd.cxx create mode 100644 Utilities/FLTK/src/fl_dnd_mac.cxx create mode 100644 Utilities/FLTK/src/fl_dnd_win32.cxx create mode 100644 Utilities/FLTK/src/fl_dnd_x.cxx create mode 100644 Utilities/FLTK/src/fl_draw.cxx create mode 100644 Utilities/FLTK/src/fl_draw_image.cxx create mode 100644 Utilities/FLTK/src/fl_draw_image_mac.cxx create mode 100644 Utilities/FLTK/src/fl_draw_image_win32.cxx create mode 100644 Utilities/FLTK/src/fl_draw_pixmap.cxx create mode 100644 Utilities/FLTK/src/fl_engraved_label.cxx create mode 100644 Utilities/FLTK/src/fl_file_dir.cxx create mode 100644 Utilities/FLTK/src/fl_font.cxx create mode 100644 Utilities/FLTK/src/fl_font_mac.cxx create mode 100644 Utilities/FLTK/src/fl_font_win32.cxx create mode 100644 Utilities/FLTK/src/fl_font_x.cxx create mode 100644 Utilities/FLTK/src/fl_font_xft.cxx create mode 100644 Utilities/FLTK/src/fl_images_core.cxx create mode 100644 Utilities/FLTK/src/fl_labeltype.cxx create mode 100644 Utilities/FLTK/src/fl_line_style.cxx create mode 100644 Utilities/FLTK/src/fl_oval_box.cxx create mode 100644 Utilities/FLTK/src/fl_overlay.cxx create mode 100644 Utilities/FLTK/src/fl_overlay_visual.cxx create mode 100644 Utilities/FLTK/src/fl_plastic.cxx create mode 100644 Utilities/FLTK/src/fl_read_image.cxx create mode 100644 Utilities/FLTK/src/fl_read_image_mac.cxx create mode 100644 Utilities/FLTK/src/fl_read_image_win32.cxx create mode 100644 Utilities/FLTK/src/fl_rect.cxx create mode 100644 Utilities/FLTK/src/fl_round_box.cxx create mode 100644 Utilities/FLTK/src/fl_rounded_box.cxx create mode 100644 Utilities/FLTK/src/fl_scroll_area.cxx create mode 100644 Utilities/FLTK/src/fl_set_font.cxx create mode 100644 Utilities/FLTK/src/fl_set_fonts.cxx create mode 100644 Utilities/FLTK/src/fl_set_fonts_mac.cxx create mode 100755 Utilities/FLTK/src/fl_set_fonts_win32.cxx create mode 100644 Utilities/FLTK/src/fl_set_fonts_x.cxx create mode 100644 Utilities/FLTK/src/fl_set_fonts_xft.cxx create mode 100644 Utilities/FLTK/src/fl_shadow_box.cxx create mode 100644 Utilities/FLTK/src/fl_shortcut.cxx create mode 100644 Utilities/FLTK/src/fl_show_colormap.cxx create mode 100644 Utilities/FLTK/src/fl_symbols.cxx create mode 100644 Utilities/FLTK/src/fl_vertex.cxx create mode 100644 Utilities/FLTK/src/flstring.c create mode 100644 Utilities/FLTK/src/flstring.h create mode 100644 Utilities/FLTK/src/forms_bitmap.cxx create mode 100755 Utilities/FLTK/src/forms_compatability.cxx create mode 100644 Utilities/FLTK/src/forms_free.cxx create mode 100644 Utilities/FLTK/src/forms_fselect.cxx create mode 100644 Utilities/FLTK/src/forms_pixmap.cxx create mode 100644 Utilities/FLTK/src/forms_timer.cxx create mode 100644 Utilities/FLTK/src/gl_draw.cxx create mode 100644 Utilities/FLTK/src/gl_start.cxx create mode 100644 Utilities/FLTK/src/glut_compatability.cxx create mode 100644 Utilities/FLTK/src/glut_font.cxx create mode 100644 Utilities/FLTK/src/makefile.wat create mode 100644 Utilities/FLTK/src/mediumarrow.h create mode 100644 Utilities/FLTK/src/new.xbm create mode 100644 Utilities/FLTK/src/ns.xbm create mode 100644 Utilities/FLTK/src/ns_mask.xbm create mode 100644 Utilities/FLTK/src/numericsort.c create mode 100644 Utilities/FLTK/src/scandir.c create mode 100644 Utilities/FLTK/src/scandir_win32.c create mode 100644 Utilities/FLTK/src/screen_xywh.cxx create mode 100644 Utilities/FLTK/src/slowarrow.h create mode 100644 Utilities/FLTK/src/tile.xpm create mode 100644 Utilities/FLTK/src/up.xbm create mode 100644 Utilities/FLTK/src/vsnprintf.c create mode 100644 Utilities/FLTK/zlib/CMakeLists.txt create mode 100644 Utilities/FLTK/zlib/ChangeLog create mode 100644 Utilities/FLTK/zlib/FAQ create mode 100644 Utilities/FLTK/zlib/INDEX create mode 100644 Utilities/FLTK/zlib/Makefile create mode 100644 Utilities/FLTK/zlib/README create mode 100644 Utilities/FLTK/zlib/adler32.c create mode 100644 Utilities/FLTK/zlib/algorithm.txt create mode 100644 Utilities/FLTK/zlib/compress.c create mode 100644 Utilities/FLTK/zlib/crc32.c create mode 100644 Utilities/FLTK/zlib/crc32.h create mode 100644 Utilities/FLTK/zlib/deflate.c create mode 100644 Utilities/FLTK/zlib/deflate.h create mode 100644 Utilities/FLTK/zlib/gzio.c create mode 100644 Utilities/FLTK/zlib/inffast.c create mode 100644 Utilities/FLTK/zlib/inffast.h create mode 100644 Utilities/FLTK/zlib/inffixed.h create mode 100644 Utilities/FLTK/zlib/inflate.c create mode 100644 Utilities/FLTK/zlib/inflate.h create mode 100644 Utilities/FLTK/zlib/inftrees.c create mode 100644 Utilities/FLTK/zlib/inftrees.h create mode 100644 Utilities/FLTK/zlib/makedepend create mode 100644 Utilities/FLTK/zlib/makefile.wat create mode 100644 Utilities/FLTK/zlib/trees.c create mode 100644 Utilities/FLTK/zlib/trees.h create mode 100644 Utilities/FLTK/zlib/uncompr.c create mode 100644 Utilities/FLTK/zlib/zconf.h create mode 100644 Utilities/FLTK/zlib/zlib.3 create mode 100644 Utilities/FLTK/zlib/zlib.h create mode 100644 Utilities/FLTK/zlib/zutil.c create mode 100644 Utilities/FLTK/zlib/zutil.h diff --git a/Utilities/CMakeLists.txt b/Utilities/CMakeLists.txt index 21b76ce5d4..30e92c355c 100755 --- a/Utilities/CMakeLists.txt +++ b/Utilities/CMakeLists.txt @@ -4,6 +4,10 @@ IF(NOT OTB_USE_EXTERNAL_ITK) SUBDIRS( ITK ) ENDIF(NOT OTB_USE_EXTERNAL_ITK) +IF(NOT OTB_USE_EXTERNAL_FLTK) + SUBDIRS( FLTK ) +ENDIF(NOT OTB_USE_EXTERNAL_FLTK) + SUBDIRS(BGL otbsvm dxflib InsightJournal otbossim otb6S otbgeotiff) IF(BUILD_TESTING) diff --git a/Utilities/FLTK/.cvsignore b/Utilities/FLTK/.cvsignore new file mode 100644 index 0000000000..7b7eb8a9dc --- /dev/null +++ b/Utilities/FLTK/.cvsignore @@ -0,0 +1,9 @@ +config.cache +config.h +config.log +config.status +configure +fltk-config +fltk.list +makeinclude +*.bck diff --git a/Utilities/FLTK/ANNOUNCEMENT b/Utilities/FLTK/ANNOUNCEMENT new file mode 100644 index 0000000000..5f67d25c7a --- /dev/null +++ b/Utilities/FLTK/ANNOUNCEMENT @@ -0,0 +1,349 @@ +The FLTK Team is proud to announce the release of FLTK 1.1.7, +a cross-platform C++ GUI toolkit for UNIX(r)/Linux(r) (X11), +Microsoft(r) Windows(r), and MacOS(r) X. FLTK provides +modern GUI functionality without the bloat and supports 3D +graphics via OpenGL(r) and its built-in GLUT emulation. + +FLTK 1.1.7 fixes many bugs, adds some new example programs, and +adds many new improvements to the FLUID software including +multi-level undo, syntax highlighting in all code fields, widget +alignment and sizing guides, dialog templates, widget subclasses, +and printing and testing of user interfaces within FLUID. + +FLTK is provided under the GNU Library Public License with +exceptions that allow for static linking. + +Changes since FLTK 1.1.6 include: + + - Added Fl::screen_count() and Fl::screen_xywh() APIs to + support multi-screen displays. + - Added Greg Ercolano's simple Fl_Input_Choice widget + which is a combination of the Fl_Input and + Fl_Menu_Button widgets (STR #650) + - Added many new FLUID features: syntax highlighting, + multi-level undo, templates, comments, live code view, + live UI test, alignment/sizing guides, printing, and + widget subclassing! + - Documentation fixes (STR #571, STR #648, STR #692, STR + #730, STR #744, STR #745, STR #931, STR #942, STR #960, + STR #969) + - Build system fixes (STR #636, STR #638, STR #645, STR + #724, STR #774, STR #863, STR #893, STR #926, STR #972, + STR #995, STR #996, STR #997, STR #1087, STR #1123) + - fltk-config fixes (STR #840, STR #868, STR #869) + - Threading fixes (STR #1138) + - X11 fixes (STR #711, STR #933, STR #1012) + - MacOS fixes (STR #602, STR #662, STR #765, STR #804, + STR #905, STR #908, STR #968, STR #1099) + - WIN32 fixes (STR #647, STR #726, STR #821, STR #828, + STR #831, STR #848, STR #862, STR #905, STR #961, STR + #968, STR #1007, STR #1019, STR #1079, STR #1104) + - Drawing API fixes (STR #837, STR #924, STR + #1052) + - Filename handling fixes (STR #741, STR #816, STR #854, + STR #874) + - Plastic scheme fixes (STR #769, STR #841, STR #852, STR + #906) + - Image class fixes (STR #632, STR #652, STR #676, STR + #739, STR #825, STR #914, STR #915, STR #918) + - FLUID fixes (STR #668, STR #701, STR #718, STR #742, + STR #776, STR #783, STR #784, STR #790, STR #791, STR + #798, STR #799, STR #850, STR #851, STR #873, STR #879, + STR #891, STR #904, STR #912, STR #959, STR #964, STR + #979, STR #984, STR #999, STR #1129) + - Example program fixes (STR #777, STR #809, STR #843, + STR #867, STR #909) + - Fl_Widget fixes (STR #643, STR #707, STR #860, STR + #910) + - Browser widget fixes (STR #681, STR #729, STR #786, STR + #834, STR #839, STR #967) + - Fl_Chart would draw outside its bounding box (STR #780) + - Fl_Clock_Output::value() did not return the previously + set value (STR #748) + - Fl_File_Chooser fixes (STR #653, STR #654, STR #746, + STR #747, STR #766, STR #770, STR #811, STR #819, STR + #884, STR #958, STR #970) + - Fl_Help_View fixes (STR #631, STR #768, STR #815, STR + #871, STR #998) + - Input widget fixes (STR #727, STR #836, STR #903, STR + #941, STR #981) + - Menu widget fixes (STR #637, STR #651, STR #685, STR + #704, STR #706, STR #740, STR #781, STR #795, STR #973, + STR #1140, STR #1143, STR #1144) + - Fl_Preferences fixes (STR #720, STR #872, STR #1025) + - Fl_Scrollbar didn't compute the correct knob size when + using the "nice" types (STR #845) + - Fl_Tabs fixes (STR #870, STR #882) + - Fl_Text_Display/Editor fixes (STR #635, STR #762, STR + #915, STR #1069, STR #1122) + - Valuator widget fixes (STR #911, STR #971, STR #1037) + - Window widget fixes (STR #641, STR #723, STR #886, STR + #898) + - FL_SHADOW_BOX/FRAME drew outside of the bounding box + (STR #694) + - Fl::delete_widget would hang fl_wait() after deleting the + window (STR #679) + - Fl::event_number() didn't always match the value sent + to the handle() method (STR #634) + - Fl::paste() would sometimes not recoginze external + changes of the clipboard (STR #722) + - Fixed fl_message() code so that it does not get + accidentaly addded to the current group (STR #253) + - The keyboard shortcut handling code did not handle + 8-bit characters properly (STR #731) + +----HTML---- + +<P>The FLTK Team is proud to announce the release of FLTK 1.1.7, +a cross-platform C++ GUI toolkit for UNIX®/Linux® (X11), +Microsoft® Windows®, and MacOS® X. FLTK provides +modern GUI functionality without the bloat and supports 3D +graphics via OpenGL® and its built-in GLUT emulation. + +<P>FLTK 1.1.7 fixes many bugs, adds some new example programs, and +adds many new improvements to the FLUID software including +multi-level undo, syntax highlighting in all code fields, widget +alignment and sizing guides, the ability to create widget +subclasses, and the ability to print and test your user +interfaces within FLUID. + +<P>FLTK is provided under the GNU Library Public License with +exceptions that allow for static linking. + +<P>Changes since FLTK 1.1.6 include: + +<UL> + + <li>Added Fl::screen_count() and Fl::screen_xywh() APIs to + support multi-screen displays.</li> + + <li>Added Greg Ercolano's simple Fl_Input_Choice widget + which is a combination of the Fl_Input and Fl_Menu_Button + widgets (<a href='str.php?L650'>STR #650</a>)</li> + + <li>Added many new FLUID features: syntax highlighting, + multi-level undo, templates, comments, live code view, + live UI test, alignment/sizing guides, printing, and + widget subclassing!</li> + + <li>Documentation fixes (<a href='str.php?L571'>STR + #571</a>, <a href='str.php?L648'>STR #648</a>, <a + href='str.php?L692'>STR #692</a>, <a + href='str.php?L730'>STR #730</a>, <a + href='str.php?L744'>STR #744</a>, <a + href='str.php?L745'>STR #745</a>, <a + href='str.php?L931'>STR #931</a>, <a + href='str.php?L942'>STR #942</a>, <a + href='str.php?L960'>STR #960</a>, <a + href='str.php?L969'>STR #969</a>)</li> + + <li>Build system fixes (<a href='str.php?L636'>STR + #636</a>, <a href='str.php?L638'>STR #638</a>, <a + href='str.php?L645'>STR #645</a>, <a + href='str.php?L724'>STR #724</a>, <a + href='str.php?L774'>STR #774</a>, <a + href='str.php?L863'>STR #863</a>, <a + href='str.php?L893'>STR #893</a>, <a + href='str.php?L926'>STR #926</a>, <a + href='str.php?L972'>STR #972</a>, <a + href='str.php?L995'>STR #995</a>, <a + href='str.php?L996'>STR #996</a>, <a + href='str.php?L997'>STR #997</a>, <a + href='str.php?L1087'>STR #1087</a>, <a + href='str.php?L1123'>STR #1123</a>)</li> + + <li>fltk-config fixes (<a href='str.php?L840'>STR + #840</a>, <a href='str.php?L868'>STR #868</a>, <a + href='str.php?L869'>STR #869</a>)</li> + + <li>Threading fixes (<a href='str.php?L1138'>STR + #1138</a>)</li> + + <li>X11 fixes (<a href='str.php?L711'>STR #711</a>, <a + href='str.php?L933'>STR #933</a>, <a href='str.php?L1012'>STR + #1012</a>)</li> + + <li>MacOS fixes (<a href='str.php?L602'>STR #602</a>, <a + href='str.php?L662'>STR #662</a>, <a + href='str.php?L765'>STR #765</a>, <a + href='str.php?L804'>STR #804</a>, <a + href='str.php?L905'>STR #905</a>, <a + href='str.php?L908'>STR #908</a>, <a + href='str.php?L968'>STR #968</a>, <a + href='str.php?L1099'>STR #1099</a>)</li> + + <li>WIN32 fixes (<a href='str.php?L647'>STR #647</a>, <a + href='str.php?L726'>STR #726</a>, <a + href='str.php?L821'>STR #821</a>, <a + href='str.php?L828'>STR #828</a>, <a + href='str.php?L831'>STR #831</a>, <a + href='str.php?L848'>STR #848</a>, <a + href='str.php?L862'>STR #862</a>, <a + href='str.php?L905'>STR #905</a>, <a + href='str.php?L961'>STR #961</a>, <a + href='str.php?L968'>STR #968</a>, <a + href='str.php?L1007'>STR #1007</a>, <a + href='str.php?L1019'>STR #1019</a>, <a + href='str.php?L1079'>STR #1079</a>, <a + href='str.php?L1104'>STR #1104</a>)</li> + + <li>Drawing API fixes (<a href='str.php?L837'>STR + #837</a>, <a href='str.php?L924'>STR #924</a>, <a + href='str.php?L1052'>STR #1052</a>)</li> + + <li>Filename handling fixes (<a href='str.php?L741'>STR + #741</a>, <a href='str.php?L816'>STR #816</a>, <a + href='str.php?L854'>STR #854</a>, <a + href='str.php?L874'>STR #874</a>)</li> + + <li>Plastic scheme fixes (<a href='str.php?L769'>STR + #769</a>, <a href='str.php?L841'>STR #841</a>, <a + href='str.php?L852'>STR #852</a>, <a + href='str.php?L906'>STR #906</a>)</li> + + <li>Image class fixes (<a href='str.php?L632'>STR + #632</a>, <a href='str.php?L652'>STR #652</a>, <a + href='str.php?L676'>STR #676</a>, <a + href='str.php?L739'>STR #739</a>, <a + href='str.php?L825'>STR #825</a>, <a + href='str.php?L914'>STR #914</a>, <a + href='str.php?L915'>STR #915</a>, <a + href='str.php?L918'>STR #918</a>)</li> + + <li>FLUID fixes (<a href='str.php?L668'>STR #668</a>, <a + href='str.php?L701'>STR #701</a>, <a + href='str.php?L718'>STR #718</a>, <a + href='str.php?L742'>STR #742</a>, <a + href='str.php?L776'>STR #776</a>, <a + href='str.php?L783'>STR #783</a>, <a + href='str.php?L784'>STR #784</a>, <a + href='str.php?L790'>STR #790</a>, <a + href='str.php?L791'>STR #791</a>, <a + href='str.php?L798'>STR #798</a>, <a + href='str.php?L799'>STR #799</a>, <a + href='str.php?L850'>STR #850</a>, <a + href='str.php?L851'>STR #851</a>, <a + href='str.php?L873'>STR #873</a>, <a + href='str.php?L879'>STR #879</a>, <a + href='str.php?L891'>STR #891</a>, <a + href='str.php?L904'>STR #904</a>, <a + href='str.php?L912'>STR #912</a>, <a + href='str.php?L959'>STR #959</a>, <a + href='str.php?L964'>STR #964</a>, <a + href='str.php?L979'>STR #979</a>, <a + href='str.php?L984'>STR #984</a>, <a + href='str.php?L999'>STR #999</a>, <a + href='str.php?L1129'>STR #1129</a>)</li> + + <li>Example program fixes (<a href='str.php?L777'>STR + #777</a>, <a href='str.php?L809'>STR #809</a>, <a + href='str.php?L843'>STR #843</a>, <a + href='str.php?L867'>STR #867</a>, <a + href='str.php?L909'>STR #909</a>)</li> + + <li>Fl_Widget fixes (<a href='str.php?L643'>STR #643</a>, + <a href='str.php?L707'>STR #707</a>, <a + href='str.php?L860'>STR #860</a>, <a + href='str.php?L910'>STR #910</a>)</li> + + <li>Browser widget fixes (<a href='str.php?L681'>STR + #681</a>, <a href='str.php?L729'>STR #729</a>, <a + href='str.php?L786'>STR #786</a>, <a + href='str.php?L834'>STR #834</a>, <a + href='str.php?L839'>STR #839</a>, <a + href='str.php?L967'>STR #967</a>)</li> + + <li>Fl_Chart would draw outside its bounding box (<a + href='str.php?L780'>STR #780</a>)</li> + + <li>Fl_Clock_Output::value() did not return the + previously set value (<a href='str.php?L748'>STR + #748</a>)</li> + + <li>Fl_File_Chooser fixes (<a href='str.php?L653'>STR + #653</a>, <a href='str.php?L654'>STR #654</a>, <a + href='str.php?L746'>STR #746</a>, <a + href='str.php?L747'>STR #747</a>, <a + href='str.php?L766'>STR #766</a>, <a + href='str.php?L770'>STR #770</a>, <a + href='str.php?L811'>STR #811</a>, <a + href='str.php?L819'>STR #819</a>, <a + href='str.php?L884'>STR #884</a>, <a + href='str.php?L958'>STR #958</a>, <a + href='str.php?L970'>STR #970</a>)</li> + + <li>Fl_Help_View fixes (<a href='str.php?L631'>STR + #631</a>, <a href='str.php?L768'>STR #768</a>, <a + href='str.php?L815'>STR #815</a>, <a + href='str.php?L871'>STR #871</a>, <a + href='str.php?L998'>STR #998</a>)</li> + + <li>Input widget fixes (<a href='str.php?L727'>STR + #727</a>, <a href='str.php?L836'>STR #836</a>, <a + href='str.php?L903'>STR #903</a>, <a + href='str.php?L941'>STR #941</a>, <a + href='str.php?L981'>STR #981</a>)</li> + + <li>Menu widget fixes (<a href='str.php?L637'>STR + #637</a>, <a href='str.php?L651'>STR #651</a>, <a + href='str.php?L685'>STR #685</a>, <a + href='str.php?L704'>STR #704</a>, <a + href='str.php?L706'>STR #706</a>, <a + href='str.php?L740'>STR #740</a>, <a + href='str.php?L781'>STR #781</a>, <a + href='str.php?L795'>STR #795</a>, <a + href='str.php?L973'>STR #973</a>, <a + href='str.php?L1140'>STR #1140</a>, <a + href='str.php?L1143'>STR #1143</a>, <a + href='str.php?L1144'>STR #1144</a>)</li> + + <li>Fl_Preferences fixes (<a href='str.php?L720'>STR + #720</a>, <a href='str.php?L872'>STR #872</a>, <a + href='str.php?L1025'>STR #1025</a>)</li> + + <li>Fl_Scrollbar didn't compute the correct knob size + when using the "nice" types (<a href='str.php?L845'>STR + #845</a>)</li> + + <li>Fl_Tabs fixes (<a href='str.php?L870'>STR #870</a>, + <a href='str.php?L882'>STR #882</a>)</li> + + <li>Fl_Text_Display/Editor fixes (<a + href='str.php?L635'>STR #635</a>, <a + href='str.php?L762'>STR #762</a>, <a + href='str.php?L915'>STR #915</a>, <a + href='str.php?L1069'>STR #1069</a>, <a + href='str.php?L1122'>STR #1122</a>)</li> + + <li>Valuator widget fixes (<a href='str.php?L911'>STR + #911</a>, <a href='str.php?L971'>STR #971</a>, <a + href='str.php?L1037'>STR #1037</a>)</li> + + <li>Window widget fixes (<a href='str.php?L641'>STR + #641</a>, <a href='str.php?L723'>STR #723</a>, <a + href='str.php?L886'>STR #886</a>, <a + href='str.php?L898'>STR #898</a>)</li> + + <li>FL_SHADOW_BOX/FRAME drew outside of the bounding box + (<a href='str.php?L694'>STR #694</a>)</li> + + <li>Fl::delete_widget would hang fl_wait() after deleting + the window (<a href='str.php?L679'>STR #679</a>)</li> + + <li>Fl::event_number() didn't always match the value sent + to the handle() method (<a href='str.php?L634'>STR + #634</a>)</li> + + <li>Fl::paste() would sometimes not recoginze external + changes of the clipboard (<a href='str.php?L722'>STR + #722</a>)</li> + + <li>Fixed fl_message() code so that it does not get + accidentaly addded to the current group (<a + href='str.php?L253'>STR #253</a>)</li> + + <li>The keyboard shortcut handling code did not handle + 8-bit characters properly (<a href='str.php?L731'>STR + #731</a>)</li> + +</UL> diff --git a/Utilities/FLTK/CHANGES b/Utilities/FLTK/CHANGES new file mode 100644 index 0000000000..ed0a33e60a --- /dev/null +++ b/Utilities/FLTK/CHANGES @@ -0,0 +1,3049 @@ +CHANGES IN FLTK 1.1.7 + + - Documentation fixes (STR #571, STR #648, STR #692, STR + #730, STR #744, STR #745, STR #931, STR #942, STR #960, + STR #969) + - Various menu widget fixes (STR #1140, STR #1143, STR + #1144) + - The threads demo would display negative prime numbers + on MacOS X; this appears to be a MacOS X bug, but we + added a workaround to "fix" this (STR #1138) + - Fl::dnd() now sets the content type of the drag to + "text/uri-list" when it sees the dragged text is + composed of URIs. + - Fixed keyboard shortcut handling in FLUID and shortcut + labeling in FLTK (STR #1129) + - Fixed include path for CMake build (STR #1123) + - Fixed unnecessary delay in WIN32 event handling + (STR #1104) + - Fixed handling of Ctrl-C in Fl_Text_Display (STR #1122) + - OS X Quartz version now draw a nice resize control (STR + #1099) + - FLTK now enables large file support when available (STR + #1087) + - Fl_Clock_Output depended on a time value that was the + same as an unsigned long, which is incorrect for WIN64 + and VC++ 2005 (STR #1079) + - Fl_Text_Display::wrap_mode() would crash if no buffer + was associated with the widget (STR #1069) + - Updated the default label and text colors of all widgets + to use FL_FOREGROUND_COLOR instead of FL_BLACK (STR + #1052) + - Fl::set_fonts() now works with Xft (STR #1012) + - Fl_Value_Input now uses the screen-absolute position + instead of the window-relative position when dragging + the value; this avoids some jumping conditions (STR + #1037) + - Menus now pop up fully inside the screen if possible + (STR #973) + - Fixed illegal access in Preferences (STR #1025) + - Fixed x-offset problem in Help_Widget (STR #998) + - Clipboard will persist if owner window is hidden (STR + #1019) + - Fixed handling of Win32 Device Contexts (STR #1007) + - Fixed C++ style comments in C files (STR #997) + - Fixed signedness of scanf() argument (STR #996) + - Fixed cross-compiling problem (STR #995). + - FLUID now knows if a static callback is already + declared in a class and won't declare it 'extern' (STR + #776) + - Some actions in FLUID would not set the "changed" flag + (STR #984, STR #999) + - fl_filename_list now always appends a forward slash to + directory names (STR #874) + - Multiline Input will update right if a space character is + inserted in word wrap mode (STR #981) + - FLUID group labels redraw correctly (STR #959) + - FLUID now updates color of Fl_Tabs children (STR #979) + - FLUID now supports 'size_range()' (STR #851) + - FLUID selection boxes now synchronised (STR #964) + - fl_filename_list() now recognizes pathnames without + trailing slash as directions (STR #854) + - Fl_Text_Display now auto-scrolls in all + directions (STR #915) + - Borderless windows will not show in the taskbar anymore + on X11 (STR #933) + - Fixed event_text() field on FL_DND_* event on + OS X and WIN32 (STR #968) + - The fltk-config utility now supports "--cc" and "--cxx" + options to get the C and C++ compilers that were used + to compile FLTK (STR #868) + - Fl_Valuator-derived widgets could show more digits than + were necessary (STR #971) + - Fl_GIF_Image did not handle images with an incorrect + number of data bits (STR #914) + - Fixed some plastic drawing artifacts (STR #906) + - Fl_Help_View now draws the box outside the scrollbars, + like the other scrollable widgets (STR #871) + - The fltk-config script now handles invocation via a + symlink (STR #869) + - Updated WIN32 cut/paste code to consistently handle DOS + text (STR #961) + - Added shared library support for Cygwin and MingW (STR + #893) + - Fl_File_Chooser did not implement the user_data() + methods (STR #970) + - Compilation could fail if a previous installation of + FLTK was in the same (non-standard) directory as an + image library (STR #926) + - Fixed OSX compilation problems with non-HFS filesystems + (STR #972) + - Problems with CMake on MinGW have been solved, thanks + to Mr. "fltk.x0", who submitted the patch. (STR #863) + - Fixed memory leak in Fl_Check_Browser reported by + "miguel2i". (STR #967) + - Fl_File_Input could draw in the wrong window (STR #958) + - WIN32: Internal WM_PAINT message now ignored (STR #831) + - Added Windows support for Fl_Window::xclass() (STR #848) + - Floating point input field allows characters from + current locale (STR #903) + - Fixed integration of Fl_Input_Choice into FLUID (STR + #879) + - New windows touching the right screen border would be + positioned all the way to the left (STR #898) + - Made pie drawing size for WIN32 and OS X the same as + X11 (STR #905) + - Fixed OS X issue with OpenGL windows inside of Tabs + (STR #602) + - FLUID Code Editor would occasionally not draw the last + character in the buffer (STR #798) + - FLUID Declaration private flag fixed (STR #799) + - FLUID overlay now shows a seperate bounding box of + selected items with correct handles and a dotted + boundig box for all labels (STR #790) + - Fixed left overhang of large chracters in Fl_Input_ + (STR #941) + - Fixed button resizing in File Chooser (STR #884) + - Fixed FLUID redraw issue (STR #912) + - Added 32bit BMP Image file format support (STR #918) + - Value Sliders would not receive focus when clicked on + (STR #911) + - Added redraw of some widgets to show focus change (STR + #910) + - Fl::set_font would not clear 'pretty' name (STR #902) + - Fixed unescaped '@' in fonts demo (STR #867) + - FLUID should not open the Display connection anymore if + creating code only (STR #904) + - Improved hidden copy / ctor implementation (STR #860) + - Increased matrix stack depth and added over/underflow + error (STR #924) + - Reverted Mac Carbon Clipping simplification that broke + subwindow clipping (STR #908, SVN r4386) + - Fixed bitmap scaling code + - Fixed tiny memory leak (STR #878) + - Fixed hang on corrupt jpeg (STR #915) + - Fixed static allocation of font buffer in demo (STR #909) + - Added symbols 'refresh', 'reload', 'undo', and 'redo'. + - Fixed focus loss on Fl_Window:resize() + - Fl::delete_widget would hang fl_wait after deleting the + window (STR #679) + - Fl::paste would sometimes not recoginze external + changes of the clipboard (STR #722) + - Clipping fixes for OSX + - Removed attempt to find items via + Fl_Menu_::find_item() in linked submenus + - FLUID interactive window resizing fixes (STR #873, 791) + - FLUID panel resize and alignment fixes (STR #891) + - Fl_Window::show(argc, argv) now sets the scheme before + showing the window; this should eliminate any + flickering between the standard and plastic schemes on + startup (STR #886) + - Selected tabs are now drawn slightly larger than + unselected tabs so they stand out more (STR #882) + - Round Plastic boxes now draw round (STR #841) + - FL_PLASTIC_DOWN_BOX drew with artifacts (STR #852) + - Changed initializations on WIN32 (STR #862) + - Fl_Preferences::getUserdataPath() didn't work for + sub-groups (STR #872) + - Fixed some redraw issues on Windows XP. + - FLUID didn't set the initial size of widgets properly + (STR #850) + - Fl_Tabs would steal focus away from its children on a + window focus change (STR #870) + - filename_relative() now converts the current directory + to forward slashes as needed on WIN32 (STR #816) + - Fl_File_Chooser::value() and ::directory() now handle + paths with backslashes on WIN32 (STR #811) + - Added the standard rgb.txt file from X11 to the test + directory, allowing all platforms to try the colbrowser + demo (STR #843) + - Resizing of OpenGL subwindows was broken on OSX (STR #804) + - The fltk-config script now supports running from a + source directory (STR #840) + - Fl_Browser_ didn't update the position properly when an + item was deleted (STR #839) + - fl_contrast() now compares the luminosity of each color + (STR #837) + - Fl_Input_ crashed on some platforms when wrapping + international text characters (STR #836) + - Fixed some BMP images loading bugs (STR #825) + - Fl_File_Chooser now returns directory names with a + trailing slash to avoid problems with relative + filenames (STR #819) + - Fl_Help_View now supports the FONT and U elements (STR + #815) + - OpenGL windows that were completely off-screen caused + problems with some graphics cards on WIN32 (STR #831) + - Multiple screen support didn't work on Windows NT and + 95 (STR #821) + - Fl_Scrollbar didn't compute the correct knob size when + using the "nice" types (STR #845) + - fl_draw() would segfault on WIN32 if no font was set; + it now uses the default font (STR #828) + - Fl_Browser_ was calling the callback multiple times for + a single selection change with FL_WHEN_CHANGED (STR + #834) + - Added "filenew", "fileopen", "filesave", "filesaveas", + and "fileprint" symbols with standard toolbar + symbology. + - Updated Fl_Tabs to check the contrast of the label + color against the tab background, and to highlight the + top 5 lines of the tab pane with the selection color so + that selected tabs stand out more. + - The example programs can now compile separate from the + FLTK source distribution (STR #809) + - The example programs are now installed with the + documentation (STR #809) + - Fixed the drawing of the Fl_Browser_ selection box (STR + #786) + - Dropped Codewarrier project files and support. + - The FLTK string functions are now compiled in on all + systems (STR #774) + - Fixed symbol demo label bug (STR #777) + - Fixed position of menu titles (STR #795) + - Added missing Fl_Window::copy_label() method. + - Fixed wrong tooltip in fluid (STR #784) + - Added zlib path to fluid (STR #783) + - Menus and other pop-up windows now obey screen + boundaries on multi-screen displays (STR #781) + - Fl_Chart would draw outside its bounding box (STR #780) + - Added Fl::screen_count() and Fl::screen_xywh() APIs to + support multi-screen displays. + - FLUID now supports direct creation of widget classes. + - Fl_File_Chooser now correctly handles multiple + selections that are a mix of files and directories. + - Fl_File_Chooser no longer resets the type() when + choosing a single file, and it now works when selecting + multiple directories (STR #747) + - Fl_File_Icon::load_system_icons() now only loads 16x16 + and 32x32 icon images to improve startup performance. + - Pressing Enter in the file chooser when selecting a + directory will choose that directory if it is currently + shown (STR #746) + - Added a fl_file_chooser_ok_label() function to set the + "OK" button label for the fl_file_chooser() and + fl_dir_chooser() functions. + - Added Fl_File_Chooser::ok_label() methods to set the + "OK" button label. + - The fl_ask() function is now deprecated since it does + not conform to the FLTK Human Interface Guidelines. + - The Fl_File_Chooser window now properly resizes its + controls (STR #766) + - The Fl_Help_Dialog window now properly resizes its + controls (STR #768) + - The Fl_File_Chooser favorites window is now resizable + (STR #770) + - Now provide FL_PLASTIC_ROUND_UP/DOWN_BOX box types + which are used by the plastic scheme. + - FLUID windows that are resized through the widget panel + now remain resizable by the window manager. + - Increased the size of the background image used by + the plastic scheme to reduce the CPU load of redraws + (STR #769) + - Fixed a syntax highlighting bug in the editor demo. + - Fl_Progress now contrasts the label color with the bar + color, so labels will be readable at all times. + - fl_read_image() didn't use the right red, green, and + blue masks on XFree86. + - Fixed Quickdraw drawing of 3 and 4 sided polygons (STR + #765) + - Fixed fl_message() code so that it does not get + accidentaly addded to the current group (STR #253) + - FLUID now highlights code in the widget callback and + code editors. + - FLUID now supports printing of windows. + - Fixed inactive drawing of border, embossed, and + engraved box types. + - Added Fl_Spinner widget (another combination of + existing widgets in a header file) + - FLUID now provides support for UI templates. + - fl_not_clipped() incorrectly used the current window + dimensions for gross clipping, which interfered with + off-screen rendering. + - Fl_Window::draw() and Fl_Window::iconlabel() could leak + memory if copy_label() was used on the window. + - fl_shortcut_label() now shows letter shortcuts in + uppercase, e.g. "Ctrl+N" instead of "Ctrl+n" to be + consistent with other toolkits. + - FLUID now provides unlimited undo/redo support. + - FLUID now provides an option to choose which scheme + (default, none, plastic) to display. + - Fixed scheme background issue with windows in FLUID. + - In FLUID, new widgets are now created with the ideal + size by default, and menu bars are positioned to use + the entire width of the window. + - Added Layout/Widget Size submenu to select default + label and text size (Tiny, Small, and Normal). + - Added Edit/Duplicate command to FLUID to duplicate the + current selection. + - FLUID now tracks the current state of the widget bin + and overlays. + - Now fill the widget image paths with relative + filenames. + - Fixed frame drawing of Fl_Text_Display (STR #762) + - Fl_Clock_Output::value() did not return the previously + set value (STR #748) + - Added comment type to FLUID. This is useful for + generating copyright notices in the source and header + files. + - Fl_Valuator would not format text output with decimal + point when the step value was fractional, but above 1. + - fl_filename_relative() didn't compare drive letters in + a case-insensitive way (STR #741) + - Fixed menu item width calculations with symbols (STR + #740) + - The keyboard shortcut handling code did not handle + 8-bit characters properly (STR #731) + - Fl_JPEG_Image could still crash an app with a corrupt + JPEG file (STR #739) + - Using the layout alignment controls on a menu widget + would cause FLUID to crash (STR #742) + - Added QNX bug workaround for menu handling (STR #704) + - Added Greg Ercolano's simple Fl_Input_Choice widget + which is a combination of the Fl_Input and + Fl_Menu_Button widgets (STR #650) + - Fl_Multiline_Input now scrolls the full height of the + widget instead of 5 lines when the user presses PageUp + or PageDown (STR #727) + - CMake build fixes (STR #724) + - Fl_Browser::swap() didn't handle redraws properly when + the swapped lines had different heights (STR #729) + - FL_MOUSEWHEEL events are now sent first to the widget + under the mouse pointer and then to the first widget + which accepts them. This is similar to the way + shortcut events are handled and is consistent with the + way the mouse wheel is handled by other toolkits. + - Fl::wait() could block on WIN32 if the window was + deleted via Fl::delete_widget() (STR #679) + - Fl_Preferences::RootNode did not find the user's home + directory on some non-US versions of Windows (STR + #720) + - Fl_Window::hide() didn't delete the current clipping + region on WIN32, causing a GDI resource leak in some + situations (STR #723) + - Removed a few warnings when compiling on OS X + - Fl_Menu now draws the arrow more like other toolkits + and 2.0 (STR #651) + - Fixed a VC++ compiler error in Fl_JPEG_Image.cxx (STR + #676) + - FL_SHADOW_BOX/FRAME drew outside of the bounding box + (STR #694) + - Fl_Widget::copy_label(NULL) didn't work (STR #707) + - Fl_Choice now allows click selection like + Fl_Menu_Button and Fl_Menubar (STR #706) + - Updated cmake support (STR #645) + - Fl_Check_Browser didn't draw properly when inactive + (STR #681) + - Removed some redundant code in Fl_Group::handle() (STR + #669) + - The file chooser didn't always deactivate the OK + button when necessary (STR #653) + - Image drawing on OSX changed the current drawing + colors (STR #662) + - Fixed some compiler errors on WIN32 (STR #647, STR + #726) + - FLUID didn't update the widget panel X/Y/W/H values + when moving the selected window (STR #701) + - FLUID didn't use the label type constant names for + menu items, causing them to be drawn using the normal + label type (STR #668) + - Fl_File_Chooser was slow with large directories (STR + #654) + - FLUID didn't add xclass() calls to windows (STR #718) + - The X11 DND code did not correctly select a text + format for incoming data (STR #711) + - Fixes to Fl_JPEG_Image error handler. + - Fl_Menu::popup() and ::pulldown() would crash an + application if a callback created widgets before they + returned (STR #685) + - Fl_Double_Window would cause a full redraw, even if + only small parts of the UI were changed on Mac OS X. + - Fl_JPEG_Image did not correctly handle errors reported + by the JPEG library (STR #652) + - Fl_Menu now draws sub-menu arrows like other toolkits + and FLTK 2.0 (STR #651) + - Fixed a compiler warning in Fl_Window.H (STR #641) + - Tooltips disabled shortcut processing (STR #643) + - Fl::event_number() didn't always match the value sent + to the handle() method (STR #634) + - Fl_Shared_Image::reload() didn't set the image_ + pointer properly in all cases (STR #632) + - Fl_Help_View::topline() incorrectly set the changed() + flag (STR #631) + - Fl_Choice::value() now supports NULL or -1 to deselect + the current item (STR #637) + - More VC++ 6 project file fixes (STR #638) + - Added missing Watcom makefile in the test directory + (STR #636) + - Fl_Text_Display::word_left would hang if the cursor + was at position 0 (STR #635) + + +CHANGES IN FLTK 1.1.6 + + - Documentation updates (STR #552, STR #608) + - Added the 2.0 Fl_Widget::copy_label() method to + allow FLTK 1.x applications to have their label + strings managed by FLTK (STR #630) + - Added Fl::delete_widget() method to safely delete + widgets in callback methods (STR #629) + - Fl_Widget::damage(uchar,int,int,int,int) didn't clip + the bounding box properly (STR #626) + - Windows could appear on the wrong screen on OSX (STR + #628) + - Fl_Double_Window produced an error on resize with X11 + - FLUID didn't display menu items using images properly + (STR #564) + - Fl_Sys_Menu_Bar didn't compile on case-sensitive + file-systems (STR #622) + - FLUID didn't handle default function parameters + properly (STR #579) + - Moving or resizing widgets in FLUID didn't always + update the widget panel (STR #600) + - FLTK windows could appear off-screen on X11 (STR #586) + - The configure script did not support + --disable-localfoo to completely disable image file + support (STR #582) + - The Visual C++ 6.0 project files still listed the old + JPEG, PNG, and ZLIB library names (STR #577) + - Fixed the scandir() conditional code for HP-UX 11i + (STR #585) + - Fl_Text_Display didn't support CTRL/CMD-A/C (STR #601) + - Watcom fixes (STR #581, STR #584, STR #594, STR #595, + STR #623, STR #627) + - Fixed library include order when building DSOs on + MacOS X (STR #596) + - fl_xid() could cause a WIN32 application to crash (STR + #560, STR #576, STR #618) + - Fl_Browser::remove_() removed the item from the list + before computing the item height, which caused + problems with some programs (STR #613) + + +CHANGES IN FLTK 1.1.5 + + - Documentation updates (STR #568, STR #570) + - Shortcuts were incorrectly underlined in multi-line + labels (STR #566) + - More CMake updates (STR #499) + - The Watcom C++ compiler needed a small change (STR + #567) + - Added DESTDIR support and now remove all man pages for + the "uninstall" target (STR #545) + - Fix PNG drawing on buggy WIN32 graphics cards (STR + #548) + - The configure script didn't propagate the CPPFLAGS + environment variable (STR #549) + - The numpad keys didn't work properly on WIN32 (STR + #502) + - fl_input() and friends now set the input focus to the + text field when the dialog is shown (STR #553) + - Fixed background color mixup when drawing Fl_Choice + menus (STR #544) + - Fixed MingW makefiles (STR #550) + - More VC++ project file tweaking (STR #559) + - Fl_PNG_Image didn't use the png_set_trns_to_alpha + function when available (STR #547) + - The FL_UNFOCUS event wasn't always sent when switching + tabs (STR #558) + + +CHANGES IN FLTK 1.1.5rc3 + + - Documentation updates (STR #505, STR #513) + - Updated PNG library source to 1.2.7. + - Updated ZLIB library source to 1.2.1. + - Fixed VC++ project file problems (STR #476, STR #478, + STR #520, STR #527, STR #537) + - Now look for 8 bits of alpha when the developer has + requested FL_RGB8 (STR #541) + - The last line in an Fl_Help_View widget was not + aligned properly (STR #536) + - The "search" symbol looked like a Q (STR #536) + - Changed Fl_Help_View::get_color() to use a lookup + table to avoid serious Borland C++ 5.5 compiler bugs + (STR #533) + - Fixed Watcom compiler warnings with FL/Fl_Widget.H + (STR #540) + - The image class copy() methods did not always make a + separate copy of the image data (STR #539) + - Fixed an edge case in fl_old_shortcut() that could + cause it to read beyond then end of the shortcut + string (used for XForms named shortcuts) + - Added (unsupported) CMake files (STR #499) + - Tooltips would not reappear on the same widget, and + the initial tooltip delay was not used after a tooltip + was shown (STR #465) + - Fixed a compile problem with the Linux 2.6 threading + support (STR #483) + - Fixed problems with 2-byte Xpm files on 64-bit + platforms (STR #525) + - FLTK didn't handle the ReparentNotify event on X11 + (STR #524) + - The old source file "fl_set_gray.cxx" is not needed + (STR #516) + - Fl_Text_Display still called delete[] instead of + free() in one place (STR #503) + - The symbol test program did not handle the @+ symbol + properly (STR #490) + - Fl_File_Chooser didn't correctly call isprint() and + isspace() when checking to see if the current file was + text that can be previewed (STR #517) + - FLUID didn't compile with Borland C++ due to a + compiler bug (STR #496) + - Fl_Positioner did not handle reversed min and max + values (STR #510) + - fl_descent(), fl_height(), and fl_width() would crash + a program if you didn't call fl_font() first; they now + return -1 if no font is set (STR #500) + - Added test/unittests to verify pixel drawing and + alignment across platforms + - Fl_Menu_::find_item() didn't determine the menu path + properly (STR #481) + - The build system now installs image library header + files in FL/images/filename.h so that FLTK programs + will use the same header files as the FLTK image + libraries. + - The build system now creates image libraries named + "libfltk_name.a" instead of "libname.a" to avoid + clobbering an existing installed library (STR #480) + + +CHANGES IN FLTK 1.1.5rc2 + + - Documentation updates (STR #365, STR #399, STR #407, + STR #412, STR #414, STR #452, STR #462) + - Fl_Text_Display did not handle drawing of overlapping + text (italic next to plain, etc.) properly (STR #381) + - All of the core widgets now consistently set changed() + before calling the callback function for a change in + value; this allows programs to check the changed() + state in a callback to see why they are being called + (STR #475) + - Fl_File_Chooser did not handle some cases for filename + completion (STR #376) + - Fl_Help_View didn't properly compute the default + maximum width of the page properly, resulting in + non-wrapped text in table cells (STR #464) + - Fl_Text_Editor no longer tries to emulate the Emacs + CTRL-A shortcut to move to the first column, since + there is a key for that and the widget does not + emulate any other Emacs keys (STR #421) + - Fl_File_Chooser always disabled the OK button when the + user pressed DELETE or BACKSPACE (STR #397) + - Added Fl_Browser::swap() methods (STR #459) + - Fl_Counter didn't use a thin down box for the text + field if the box type was set to FL_THIN_UP_BOX (STR + #467) + - Fl_Help_View now resets the scrollbars if they go + outside the current view (STR #464) + - fl_dir_chooser() did not show the previous selection + as documented (STR #443) + - Fl_Text_Display used delete[] instead of free() in + some places (STR #466) + - FLTK now includes copies of the PNG, JPEG, and ZLIB + libraries for platforms that do not have them (STR + #441) + - The fltk-config script did not include the + "-mno-cygwin" option under CygWin (STR #434) + - Fl_Help_View::find() did not check for a NULL value + (STR #442) + - Added search symbol to the search field of + Fl_Help_Dialog (STR #417) + - Added two new symbols, @search and @FLTK, which can be + used in labels. + - MacOS X: fixed NumLock mixup, added support for + FL_Menu and FL_Delete keys on external (PC) keyboards + (STR #445) + - Fl_File_Icon::draw() did not support drawing of complex + polygons in icon descriptions (STR #474) + - The configure script now offers options for JPEG, PNG, + and ZLIB libraries (STR #416) + - The first menu item in a list would not go invisible + (STR #406) + - Fl_Text_Buffer::replace() now range checks its input + (STR #385) + - FLTK now builds with the current release of MinGW (STR + #325, STR #401, STR #402) + - FLTK now honors the numlock key state (STR #369) + - The Fl_Text_Display widget did not redraw selections + when focus changed (STR #390) + - The plastic background image is now less contrasty + (STR #394) + - Fl_Scroll now uses a full redraw when the scheme is + set to plastic and the box type is a frame (STR #205) + - Fl_Window::resize() did not work properly with KDE 3.2 + (STR #356) + - FLTK didn't delete font bitmaps when the last OpenGL + window was deleted, preventing future text from + displaying (STR #310) + - FLUID didn't include a full initialization record for + the trailing NULL menu items (STR #375) + - Fl_Browser::item_width() did not properly handle + format modifiers (STR #372) + - Fl_Browser::item_height() did not handle columns + properly (STR #371) + - Fl_Gl_Window's on WIN32 now prefer accelerated pixel + formats over generic formats (STR #382) + - Fl_Window::resize() did not work on some systems if + the window was not shown (STR #373) + - FLUID did not write the user_data type if the + user_data field was empty (STR #374) + - The value(const Fl_Menu_Item*) method was not + implemented for Fl_Choice (STR #366) + - Fl_Pack didn't draw child widget labels the same way + as Fl_Group, causing display problems (STR #360) + - fl_read_image() didn't work when reading from an + offscreen buffer with some X11 servers (STR #364) + + +CHANGES IN FLTK 1.1.5rc1 + + - Documentation updates (STR #186, STR #245, STR #250, + STR #277, STR #281, STR #328, STR #338) + - fl_scroll() did not handle scrolling from off-screen on + WIN32 (STR #315) + - Fl_File_Chooser did not allow manual entry of a drive + letter (STR #339) + - Fl_Menu now uses the boxtype to redraw the menu + background (STR #204) + - Fl_Scroll now shows the background image when a framed + box type is used and the Fl_Scroll is a direct + decendent of a window (STR #205) + - Added a new_directory_tooltip string pointer to allow + localization of the file chooser's new directory + button (STR #340) + - Added Fl_Menu_::find_item() method (STR #316) + - The Fl_Widget copy operator definitions were not + conditionally compiled properly (STR #329) + - FLUID's Layout functionality did not move child + widgets when laying out group widgets (STR #319) + - FLUID's Layout->Center In Group functionality did not + properly handle widgets that were children of a + Fl_Window widget (STR #318) + - The Fl_Text_Display destructor did not remove the + predelete callback associated with the current buffer + (STR #332) + - Fixed several bugs in the MacOS X Fl::add_fd() + handling (STR #333, STR #337) + - The Fl_Text_Display widget did not display selections + set by the application (STR #322) + - FLUID crashed if you did layout with a window widget + (STR #317) + - Fl_Scroll::clear() didn't remove the child widget from + the Fl_Scroll widget (STR #327) + - Fl_Value_Slider::draw_bg() didn't always apply the + clipping rectangle (STR #235) + - fl_filename_relative() returned the wrong string if + the absolute pathname was equal to the current working + directory (STR #224) + - Fl_Help_Dialog didn't correctly restore the scroll + position when going forward/back in the link history + if the file changed (STR #218) + - glutGetModifiers() did not mask off extra state bits, + confusing some GLUT-based applications (STR #213) + - Fixed mouse capture problems on MacOS X (STR #209, STR + #229) + - Fl_Sys_Menu_Bar is now built into the library for + MacOS X (STR #229) + - Fl_Menu_ now provides item_pathname() methods to get + the "pathname" of a menu item, e.g. "File/Quit" (STR + #283) + - Fl_Text_Display now provides cursor_color() methods to + get and set the cursor color (STR #271) + - Fl_Scroll didn't honor FL_NO_BOX (STR #305) + - FLUID declaration blocks didn't support public/private + definitions (STR #301) + - Fl_Preferences incorrectly created the preferences + directory before necessary (STR #247) + - The WIN32 project files still defined the (obsolete) + FL_STATIC constant (STR #279) + - Fl_Text_Display::buffer() did not support NULL values, + making it impossible to clean up text buffers from a + subclass (STR #295) + - Fl_Text_Display did not support a NULL + unfinishedStyleCB function (STR #241) + - Fl::background2() incorrectly marked the foreground + color as initialized (STR #255) + - Fixed the X11 CTRL + "-" detection code to properly + track the state of the CTRL key (STR #264) + - Fl_File_Icon::load_system_icons() didn't support KDE + 3.x (STR #299) + - WIN32's scandir() emulation did not allocate enough + memory for directory names (STR #263) + - Fl::compose() did not handle special keys like + backspace properly (STR #293) + - Fl_Choice did not clip its text when drawing using the + plastic scheme (STR #287) + - Fl_Group incorrectly mapped the emacs CTRL keys to + keyboard navigation (STR #228) + - Fl_File_Browser::load() didn't handle a NULL directory + name (STR #266) + - 64-bit library fixes (STR #261) + - The Fl_Valuator::format() function did not limit the + size of the number buffer (STR #268) + - The keypad Enter key works as the normal Enter/Return + key in common widgets (STR #191) + - Fixed some OS/2-specific build problems (STR #185, STR + #197) + - Calling Fl_Text_Display::buffer() with the same buffer + would cause an application to lockup (STR #196) + - Some of the widgets could crash an application if the + cursor was changed after a window was deleted (STR + #181) + - The Fl_Gl_Window WIN32 pixel format code did not + choose the pixel format with the largest depth buffer + (STR #175) + - The configure script didn't leave space between the + CFLAGS/CXXFLAGS and X_CFLAGS variables (STR #174) + - The Fl_JPEG_Image and Fl_PNG_Image classes did not + trap errors from the corresponding image libraries + (STR #168) + - Added "--with-links" configure option to control + whether symlinks are created for the FLTK header files + (STR #164) + - Added new hoverdelay() to Fl_Tooltip to control how + quickly recent tooltips appear (STR #126) + - FLUID now sets the size range when a window is shown. + This seems to be necessary with some window managers + (STR #166) + + +CHANGES IN FLTK 1.1.4 + + - The fl_read_image() function was not implemented on + OSX (STR #161) + - VC++ 7.1 didn't like how the copy operators were + disabled for the Fl_Widget class; now include inline + code which will never be used but makes VC++ happy + (STR #156) + - Fixed an IRIX compile problem caused by a missing + #include (STR #157) + - FLUID didn't write color/selection_color() calls using + the symbolic names when possible, nor did it cast + integer colors to Fl_Color (STR #146) + - Fl_File_Chooser was very close for multiple file + selection in large directories (STR #140) + - Fl_Text_Display/Editor did not disable the current + selection when focus was shifted to another widget + (STR #131) + - Fl_Choice didn't use the normal focus box when the + plastic scheme was in use (STR #129) + - Fl_Text_Editor didn't use selection_color() + consistently (STR #130) + - The fltk_forms, fltk_gl, and fltk_images DSO's and + HP-UX shared libraries are now linked against the fltk + shared library to provide complete dependency + resolution (STR #118) + - The configure.in file did not work with autoconf 2.57. + - FLUID didn't redraw widgets when changing the X, Y, W, + or H values in the widget panel (STR #120) + - Fl_Window::show(argc, argv) wasn't calling + Fl::get_system_colors() as documented (STR #119) + - DSO (shared library) building wasn't quite right for + some platforms (STR #118) + - OSX: some changes to make ProjectBuilder compiles + possible. + - OSX: FLTK would not know where a window was positioned + by the OS. As a result, popup menus could open at + wrong positions. + + +CHANGES IN FLTK 1.1.4rc2 + + - Fl_Window::show(argc,argv) incorrectly opened the + display prior to parsing the arguments; this prevented + the "-display foo" option from working (STR #111) + - Images were not clipped properly on MacOS X (STR #114) + - Fl::reload_scheme() and Fl::scheme("foo") incorrectly + called Fl::get_system_colors(). This prevented an + application from setting its own color preferences + (STR #115) + - The 'Enter' key event on OS X would not set + Fl::e_text. + - Changed behaviour of fluid to always paste into + a selected group (STR #88) + - Menuitem now changes font, even if fontsize + is not set (STR #110) + - Swapped shortcut labels in OS X (STR #86) + - Non-square Fl_Dial would calculate angle from user + input wrong (STR #101) + - Updated documentatiopn of fl_draw (STR #94) + and Fl_Menu_::add() (STR #99) + - FLUID collapse triangle events were not offset by + horizontal scroll (STR #106) + - QuitAppleEvent now correctly returns from Fl::run() + instead of just exiting (STR #87) + - Hiding the first created OpenGL context was not + possible. FLTK now manages a list of contexts (STR #77) + - FLUID didn't keep the double/single buffer type for + windows. + - FLTK didn't work with Xft2. + - OSX window resizing didn't work (STR #64) + - Fixed MacOS X shared library generation (STR #51) + - Several widgets defined their own size() method but + didn't provide an inline method that mapped to the + Fl_Widget::size() method (STR #62) + - Fl_Scroll didn't provide its own clear() method, so + calling clear() on a Fl_Scroll widget would also + destroy the scrollbars (STR #75) + - Fl::event_text() was sometimes initialized to NULL + instead of an empty string (STR #70) + - fl_draw() didn't properly handle a trailing escaped + "@" character (STR #84) + - Added documentation for all forms of + Fl_Widget::damage() (STR #61) + - Fl_Double_Window now has a type() value of + FL_DOUBLE_WINDOW, to allow double-buffered windows to + process redraws properly on WIN32 (STR #46) + - Added FL_DAMAGE_USER1 and FL_DAMAGE_USER2 damage bits + for use by widget developers (STR #57) + - Fl_Help_View didn't support numeric character entities + (STR #66) + - Menu shortcuts didn't use the Mac key names under + MacOS X (STR #71) + - CodeWarrior Mac OS X updated to work with current + CW8.3 (STR #34) + - Apple-C/X/V/Z didn't work in the Fl_Input widget due + to a bad mapping to control keys (STR #79) + - Added the OSX-specific fl_open_callback() function to + handle Open Documents messages from the Finder (STR + #80) + - The configure script contained erroneous whitespace in + various tests which caused errors on some platforms + (STR #60) + - The fltk-config script still supported the deprecated + --prefix and --exec-prefix options; dropped them since + they serve no useful purpose and would never have + worked for the intended purpose anyways... (STR #56) + - fl_filename_list returned 0 on Win32 if no directory + existed (STR #54) + - Pressing 'home' after the last letter in a Text_Editor + would move the cursor to pos 0 (STR #39) + - Fl::get_key(x) would mix up Ctrl and Meta on OS X (STR + #55) + - The configure script used the wrong dynamic library + linking command for OSX (STR #51) + - The Fl_Text_Editor widget did not set changed() nor + did it call the widget's callback function for + FL_WHEN_CHANGED when processing characters that + Fl::compose() handles (STR #52) + + +CHANGES IN FLTK 1.1.4rc1 + + - The file chooser did not reset the click count when + changing directories; if you clicked on a file in the + same position after changing directories with a + double-click, the chooser treated it as a triple + click (STR #27) + - Symbols with outlines did not get drawn inactive. + - The Fl_Help_View widget now provides a find() method + to search for text within the page. + - The Fl_Help_Dialog widget now provides a search box + for entering text to search for. + - The default font encoding on OSX did not match the + default on WIN32 or X11. + - Menu items were not drawn using the font specified in + the Fl_Menu_Item structure (STR #30) + - Long menus that were aligned such that the top of an + item was exactly at the top of the screen would not + scroll (STR #33) + - The OS issues appendix incorrectly stated that MacOS + 8.6 and 9 were supported; they are not (STR #28) + - Fixed handling of nested double-buffered windows (STR + #1) + - Showing a subwindow inside a hidden window would crash + the application (STR #23) + - OSX users couldn't enter some special chars when using + some foreign key layouts (STR #32) + - Hiding subwindows on OSX would hide the parent window + (STR #22) + - Added thin plastic box types. + - Fl_Pack ignored the box() setting and cleared any + unused areas to the widget color; it now only does so + if the box() is set to something other than FL_NO_BOX. + - Updated the Fl_Tabs widget to offset the first tab by + the box dx value to avoid visual errors. + - Updated the plastic up box to draw only a single + border frame instead of the old double one for + improved appearance. + - Updated the default background color on OSX to provide + better contrast. + - Fl_Text_Display and friends now look for the next + non-punctuation/space character for word boundaries + (STR #26) + - gl_font() didn't work properly for X11 when Xft was + used (STR #12) + - Fl_File_Browser incorrectly included "." on WIN32 (STR + #9) + - Include shellapi.h instead of ShellAPI.h in the WIN32 + drag-n-drop code in order to work with the MingW cross + compiler (STR #6) + - The cursor was not properly restored when doing + drag-n-drop on X11 (STR #4) + - Fl::remove_fd() didn't recalculate the highest file + descriptor properly (STR #20) + - Fl_Preferences::deleteGroup() didn't work properly + (STR #13) + - Fixed the fl_show_file_selector() function - it was + copying using the wrong string size (STR #14) + - fl_font() and fl_size() were not implemented on MacOS + X. + - Sorted the icon menu bar in fluid. + - Fixed minor memory access complaints from Valgrind + - Compiling src/flstring.h on OS X with BSD header would + fail. + - Fl_Text_Editor didn't scroll the buffer when the user + pressed Ctrl+End or Ctrl+Home. + - Fl_Text_Editor didn't show its cursor when the mouse + was moved inside the window. + - FLUID now uses an Fl_Text_Display widget for command + output, which allows you to copy and paste text from + command output into other windows. + - Fl_Gl_Window could cause a bus error on MacOS X if the + parent window was not yet shown. + - FLUID could crash after displaying a syntax error + dialog for the callback code. + - FLUID would reset the callback code if you opened the + widget panel for multiple widgets. + - Added a NULL check to Fl_Text_Display (SF Bug #706921). + - The fltk-config script placed the LDFLAGS at the wrong + place in the linker options. + - Fl_Text_Display didn't draw the outer box in the right + dimensions, so it was invisible. + - Fl_Help_Dialog used the same color for links as for + the background, causing links to be invisible on pages + without a background color set. + + +CHANGES IN FLTK 1.1.3 + + - Documentation updates. + - FLTK now ignores KeyRelease events when X11 sends them + for repeating keys. + - FLUID now supports up to two additional qualifiers + before a class name (FL_EXPORT, etc.) to aide in + developing DLL interfaces for WIN32. + - Additional NULL checks in Fl_Button, + fl_draw_boxtype(), Fl_File_Chooser, and + Fl_Window::hotspot(). + - The Fl_Preferences header file needed to FL_EXPORT all + of the nested classes for WIN32. + - Fl_Double_Window couldn't be nested on WIN32. [SF Bug + #658219] + - Fl_Slider didn't call the callback function when the + user changed the value using the keyboard and the + "when" condition was FL_WHEN_RELEASE. [SF Bug #647072] + - Lines with less than 2 unique vertices and polygons + with less the 3 unique vertices were not drawn + properly. [SF Bug #647067] + - The size_range() values were not honored under MacOS + X. [SF Bug #647074] + - OpenGL windows didn't resize correctly on MacOS X. + [SF Bug #667855] + - The menus incorrectly used the overlay visual when one + or more menu items contained an image. [SF Bug #653846] + - Changed some error messages to use Fl::error() instead + of fprintf()... + - Fl_Text_Buffer and Fl_Text_Display used free to free + memory that was allocated using the new operator. + - Tweeked the plastic scheme under MacOSX to better + match the colors. + - The Fl_Image.H always included the x.H header file, + which included many system headers that could + interfere with normal GUI applications. It now uses + the corresponding based types for the image id and + mask to avoid this. + - The FLUID widget panel wasn't sorted, so keyboard + navigation was strange. [SF Bug #647069] + - Fl_Scroll didn't compute the location of labels to the + right or below when determining the area to erase. + - Added backward-compatibility macro for + filename_setext(). + - Fl_Bitmap::copy(), Fl_Pixmap::copy(), and + Fl_RGB_Image::copy() all could overflow the source + image when scaling the image. + - Double/triple clicks in Fl_Input fields didn't copy + the expanded selection to the clipboard. + - Fl_Glut_Window and Fl_Gl_Window didn't always initialize + the OpenGL context on MacOS. + + +CHANGES IN FLTK 1.1.2 + + - Fl_Menu_Bar now supports drawing vertical dividers + between menu items and submenus in the menu bar. + - Fl_File_Chooser::value() didn't return NULL when the + user clicked Cancel while selecting a directory. This + bug also affected fl_dir_chooser(). + - Fl_Menu_::add(const char *) used too small a menu item + label buffer and didn't do bounds checking. + - Eliminate some compiler warnings with CodeWarrier + under WIN32 (Paul Chambers) + - Fl_Gl_Window widgets did not resize properly under + MacOS X. + - The cursor could be set for the wrong window in the + text widgets. + - Fl_Check_Browser didn't provide const char * add + methods as documented. + - Fl_Check_Browser didn't draw the same style of check + marks at the other widgets. + - Fl_Button, Fl_Choice, and Fl_Menu_Button incorrectly + activated the button/menu when the spacebar was + pressed in conjunction with shift, control, alt, or + meta. + - FLTK should now compile with Xft 2.0. + - Some versions of Tru64 4.0 have snprintf and + vnsprintf, but don't have the prototypes for those + functions. + - FLTK had trouble doing character composition with some + keyboard layouts under X11 (in particular, Belgian). + - Fl_Text_Editor would cause a segfault if the user + pressed CTRL-V (paste) without having any data in the + clipboard... + - The tab key moved backwards in menus instead of + forwards. Shift-tab still moves backwards. + - The redraw_label() method didn't damage the parent + window when the label was outside the widget's + bounding box. + - Added a "draw_children()" method to Fl_Group to make + subclassing Fl_Group with a custom draw() function + easier. + - Fl_Text_Editor now supports basic undo functionality. + - FLUID now uses Fl_Text_Editor widgets for all + multi-line code fields. + - Added new widget bin and icons to FLUID. + - FLUID would try running multiple commands in parallel, + even though it wasn't capable of handling it. + - FLUID didn't generate code for some attributes when + using custom/named widget classes. + - Added a new FL_COMMAND state bit which maps to FL_CTRL + on X11 and WIN32 and FL_META on MacOS. + - MacOS keyboard modifiers mapping corrections. Cmd and + Control are no longer swapped, event_key and event_text + return (mostly) the same values as on other platforms. + - The Fl_Tabs widget should no longer be a focus hog; + previously it would take focus from child widgets. + - The file chooser now activates the OK button when + opening a directory in directory selection mode. + - Fixed a bug in the file chooser when entering an + absolute path. + - Back-ported some FLTK 2.0 tooltip changes to eliminate + erroneous tooltip display. + - MacOS windows were resizable, even when size_range + would not allow for resizing. + - Fl_Text_Editor now supports Shift+Delete, Ctrl+Insert, + and Shift+Insert for cut, copy, and paste, + respectively. + - Fl_Text_Display didn't restore the mouse pointer when + hidden. + - Fl::arg() now ignores the MacOS X -psn_N_NNNNN option. + - Added another change to the WIN32 redraw handling for + the MingW compilers. + - Fl_File_Chooser didn't handle WIN32 home directories + that used backslashes instead of forward slashes. + - Fl_Text_Display didn't limit the resize height to 1 + line. + - Fl_Scrollbar widgets incorrectly took keyboard focus + when clicked on. This caused widgets such as + Fl_Text_Display to hide the cursor when you scrolled + the text. + + +CHANGES IN FLTK 1.1.1 + + - Fl_Text_Display didn't always show the cursor. + - Fl_Tabs now only redraws the tabs themselves when + making focus changes. This reduces flicker in tabbed + interfaces. + - The WIN32 redraw handler now correctly merges the FLTK + and Windows redraw regions. + - The Fl_Text_* widgets use the C++ bool type, which is + not supported by older C++ compilers. Added a + configure check and workaround code for this. + - Fl_X::set_xid() didn't initialize the backbuffer_bad + element that was used with XDBE. + - Fl_Shared_Image::uncache() was not implemented. + - Fl::set_font() didn't 0-initialize all font descriptor + data. + - Some OpenGL implementations don't support single- + buffered visuals. The Fl_Gl_Window class now emulates + single-buffered windows using double-buffered + windows. + - Added a workaround for a compiler bug in Borland C++ + that prevented Fl_Help_View.cxx from compiling. + - Checkmarks didn't scale properly; copied the 2.0 check + mark code over. + - Replaced several memcpy's with memmove's for + portability (memmove allows for overlapping copies, + memcpy does not) + - Bug #621737: Fl_Bitmap::copy(), Fl_Pixmap::copy(), and + Fl_RGB_Image::copy() now range-check the new width and + height to make sure they are positive integers. + - Bug #621740: the WIN32 port needed to handle WM_MOUSELEAVE events + in order to avoid problems with tooltips. + - Fl_PNM_Image didn't set the "alloc" flag for the data, + which could lead to a memory leak. + - fl_filename_match() was inconsistently doing case- + insensitive matching. + - Fl_Button redraw fix for bug #620979 (focus boxes and + check buttons). + - Fl_Text_Display fix for bug #620633 (crash on + redisplay). + - Fl_Output now calls its callback when the user clicks + or drags in the widget. + - Shortcuts now cause buttons to take focus when visible + focus is enabled. + - fl_filename_relative() didn't check that the path was + absolute under WIN32. + - fl_filename_relative() didn't check that the path was + on the current drive under WIN32. + - The Fl_BMP_Image class now handles 16-bit BMP files + and BMP files with a transparency mask. + - The fltk-config script didn't add the required include + path, if any, when compiling a program. + - Added a license clarification that the FLTK manual is + covered by the same license as FLTK itself. + - Fl_Check_Browser wasn't documented. + - Fl_Preferences::Node::addChild(), deleteEntry(), and + remove() didn't set the "dirty" flag. + - The "no change" button didn't work in the FLUID widget + panel. + - Vertical scrollbars did not draw the arrows inactive + when the scrollbar was inactive. + + +CHANGES IN FLTK 1.1.0 + + - Documentation updates. + - Added a Fl_Widget::redraw_label() method which flags a + redraw of the appropriate area. This helps to + eliminate flicker when updating the value of a widget. + - Fl_Wizard::value() now resets the mouse cursor to the + window's default cursor. + - Fl_File_Chooser::type() didn't enable/disable the new + directory button correctly. + - Fl_Preferences::entryExists() did not work properly. + - FLUID's image file chooser pattern was incorrect. + - Fl_File_Icon::load_system_icons() now detects KDE + icons in /opt/kde, /usr/local, and /usr automatically, + and supports the KDEDIR environment variable as well. + - Submenus now display to the left of the parent menu if + they won't fit to the right. Previously they would + display right on top of the parent menu... + - Fl_Menu_:add() didn't handle a trailing "\" character + gracefully. + - Clicking/dragging the middle mouse button in a + scrollbar now moves directly to that scroll position, + matching the behavior of other toolkits. + - Added some more range checking to the Fl_Text_Display + widget. + - The editor demo did not correctly update the style + (syntax highlighting) information. + + +CHANGES IN FLTK 1.1.0rc7 + + - Updated the Fl_Text_Buffer and Fl_Text_Display classes + to be based on NEdit 5.3 (patch from George Garvey). + - Fixed a problem with Fl::wait(0.0) on MacOS X 10.2; + this affected the fractals demo and other OpenGL + applications. + - Fl_Glut_Window now takes keyboard focus and handles + shortcut events. + - The MacOS X implementation of fl_ready() now checks + the event queue for events. + - Fl_PNM_Image now supports the XV/GIMP thumbnail format + (P7). + - Fl_Preferences would not find groups inside the root + group. + - Small bug fixes for Fl_Chart, Fl_Scrollbar, Fl_Tabs, + and FLUID from Matthew Morrise. + - Fl_Chart didn't have its own destructor, so data in + the chart wasn't freed. + - Fl_Menu_Button no longer responds to focus or keyboard + events when box() is FL_NO_BOX. + - FLTK convenience dialogs put the buttons in the wrong + order. + - Fl_BMP_Image didn't load 4-bit BMP files properly. + - Minor tweeks to the WIN32 DLL support. + - Fl_Text_Display::resize() could go into an infinite + loop if the buffer is emptied. + - Fl::handle() didn't pass FL_RELEASE events to the + grab() widget if pushed() was set (for proper menu + handling...) + - DND events were being sent to the target window + instead of the target widget under WIN32. + - The newest Cygwin needs the same scandir() handling as + HP-UX. + - FLUID didn't register the image formats in the + fltk_images library, and had some other image + management problems. + - Fixed one more redraw bug in Fl_Browser_ where we + weren't using the box function to erase empty space in + the list. + - Fl_Text_Display::buffer() now calls resize() to show + the buffer. + - Fl_Help_View didn't support HTML comments. + - Fl_Help_View didn't include the extra cellpadding when + handling colspan attributes in cells. + - Fl_Help_View didn't support table alignment. + + +CHANGES IN FLTK 1.1.0rc6 + + - Documentation updates. + - Fl::handle() didn't apply the modal tests for + FL_RELEASE events, which caused Fl_Tabs to allow users + to change tabs even when a modal window was open. + - Fl_Browser_, Fl_Input_, Fl_Slider now use the box + function to erase the background. This fixes some + long-standing redraw problems. + - More snprintf/strlcpy/strlcat changes where needed. + - Fl::get_font_name() would leak 128 bytes. + - Eliminated most of the "shadowed" variables to avoid + potential problems with using the wrong copy of "foo" + in a class method. + - Moved Fl_BMP_Image, Fl_GIF_Image, and Fl_PNM_Image to + the fltk_images library, so the only image formats + that are supported by the core library are XBM and XPM + files. This reduces the size of the FLTK core library + by about 16k... + - The Fl_Text_Display::resize() method was incorrectly + flagged as protected. + - Fixed some memory/initialization bugs in + Fl_File_Chooser that valgrind caught. + - The PNG library png_read_destroy() is deprecated and + does not free all of the memory allocated by + png_create_read_struct(). This caused a memory leak in + FLTK apps that loaded PNG images. + - Added uncache() method to Fl_Image and friends. + - Added image() methods to Fl_Menu_Item. + - Added default_cursor() method and data to Fl_Window. + - Fl_Group would send FL_ENTER events before FL_LEAVE + events, causing problems with adjacent widgets. + - Fixed filename problems with Fl_File_Chooser - + changing the filename field directly or choosing files + from the root directory could yield interesting + filenames. + - Fl_Input_ could crash if it received an empty paste + event. + - The mouse pointer now changes to the I beam + (FL_CURSOR_INSERT) when moved over an input field or + text widget. + - "make install" didn't automatically (re)compile the + FLUID executable. + - Added an Fl::get_boxtype() method to get the current + drawing function for a specific box type. + - Fl_Output and Fl_Multiline_Output didn't prevent + middle-mouse pastes. + - Fl_JPEG_Image didn't compile out-of-the-box with Cygwin + due to a bug in the Cygwin JPEG library headers. + - Fl_BMP_Image still didn't work with some old BMP files. + - "make distclean" didn't really clean out everything. + - Tweeked the look of the check button with a patch from + Albrecht Schlosser. + + +CHANGES IN FLTK 1.1.0rc5 + + - Added "wrap" type bit to Fl_Input_, so you can now + have a multiline text field that wraps text. + - Setting the value() of an output text field no longer + selects the text in it. + - Output text fields now show a caret for the cursor + instead of the vertical bar. + - The newButton and previewButton widgets are now public + members of the Fl_File_Chooser class. This allows + developers to disable or hide the "new directory" and + "preview" buttons as desired. + - Added new visible focus flag bit and methods to + Fl_Widget, so it is now possible to do both global and + per-widget keyboard focus control. + - Removed extra 3 pixel border around input fields. + - No longer quote characters from 0x80 to 0x9f in input + fields. + - Improved speed of Fl_Browser_::display() method with + large lists (patch from Stephen Davies.) + - Fl_Help_View didn't properly handle NULL from the link + callback (the original filename/directory name were + not preserved...) + - Fl_Help_View didn't use the boxtype border values when + clipping the page that was displayed. + - Added first steps to CodeWarrior/OS_X support (see + fltk-1.1.x/CodeWarrior/OS_X.sit) + - Cleaned up the WIN32 export definitions for some of + the widget classes. + - Fixed a filename completion bug when changing + directories. + - Fl_File_Chooser::value() would return directories with + a trailing slash, but would not accept a directory + without a trailing slash. + - When installing shared libraries, FLUID is now linked + against the shared libraries. + - MacOS: missing compile rule for .dylib files. + - Fl_Group::current(), Fl_Group::begin(), and + Fl_Group::end() are no longer inlined so that they are + properly exported in DLLs under WIN32. Similar + changes for all static inline methods in other + classes. + - MacOS: support for Mac system menu (Fl_Sys_Menu_Bar) + - MacOS: wait(0) would not handle all pending events + - Added new makeinclude file for MingW using GCC 3.1.x. + - Fl_Choice::value(n) didn't range check "n". + - The MingW and OS/2 makeinclude files didn't have the + new fltk_images library definitions. + - Fl_Text_Editor didn't scroll the text in the widget + when dragging text. + - Config header file changes for Borland C++. + - FLTK didn't provide a Fl::remove_handler() method. + + +CHANGES IN FLTK 1.1.0rc4 + + - Added new filter_value() methods to Fl_File_Chooser to + get and set the current file filters. + - Added support for custom filters to Fl_File_Chooser. + - Added Borland C++ Builder IDE project files from + Alexey Parshin. + - Resource leak fixes under WIN32 from Ori Berger. + - Now register a WIN32 message for thread messages. + - Fl_Window didn't initialize the min and max window + size fields. + - The JPEG and PNG image classes have been moved to the + fltk_images library, a la FLTK 2.0. You can register + all image file formats provided in fltk_images using + the new fl_register_images() function. + - Fl_XBM_Image didn't correctly load XBM files. + - MacOS: Added Greg Ercolano's file descriptor support. + - MacOS: Fixed text width bug. + - A change in fl_fix_focus() broken click-focus in FLWM. + - Cygwin with -mnocygwin didn't like the FL/math.h + header file. + - Fl_Browser_ cleared the click count unnecessarily. + - MacOS: Pixmap draw fix, gl_font implemented + FL_FOCUS fix, window type fix for modal and nonmodal + windows, glut uninitialised 'display' proc fix + - Now support FLTK_1_0_COMPAT symbol to define + compatibility macros for the old FLTK 1.0.x function + names to the 1.1.x names. + - Now translate the window coordinates when a window is + shown, moved, or resized. This should fix the "menus + showing up at the wrong position" bug under XFree86. + - Fixed some more problems with the Fl_BMP_Image file + loader. + - BC++ fixes. + - The pixmap_browser demo didn't check for a NULL image + pointer. + - Fl_File_Icon::find() now uses fl_filename_isdir() + under WIN32 to check for directories. + - Fl_File_Chooser's preview code called refcount() + on the deleted image's object. + - Fixed another problem with the Fl_BMP_Image loader. + - The fl_file_chooser() callback was being called with a + NULL filename. + - Documented that fl_push_clip() is preferred over + fl_clip(), with a corresponding source change. + - Minor changes to the MacOS X event handling code. + - Added syntax highlighting example code to the editor + test program. + - Fl_Text_Display didn't range check style buffer + values. + - Added "dark" color constants (FL_DARK_RED, etc.) + - The MacOS font code was missing definitions for + fl_font_ and fl_size_. + + +CHANGES IN FLTK 1.1.0rc3 + + - Documentation updates. + - New file chooser from design contest. + - Did some testing with Valgrind and fixed some memory + problems in Fl_Help_View::Fl_HelpView, + Fl_Menu_::remove(), Fl_Text_Display::draw_vline(), and + resizeform() (convenience dialogs). + - Fixed some redraw() bugs, and now redraw portions of + the parent widget when the label appears outside the + widget. + - The boolean (char) value methods in Fl_Preferences + have been removed since some C++ compilers can't + handle char and int value methods with the same name. + - Added fl_read_image() function. + - Fixed Fl_Valuator::format() so that the correct format + type is used when step == 1.0. + - Fl_Help_View didn't support the TT markup. + - Fl_Shared_Image used a double-pointer to the image + handler functions, which was unnecessary and + unintuitive. + - Fl_PNM_Image didn't load the height of the image + properly. + - Fl_BMP_Image, Fl_JPEG_Image, Fl_PNG_Image, and + Fl_Shared_Image didn't delete image data that was + allocated. + - Enabled the OpenGL and threads demos when compiling + for MingW. + - Fl_File_Input didn't update the directory buttons if a + callback was registered with the widget. + - The file chooser would return the last selected + file(s) when cancel was pressed. + - The file chooser limited the resizing of the chooser + window unnecessarily. + - Fixed WM_PAINT handling under WIN32. + - Minor tweeks to MingW and OS/2 config headers. + - Fl_Value_Input now correctly determines if step() + specifies an integer value. + - Fl_Help_View didn't add links inside PRE elements. + - OS/2 build fixes from Alexander Mai. + - Now use strlcat() instead of strncat() which could + cause buffer overflows. + - Now use of strlcpy() instead of strncpy() to simplify + the code. + - Drag-n-drop under WIN32 now shows a [+] cursor instead + of the link cursor. + - Fixed widget width tooltip and default argument + handling code in FLUID. + - Fixed colors used when drawing antialiased text using + Xft. + - Fl_Preferences::makePath() now uses access() instead + of stat() when checking to see if the destination + directory already exists. + - Fl_BMP_Image now supports older BMP files with the 12 + byte header. + - Optimized the redrawing of tabs and radio/check + buttons when the keyboard focus changes. + - More tooltip fixes. + - DND text operations would loop under X11. + + +CHANGES IN FLTK 1.1.0rc2 + + - Portability fixes. + - Backported 2.0 tooltip changes. + - Several of the valuators did not support tooltips. + - The last menu item in a menu didn't pick up on font + changes. + - FLUID now properly handles default argument parameters + properly. + - Fixed WM_PAINT handling under WIN32 - didn't validate + the correct region that was drawn. + - Fl_Multiline_Output would insert the enter key. + - Fl_File_Browser didn't clip items to the column width. + - Fl_Window::draw() cleared the window label but didn't + restore it, so windows could lose their titles. + - Eliminated multiple definitions of dirent structure + when compiling under WIN32. + - Adjusted the size of the circle that is drawn inside + radio buttons to scale better for larger labels. + - FLUID was opening the display when it shouldn't have. + - Fl_File_Chooser.cxx defined the file chooser functions + again; they should only be defined in the header file. + - Wide arcs would draw with "teeth". + - The preferences demo included Fl/Fl_Preferences.H + instead of FL/Fl_Preferences.H. + + +CHANGES IN FLTK 1.1.0rc1 + + - The fl_file_chooser() and fl_dir_chooser() functions + now support an optional "relative" argument to get + relative pathnames; the default is to return absolute + pathnames. + - The backspace and delete keys now work as expected in + the file chooser when doing filename completion. + - FLUID now supports running shell commands. + - New Fl_File_Input widget that shows directory + separators with filename in input field. + - The Fl_File_Chooser dialog now shows the absolute path + in the filename field using the Fl_File_Input widget. + - FLUID now keeps track of grid, tooltip, and other + GUI options, along with the last 10 files opened. + - Tooltip windows would show up in the task bar under + WIN32. + - Now append trailing slash to directory names in names + in WIN32 version of scandir(). This takes care of a + file chooser performance problem with large + directories. + - Added Fl_Preferences class from Matthias Melcher, + including binary data support. + - FLUID now recognizes the "using" keyword in + declarations. + - fl_file_chooser() didn't highlight the requested file + the second time the file chooser dialog was shown. + - Fixed rendering of Fl_Light_Button with the plastic + scheme. + - Fixed a bug in the MacOS font enumeration code. + - Now show a "locked" icon next to static/private + elements in FLUID, and "unlocked" icon next to + global/public elements. + - Implemented Fl_Menu_Item image labels using older + 1.0.x labeltype method. + - Updated the PNG library check to support both png.h + and libpng/png.h. + - Fixed a recursion bug in tooltips that was causing + random crashes. + - fl_file_chooser() could cause a segfault when passed a + NULL filename parameter in some situations. + - Added a "-g" option to fltk-config to support quick + compiling with debugging enabled. + - Fixed redraw problem with Fl_Input and anti-aliased + text. + - Added threading support for MacOS X and Darwin. + - The filesystem list in the file chooser now works under + MacOS X and Darwin. + - The fl_msg structure now contains all data passed to + the WndProc function under WIN32. + - Fixed some window focus/positioning problems under + MacOS X. + - Added fl_create_alphamask() function to create an alpha + mask from 8-bit data; currently this always generates a + 1-bit screen-door bitmask, however in the future it will + allow us to generate N-bit masks as needed by various + OS's. + - Fl_File_Browser::load() didn't properly show drives + when compiled in Cygwin mode. + - Now pass correctly pass keyboard and mouse events to + widget under tooltip as needed... + - Added new Fl::dnd_text_ops() methods to enable/disable + drag-and-drop text operations. + - Fl_Input now supports clicking inside a selection to + set the new text position when drag-and-drop is + enabled. + - Added support of X resources for scheme, dnd_text_ops, + tooltips, and visible_focus... + - Fixed some case problems in includes for the MacOS X + code. + - Fl_Widget::handle() returned 1 for FL_ENTER and + FL_LEAVE events, which caused some compatibility + problems with 1.0 code. + - Fl_Box::handle() now returns 1 for FL_ENTER and + FL_LEAVE events so that tooltips will work with Fl_Box + widgets. + - Some source files still defined strcasecmp and + strncasecmp under WIN32. + - Some source files still used the "false" and "true" + C++ keywords, even though several of our "supported" + C++ compilers don't support them. Using 0 and 1 until + FLTK 2.0 (which uses the bool type instead of int for + any boolean values...) + - Minor Fl_Color revamping, so that color constants map + to the color cube and FL_FOREGROUND_COLOR, + FL_BACKGROUND_COLOR, FL_BACKGROUND2_COLOR, + FL_INACTIVE_COLOR, and FL_SELECTION_COLOR map to the + user-defined colors. + + +CHANGES IN FLTK 1.1.0b13 + + - Fixed a bug in the Xft support in Fl_Window::hide() + (the config header wasn't included, so the Xft code + wasn't getting called) + - Xdbe support must now be enabled explicitly using + --enable-xdbe due to inconsistent bugs in XFree86 and + others. + - Windows resized by a program would revert to their + original size when moved under WIN32. + - Cygwin can only compile the new WIN32 drag-n-drop code + using GCC 3.x. + - Tooltips now appear for inactive and output widgets. + - Tooltips no longer steal keyboard events other than + ESCape. + - Tooltips are no longer delayed when moving between + adjacent widgets. + - fl_beep(FL_BEEP_DEFAULT) now uses the PC speaker under + Windows (0xFFFFFFFF) rather than an event sound. + - The configure script didn't include the -mwindows or + -DWIN32 compiler options in the output of fltk-config + when using the Cygwin tools. + - Fl_Output didn't take input focus when needed, so it + was unable to support CTRL-C for copying text in the + field and did not unhighlight selections when the + widget lost focus. + - The fl_filename_name() function didn't handle a NULL + input string. + - The input field used by the fl_input() and + fl_password() functions was resized too small in + 1.1.0b12. + - Added casts in fl_set_fonts_win32.cxx for VC++ 5.0. + - Fl_File_Icon::find() did not check the basename of a + filename for a match; this caused matches for a + specific filename (e.g. "fluid") to fail. + - The Fl_Shared_Image class now supports additional + image handling functions - this allows you to support + additional image file formats transparently. + + +CHANGES IN FLTK 1.1.0b12 + + - Documentation updates. + - Fl_Choice didn't clip the current value properly - it + wasn't accounting for the box border width. + - The forms compatibility functions are now placed in a + "fltk_forms" library to match FLTK 2.0. + - Renamed down() and frame() to fl_down() and + fl_frame(), filename_xyz() to fl_filename_xyz(), and + all of the define_FL_FOO() functions for the custom + boxtypes to fl_define_FL_FOO() to avoid namespace + clashes. + - Stereo OpenGL support (patch from Stuart Levy) + - All of the convenience functions defined in fl_ask.H + now resize the widgets and dialog window as needed for + the labels and prompt. + - Backported FLTK 2.0 dual cut/paste buffer code. + - Added support for Xft library to provide anti-aliased + text on X11. + - Fl_Help_View didn't keep track of the background color + of cells properly. + - Fl_Browser::item_width() didn't compute the width of + the item properly when column_widths() was set. + - Fl_Button didn't check to see if the widget could + accept focus before taking input focus. + - Fl_Help_View didn't preserve target names (e.g. + "filename.html#target") when following links. + - Drag-and-drop support for MacOS. + - Updated MacOS issues documentation. + + +CHANGES IN FLTK 1.1.0b11 + + - Now conditionally use the WIN32 TrackMouseEvent API + (default is no...) + - Fixed a table rendering bug in the Fl_Help_View + widget. + - The fltk-config script now recognizes all common C++ + extensions. + - The menu code was using overlay visuals when the + scheme was set to "plastic". + - Fixed some drawing problems with Fl_Light_Button and + its subclasses. + - Fixed a minor event propagation bug in Fl_Group that + caused mousewheel events to be passed to scrollbars + that were not visible. + - The fl_file_chooser() function did not preserve the + old file/directory like the old file chooser did. + - The prototypes for fl_input() and fl_password() did + not default the "default value" to NULL. + - Fl_Tabs now draws tabs using the selection_color() of + the child groups; this allows the tabs to be colored + separately from the body. Selected tabs are a mix of + the Fl_Tabs selection_color() and the child group's + selection_color(). + - Fl_Tabs didn't include images in the measurement of + the tabs if no label text was defined. + - The WIN32 code didn't return 0 from the window + procedure after handling WM_PAINT messages. + - fl_draw() would incorrectly test the clipping of + labels the lay outside the bounding box. + - filename_relative() didn't always return the correct + relative path. + - Updated the test makefile to work with more versions + of "make". + - Added new "--with-optim" configure option to set the + optimization flags to use when compiling FLTK. + - The fltk-config script no longer reports the + optimization flags that were used to compile FLTK. + - Initial port of FLTK 2.0 drag-and-drop support. + + +CHANGES IN FLTK 1.1.0b10 + + - Fixed the new WIN32 TrackMouseEvent code. + - Fixed the VC++ project files to link against + comctl32.lib. + + +CHANGES IN FLTK 1.1.0b9 + + - Better FL_LEAVE event handling for WIN32. + - The alpha mask was bit-reversed. + - Fl::scheme() applied the scheme tile image to overlay + and menu windows, which caused problems when the + overlay planes were in use. + - Fixed Fl::event_button() value when hiding tooltip on + some systems. + - Added Fl_BMP_Image class to support loading of Windows + bitmap (BMP) files. + - The shiny demo didn't work on some systems (no + single-buffered OpenGL visual), and the new box types + were reset when show(argc, argv) was called. + - Fl::scheme() didn't update windows that were not + shown. + - The fractals demo would get far ahead of the UI with + some Linux OpenGL drivers. Now use glFinish() instead + of glFlush() so we are at most 1 frame ahead. + - The fractals demo Y axis controls were backwards for + the "flying" mode. + - MacOS: cleaned up src/Fl_mac.cxx + - MacOS: fixed Fl::wait(0.0), fixed Cmd-Q handling + - Update CygWin support for Fl::add_fd(). + - Update the plastic scheme to not override the default + colors - move the color code to the MacOS-specific + code. Also updates the tile image colormap to match + the current background color. + - Add fl_parse_color() to X11 as well, removing a bunch + of conditional code and providing a common interface + for looking up color values. + - Fixed the make problems in the test directory - some + make programs had trouble handling the recursive + dependencies on the FLUID files... + - Now use rint() to round floating-point coordinates. + - Demo cleanup - made sure they all worked with schemes. + - Fl_Tabs no longer clears the unused area of the tab + bar. + - Added show(argc, argv) method to Fl_Help_Dialog. + - MacOS: implemented cut/copy/paste. + - MacOS: improved keyboard handling, fixed keyboard + focus handling, fixed get_key, modified 'keyboard' + demo to show second mouse wheel and additional keys + 'help' and FL_NK+'=' + + +CHANGES IN FLTK 1.1.0b8 + + - OS/2 build fixes. + - fl_draw() didn't ignore symbol escapes properly for + the browsers... + - New Fl::scheme() methods from FLTK 2.0; currently only + the standard ("") and plastic ("plastic") methods are + supported. Schemes can be set on the command-line + ("-scheme plastic") or using the FLTK_SCHEME + environment variable. + - MacOS: fixed iBook keyboard handling, moved + remaining message handling to Carbon, added mouse + capture support, added timer support, added overlay + support, fixed double-buffering side effects. + - The configure script wasn't using the -fpermissive or + -fno-exceptions options with GCC. + - Fl_JPEG_Image and friends didn't set the depth if the + image file couldn't be loaded; since Fl_RGB_Image + didn't check for this, it could fail when displaying + or copying these images. + - filename_absolute() did not always free its temporary + buffer. + - filename_relative() did not do a case-insensitive + comparison under MacOS, OS/2, and Windows. + - filename_isdir() didn't properly handle "D:L" under + WIN32. + - Fl_Shared_Image::get() did not check to see if the + image could not be loaded. + - Fl_Help_View didn't clear the line array in the + Fl_Help_Block structure; this causes erratic + formatting for some pages. + - The font and size members of Fl_Help_Block were never + used. + - The threading functions (Fl::lock() and friends) were + not exported under WIN32. + - The Fl_Text_Display destructor deleted the scrollbars + twice... + - Fl_Help_View didn't reset the horizontal scroll + position when showing a new page. + - Fl_Pack now allows any child widget to be the + resizable() widget, not just the last one. + - MacOS: opaque window resizing, all events except + Mac menus are now handled using Carbon, window + activation fixed, GL_SWAP_TYPE default changed to + make gl_overlay work. + - Fl_Help_View::resize() didn't resize the horizontal + scrollbar. + - MacOS: list all fonts, fixed clipping and mouse + pointer bugs. + - The Fl_File_Chooser widget now uses hotspot() to + position the dialog under the mouse pointer prior to + showing it. + - Added a configure check for *BSD - use -pthread option + instead of -lpthread. + - Fl_Text_Display could get in an infinite loop when + redrawing a portion of the screen. Added a check for + the return value from fl_clip_box() so that the + correct bounding box is used. + - Removed the Fl_Mutex and Fl_Signal_Mutex classes from + the threads example, since they weren't being used + and apparently are not very portable. + - Fl_Help_View now ignores links when the link callback + returns NULL, and displays a sensible error message + when an unhandled URI scheme is used (e.g. http:, + ftp:) + - Fl_File_Icon::load_system_icons() no longer complains + about missing icon files, just files that exist but + can't be loaded. + - FLUID didn't list the plastic box and frame types. + - Now hide the tooltip window whenever a window is + hidden. Otherwise a tooltip window could keep an + application running. + - Updated FLUID to only append a trailing semicolon to + code lines in a callback (so "#include" and friends + will work...) + - The Fl_Color_Chooser widget now supports keyboard + navigation. + - Fixed button and valuator widgets to call Fl::focus() + instead of take_focus(). + - Tweeked the radio button drawing code for better + circles with different boxtypes. + - The Fl_File_Chooser widget did not provide a shown() + method, and fl_file_chooser() and fl_dir_chooser() did + not wait on shown(); this would cause them to return + prematurely if you switched desktops/workspaces. + - Cosmetic changes to plastic boxtypes. Now look much + better for large areas and the buttons now have a much + greater "3D" feeling to them. + - Added new Fl::draw_box_active() method so that + boxtypes can find out if the widget they are drawing + for is active or not. + - Fl_Button and its subclasses did not redraw the parent + when the boxtype was FL_NO_BOX and they lost keyboard + focus (the parent redraw clears the focus box.) + - Fixed the example program makefile - wasn't building + the mandelbrot and shiny demos right. + - Fl::set_font(Fl_Font, Fl_Font) was not implemented. + - Fixed the documentation Makefile commands; was not + using the fltk.book file for some reason... + + +CHANGES IN FLTK 1.1.0b7 + + - More documentation updates... + - Mac OS X support works 95% + - The Fl_Window::hotspot() off-screen avoidance code was + commented out. + - Mac OS X uses mostly Carbon event handling to support + Mousewheel, three buttons, all modifier keys, etc. + - Updated paragraph 4 of the FLTK license exceptions; + there was some question about the requirement to show + that a program uses FLTK, which is required by section + 6 of the LGPL. The new exemption specifies that + inclusion of the FLTK license is not required, just a + statement that the program uses FLTK. + - Fl_Button::handle() was calling take_focus() for both + FL_PUSH and FL_DRAG. + - File and memory fixes for Fl_GIF_Image, Fl_PNG_Image, + Fl_PNM_Image, Fl_Shared_Image, Fl_Tiled_Image, and + Fl_XBM_Image. + - filename_match() didn't handle backslashes properly + under WIN32, and didn't use a case-insensitive + comparison under MacOS X. + - The Fl class was missing access methods for the + FL_MOUSEWHEEL event values - Fl::event_dx() and + Fl::event_dy(). + - The default help string didn't include the -nokbd + option. + - "make uninstall" didn't uninstall the static OpenGL + widget library. + - Mac cursor shapes added... + - Fl_Text_Display would lockup when all text was + deleted; for example, when running the editor + demo, you couldn't load a second file. + - Added Fl::lock() and friends from FLTK 2.0 to + support multi-threaded applications; see the + "threads" demo for an example of this. + - Fl_Check_Button and Fl_Round_Button now use the + FL_NO_BOX box type to show the background of the + parent widget. + - Tweeked the plastic boxtype code to draw with the + right shading for narrow, but horizontal buttons. + - Fl_Progress now shades the bounding box instead of + drawing a polygon inside it. + - Fl::warning() under WIN32 defaults to no action. This + avoids warning dialogs when an image file cannot be + loaded. + - Some Win32 drivers would draw into wrong buffers + after OpenGL mode change + - The file chooser would cause a segfault if you + clicked in an empty area of the file list. + - Fl_File_Icon::labeltype() would cause a segfault + if the value pointer was NULL. + - Fl_File_Icon::load_image() could cause segfaults + (NULL data and incrementing the data pointer too + often.) + - Fl_File_Icon::load_image() now handles 2-byte + per color XPM files. + - Some Win32 drivers would draw into wrong buffers + after OpenGL mode change. + - Message handling and Resources for MacOS port. + - Fl_Help_View could get in an infinitely loop when + determining the maximum width of the page; this + was due to a bug in the get_length() method with + percentages (100% width would cause the bug.) + - Don't need -lgdi32 for CygWin, since -mwindows + does this for us. + - The WIN32 event handler did not properly handle + WM_SYNCPAINT messages. + - Fl_Tabs now uses the boxtype exclusively to draw + both the tabs and surrounding box, so alternate + box types actually work and the look is a little + nicer. + - Fixed the drawing of large areas with the new + plastic boxtypes. + - Updated the Visual C++ demo projects to use fluid + to generate the GUI files as needed. + - The demo program didn't load the right menu file + when compiled for debugging under WIN32. + - Added plastic box types to forms demo. + - Added mousewheel to keyboard demo. + - The Fl_Text_Editor widget caused an infinite loop + when it received keyboard focus. + - filename_isdir() didn't properly handle drive letters + properly; WIN32 needs a trailing slash for drive + letters by themselves, but cannot have a trailing + slash for directory names, go figure... + - The Fl_Text_Buffer and Fl_Text_Display classes did not + initialize all of their members. + - fl_normal_label() had a totally redundant set of + if/else tests, which the new code handles all from + fl_draw(). + - The Fl_File_Chooser dialog contained two hotspots. + - The fl_draw_pixmap() function didn't free the 2-byte + color lookup table properly (delete instead of + delete[]). + - fl_draw() reset the text color under WIN32, causing + bitmaps to draw incorrectly. + - Fl::get_font_sizes() is now implemented under WIN32. + - Fl_Text_Display now uses the same default colors for + selection and text as Fl_Input_ and friends. + - Changed the default line scrolling in Fl_Text_Display + to 3 lines for the mouse wheel and scrollbar arrows. + + +CHANGES IN FLTK 1.1.0b6 + + - Documentation updates... + - The configure script now works within the CygWin + environment. + - Tooltips are now enabled by default, but are not + re-enabled when calling the Fl_Widget::tooltip() + method. + - Added new Fl::version() method to get the current + FLTK library version (for shared libraries/DLLs) + - Added new Fl::event() method to get the current + event that is being processed. + - Added new fl_beep() function to do audible + notifications of various types. + - Added new Fl_GIF_Image, Fl_JPEG_Image, Fl_PNG_Image, + Fl_PNM_Image, Fl_XBM_Image, and Fl_XPM_Image classes. + - Added new Fl_Shared_Image class, a la FLTK 2.0. + - Added new Fl_Tiled_Image class for tiled backgrounds. + - Added new copy(), desaturate(), inactive(), and + color_average() methods to the Fl_Image classes. + - Added a horizontal scrollbar to the Fl_Help_View + widget. + - Added new FL_PLASTIC_{UP/DOWN}_{BOX/FRAME} boxtypes + for a more "modern" look (sort of a cross between KDE + 2.2 and Aqua.) + - Fl_Float_Input and Fl_Int_Input no longer accept + pasted text that is not a floating point or integer + value. Pasted numbers now replace text in these + widgets. + - Implemented the Fl_File_Icon::load_png() method. + - The Fl_File_Icon::load_system_icons() method now + supports KDE 2.x icons. + - Fixed PNG support in Fl_Help_View. + - Removed the "Microsoft" mode button from the menubar + demo. + - The browser demo now makes sure that the input field + contains a number. + - The Fl_Browser::make_visible() method now range checks + the input. + - Updated the fl_draw() and fl_measure() methods to + accept an optional draw_symbols argument, which + controls whether symbols are drawn in the text. + - Added new Fl::visible_focus() methods to control + whether the focus box is drawn. + - The focus box is now drawn using the contrast color. + - Fl_Repeat_Button didn't accept keyboard focus. + - Added new Fl::visible_focus() method and standard + "-kbd" and "-nokbd" options in Fl::args() processing + to control whether keyboard focus is shown and handled + by non-text widgets. + - The wrong tooltip could be shown if the user moved the + mouse over adjacent widgets with tooltips. + - The drop-down button on Fl_Choice widgets was not + limited in width. + - Tooltips could appear off the screen. + - Mouse wheel events are now sent to the focus widget + first, then to any other interested widget. + - The Fl_RGB_Image class now supports images with an + alpha channel. Images are currently drawn using + "screen door" transparency... See the "image" demo + for an example. + - Added new fl_create_bitmask() and fl_delete_bitmask() + functions that create bitmap objects for masking and + bitmap drawing. + - Was sending FL_RELEASE events for buttons 4 and 5 + under X11, which are only for FL_MOUSEWHEEL. + - Fl_Help_View now supports the EM and STRONG elements. + - Didn't do callbacks when changing tabs via keyboard. + - FLUID didn't write tooltip strings to the message + catalog file. + - Fl_File_Icon now uses Fl_Shared_Image to load icon + images; the load_png() and load_xpm() methods have + been replaced by a single load_image() method. + - Fl_File_Icon::load_system_icons() now does a better + job of finding KDE icons. + - Now use Fl::warning() and Fl::error() in place of + printf's in some of the newer widgets. + - The default behavior of Fl::error() is now to display + an error but not to exit; Fl::fatal() still exits. + - FLUID now uses the Fl_Shared_Image class, so FLUID- + generated GUIs can embed any of the supported image + file formats. + - New filename_relative() function to convert an + absolute filename to a relative one. + - Updated the filename_absolute(), filename_expand(), + and filename_setext() functions to take the + destination string size, with inline functions for the + old FL_PATH_MAX size. + - fl_file_chooser() and fl_dir_chooser() now return a + relative path. + - Fl_Help_View now supports all ampersand escapes. + + +CHANGES IN FLTK 1.1.0b5 + + **** NOTE: DUE TO CHANGES IN THE WIDGET CLASSES, **** + **** YOU MUST RECOMPILE ALL SOURCE FILES **** + **** THAT USE FLTK!!! **** + + - All FLTK color values are now 32-bits and support + both the legacy 8-bit color values as well as 24-bit + RGB values (0xRRGGBB00 for 24-bit RGB, 0x000000II + for indexed color). + - Fl::set_boxtype() and fl_internal_boxtype() now keep + track of when a boxtype is changed; this allows you to + override the "special" boxtypes without references to + those boxtypes causing them to be reset. + - Fl_Help_Func now takes a Fl_Widget pointer as well as + a pathname. + - Added code to support FL_KEYUP events. + - Focus did not return to the Fl_Text_Display and Editor + widgets when scrolling and then clicking inside the + editor window. + - Now set the line size of the vertical scrollbar in the + text editor to 1. + - The symbols demo didn't show the strings needed to + show the corresponding symbol (the label string was + not quoted...) + - FLTK should now compile with Cygwin cleanly. + - Shortcut changes were not being saved by FLUID. + - FLUID didn't write the deimage() static data. + + +CHANGES IN FLTK 1.1.0b4 + + **** NOTE: DUE TO CHANGES IN THE FL_WIDGET CLASS, **** + **** YOU MUST RECOMPILE ALL SOURCE FILES **** + **** THAT USE FLTK!!! **** + + - Updated the flags_ member of Fl_Widget to be an + integer instead of uchar, to support the new + FL_OVERRIDE flag for Fl_Window. + + - The parent() method of Fl_Widget now uses pointers to + Fl_Group instead of Fl_Widget. + + - Fl_Window now provides the FLTK 2.0 "override()" and + "set_override()" methods for windows. + + - Added a configure check (and warning) for GCC 3.0.x. + + - Updated the configure script to check for the + png_set_tRNS_to_alpha() function. + + - Updated the config.h files for all platforms for the + image and FLTK documentation defines. + + - Updated the makeinclude files for all platforms to + match the current makeinclude.in file. + + - FLUID would crash if you cleared an image for a + widget. + + - Fl_Help_View::add_image() did not initialize the image + member of the base (unscaled) image. + + - Fl_Help_View didn't support A elements with both a + NAME and HREF attribute - the HREF was ignored. + + - Miscellaneous compile warning fixes. + + - Tooltips were being reset by Fl::belowmouse(), which + caused problems with the FLUID main window (flashing + tooltip windows and serious problems with KDE 2.2) + + - The editor demo had the save and discard button + actions reversed. + + - The Fl_Help_View widget now uses + png_destroy_read_struct() if the older + png_read_destroy() function is not available. + + - The WIN32 DLL library now includes the OpenGL widgets. + This is a simpler solution for the export/import + dillemma under WIN32, as OpenGL and non-OpenGL symbols + need to be exported at different times with the + separate library scheme. Since OpenGL is standard + under Windows, this is less of a problem than under + UNIX... + + +CHANGES IN FLTK 1.1.0b3 + + - The top-level makefile did not include the makeinclude + file, causing the fltk-config installation commands to + fail. + + - The fl_file_chooser.cxx source file conflicted with + Fl_File_Chooser.cxx under Windows. Similarly, the + fl_file_chooser.H header file conflicts with the + Fl_File_Chooser.H header file. + + - Now save and restore the GDI pen object when + responding to WIN32 paint messages. + + - Documentation updates from A. Suatoni. + + +CHANGES IN FLTK 1.1.0b2 + + - New fltk-config script. + + - Fixed image/text label handling; in b1 the label + needed a non-blank text string to display the image. + This bug also caused all sorts of crashes and display + problems. + + - Added new filetype() method to Fl_FileBrowser to allow + for file or directory browsing. + + - Fixed the drawing of the focus box around + Fl_Return_Button. + + - Fixed menu item measurement bug (wasn't initializing + image pointers to 0...) + + - Radio and checkbox menu items now draw with the new + style (round radio buttons with dots and square check + buttons with check marks.) + + - Improved the appearance of Fl_Check_Button. + + - Improved the Fl_HelpView table formatting code; now + dynamically sizes the table columns, and supports + COLSPAN. + + - The FLUID keyboard shortcuts now work as expected + (CTRL-C copies, SHIFT-CTRL-C writes code, etc.) + + - The FLTK_DOCDIR environment variable can now be + used to tell FLUID where to find the on-line + documentation files. + + - FLUID now supports image labels in addition to text + labels + text over image alignment. + + - FLUID now supports tooltips. + + - The widget panel in FLUID is now tabbed, a la FLTK + 2.0. + + - The FLUID pixmap destructor tried to free 1 too many + lines of image data. + + - FLUID now provides on-line help. + + - Changed Fl_FileXYZ to Fl_File_XYZ. + + - Changed Fl_HelpXYZ to Fl_Help_XYZ. + + - Tooltip fixes for Fl_Browser_, Fl_Choice, and Fl_Input_. + + - Added tooltips to FLUID, help dialog, and file chooser. + + - Now load system icons in FLUID. + + +CHANGES IN FLTK 1.1.0b1 + + - Added new image() and deimage() methods to support + image + text labels more easily. + + - Added new alignment bit FL_ALIGN_TEXT_OVER_IMAGE. + + - Added tooltip support using Jacques Tremblay's tooltip + patch. + + - Added keyboard navigation to all widgets. + + - Added support for mouse wheels using the new + FL_MOUSEWHEEL event type. Get the mouse wheel + movement values from Fl::e_dx (horizontal) and + Fl::e_dy (vertical). + + - Added the Fl_Check_Browser, Fl_FileBrowser, + Fl_FileChooser, Fl_FileIcon, Fl_HelpDialog, + Fl_HelpView, Fl_Progress, and Fl_Wizard widgets from + the bazaar. + + - Added 2.0 Fl_Text_Display and Fl_Text_Editor widgets + based on NEdit. + + - The Fl_Choice widget now looks more line a combo box + than a Motif option menu. + + - Moved the OpenGL widgets into a separate library + called fltkgl - this eliminates shared library + dependencies on OpenGL when no OpenGL functionality is + used/required. + + - FLUID now supports the new Fl_CheckBrowser, + Fl_FileBrowser, Fl_FileIcon, Fl_HelpView, + Fl_Text_Display, Fl_Text_Editor, and Fl_Wizard + widgets. + + - Updated configure stuff to support shared libraries + under AIX (link to -lfltk_s) + + - Symbol labels can now contain regular text. + + - FLUID now supports relative filenames for the source + and header files you generate. + + - Fl_Menu_Item::add() didn't use the flags that were + passed in. + + - Fixed a bug in Fl_Scrollbar - clicking in the "trough" + of the scrollbar would move the scroller in the wrong + direction. + + - Made the Forms pixmap parameter const to match the + Fl_Pixmap.H definitions. + + - Changed the Fl_Pixmap constructor to use the explicit + keyword which should work for all C++ compilers. + + - Fl_Menu_add of a menu item with the same name as an + existing submenu title would mess up by replacing that + menu title, it now adds a new item. + + - Fl_Menu::add() of text starting with '/' to a menu is + assummed to be a filename. So "/foo/bar" creates a + single menu item. You can also put filenames into + submenus by doing "submenu//foo/bar", this will create + a submenu called "submenu" with an item "/foo/bar". + Menu items starting with "\_" will insert an item + starting with '_' rather than a divider line. These + changes make the menus compatable with fltk 2.0. + + - Another little fix for the BoXX OpenGL overlays. + + - Fl_Gl_Window no longer blanks the mouse pointer on + WIN32 unless an OpenGL overlay is being used. This + should make non-overlay displays faster when a cursor + is set. + + +CHANGES SINCE FLTK 1.0.10 + + - CHANGED THE DEFAULT RUN-TIME LINKING TO "MULTITHREADED + DLL". You'll need to change your project settings to + use this as well or you'll get errors. + + - Added new --disable-gl option to configure script. + + - Added new const const pointer versions of pixmap + functions to eliminate an annoying pointer warning + message that was generated by the Sun and other C++ + compilers. + + - Eliminated all "var hides class::var" warnings. + + - Eliminated all "string literal converted to char *" + warnings. + + - OS/2 updates from Alexander Mai. + + - Tidied up the HTML documentation to be more standards + compliant. + + - Compiling with -DBOXX_BUGS will work around some + problems with the newest X drivers that BoXX delivers, + the problems all affect use of Overlays for normal X + drawing and OpenGL drawing. Normal compilation is + unchanged. + + - The file chooser buttons use user_data() rather than + the label to decide what to do, allowing the label to + be somewhat cleaner. + + - Selection color on X changed to blue, to match what + happens on Windows now. + + - Added support for AIX (static library only). + + - Added support for SunOS 4.x + + - Now process WIN32 WM_ACTIVATEAPP message to reset the + key and button states in Fl::e_state. + + - Fl_has_idle only tested N-1 callbacks and missed one. + + - Restored WM_SYNCPAINT handling under WIN32; this fixed + a refresh bug under some versions of Windows. + + - Check for OpenGL headers before checking to see if + OpenGL is supported. This should eliminate compile + errors due to missing non-FLTK header files... + + - Add -D_INCLUDE_POSIX_SOURCE option when compiling with + the HP compilers. + + - Replaced remaining _WIN32 symbols with WIN32 + + - Removed reference to unused GL/glu.h header file, which is missing on + some Linux systems. + + - Fl_Gl_Window has a new method to allow you to get and set the context: + + void Fl_Gl_Window::context(void*, int destroy = 0) + void* Fl_Gl_Window::context() const; + + Return or set a pointer to the GLContext that this window is + using. This is a system-dependent structure, but it is portable to + copy the context from one window to another. You can also set it to + NULL, which will force FLTK to recreate the context the next time + make_current() is called, this is useful for getting around bugs in + OpenGL implementations. + + If destroy_flag is true the context will be destroyed by fltk when + the window is destroyed, or when the mode() is changed, or the next + time context(x) is called. + + - Some cleanup of Fl_Gl_Choice to move most of the system dependent + #ifdefs into Fl_Gl_Choice.cxx. + + - Fl_Gl_Window does not set drawbuffer(BACKBUFFER) for + single-buffered windows. + + - Fl_Input::replace(...) correctly updates the display + if the replaced region does not include the mark, + point, or selected region. + + - Added Fl::add_check(...), Fl::remove_check, and + Fl::has_check. These are similar to idle callbacks but + are only called just before it waits for new events. + They can be used to watch for changes in global state + and respond to them. + + - "accu-timer": some changes to repeat_timeout that seem + to make it accurate on Unix and WIN32 at speeds up to + 500000 timeouts/second (and 700000 on Linux), and + within about .001% as accurate as the system clock. + + - Fix to Fl_Valuator::step() by Guillermo Andrade. + + - Fixed the FLUID write-menu bug introduced in 1.0.10 + + - Fl::flush() now calls GdiFlush() under WIN32 to + ensure that all graphics are drawn. + + - fl_curve() now uses a much better algorithim to figure + out how many pieces to cut the curve into. + + - FLUID now uses GetTempPath() under WIN32 to determine + where to store the clipboard. + + - Right-ctrl does not delete selected text in Fl_Input, + until you type a composed character. + + - Added simple FLTK and FLUID manual pages. + + - Fl_Gl_Window leaked memory under WIN32. + + - The colbrowser demo was missing an include file when + compiled under OS/2. + + +CHANGES SINCE FLTK 1.0.9 + + - Added a strcasecmp() function to FLUID; AIX doesn't + have it. + + - Bug #115509: Fl_Scroll not repainting background. + + - Updated the configure script and makeinclude.in file + to work with the Sun PRO compilers. + + - Disabled the WIN32 async socket select code by default: + it doesn't seem to work anymore... + + - Fl::below_mouse() was incorrectly clearing e_is_click; + this prevented any double-clicks from getting + through... + + - No longer clear Fl::keysym on every event, this makes + better back compatability and fixes Win2000 + + - FLUID now restores which tab in an Fl_Tabs was + selected when loads .fl files. + + - Hack to fix the annoying "raise another application + when a modal window is closed" problem on WIN32. + + - Fl_Tabs now draws the background behind the tabs. + + - Fl::set_fonts() on WIN32 fixed to work before the + first window is shown. + + - CUA function keys, code submitted by George Yohng + <yohng@drivex.dosware.8m.com> + + - Another attempt to get glut.h to work on WIN32. + + - Fl_Menu_::add() ignores '&' signs when comparing menu + items, so you don't have to make the shortcuts the + same all the time. + + - Fixed bit-flipping patterns in WIN32 bitmap code. + + - Fixed size of data written by gif images to .C files + + - Menu titles and buttons in the menubar can be images + (allows it to be used as a toolbar) + + - Reads selectBackground from the xrdb database to set + the selection color. Adding this to your .Xdefaults + will make fltk and Motif programs look much more + Windoze-like: + + *selectForeground: white + *selectBackground: #000080 + + - FL_WHEN_RELEASE on Fl_Input will now do the callback + when the input field is hidden, for instance when it + is on a tab and the user switches to another tab. + + - Fl_Gl_Window with an overlay on X always resized any + child windows even if you turned resizable() off + because it turned it back on to resize the overlay + window. This patch avoids changing resizable(). + + - Fix so multiple Fl::add_idle() calls works + + - The input focus got messed up if you called + Fl_Tabs::value(x) and there was something that took + focus on an earlier tab. + + - Removed some (not all) of the warnings when compiled + with -Wwrite-strings, this should also get similar + warnings Solaris produces. + + - Made Fl_Browser not hide the Fl_Widget::show() method + + - Changes & additions for OS/2 from Alexander Mai + + - Patch from Mike Lindner to make the turning on/off of + scrollbars on Fl_Scroll smarter. + + - Added missing FL_EXPORT for Fl_Valuator::format() + + - Shortcuts for "buttons" in a Fl_Menu_Bar work again. + + - Fix for cut/paste support and Xdnd. + + - Shortcuts for submenu titles in a menubar pop up the + submenu (rather than calling the callback) + + - Added documentation for GL_SWAP_TYPE + + - Buttons with box(FL_NO_BOX) did not draw. Apparently + they did in older versions of fltk, I restored this. + (bug 108771) + + - Removed 8-bit colormap drawing code that was not doing + anything in fl_draw_image due to the colormap + allocation changes. I also made fl_color(r,g,b) + actually allocate the requested color rather than the + nearest fltk color-cube color (this is only done for + the first color that maps to a given entry in the fltk + color cube), the result is that pixmaps with a small + number of colors are drawn much more accurately. The + resulting code seems to produce better images and is a + good deal smaller! + + - Fixed makeinclude.in so CFLAGS are used for c source + code instead of CXXFLAGS. (bug 108694) + + - Better fix for gif files suggested by pauly (bug + 108770) + + - Performance of Fl_Gl_Window may be improved on some + types of OpenGL implementations, in particular MESA + or other software emulators, by setting the + GL_SWAP_TYPE environment variable. This variable + declares what is in the back buffer after you do a + swapbuffers: + + setenv GL_SWAP_TYPE COPY + + This indicates that the back buffer is copied to + the front buffer, and still contains it's old + data. This is true of many hardware + implementations. Setting this will speed up + emulation of overlays, and widgets that can do + partial update can take advantage of this as + damage() will not be cleared to -1. + + setenv GL_SWAP_TYPE NODAMAGE + + This indicates that nothing changes the back + buffer except drawing into it. This is true of + MESA and Win32 software emulation and perhaps some + hardware emulation on systems with lots of memory. + + All other values for GL_SWAP_TYPE, and not setting + the variable, cause fltk to assumme that the back + buffer must be completely redrawn after a swap. + + This is easily tested by running the gl_overlay demo + program and seeing if the display is correct when + you drag another window over it or if you drag the + window off the screen and back on. You have to exit + and run the program again for it to see any changes + to the environment variable. + + - Optimized colormap usage on 8-bit displays with + images. New code only allocates colors as they are + needed (still converts indexed images to full RGB and + dithers, tho...) + + - Fixed .gif files in fluid, they were broken by the fix + for large .xpm files in version 1.0.9. + + - Fix for OpenGL hardware overlays with the transparent + index != 0. Tested on the brand new HP Linux + Workstations, this is the only bug encountered. Both + X and OpenGL hardware overlay works perfectly on + these, though configue may not enable it by + default...) + + - Fl_Choice and all other Fl_Menu_ subclasses draw the + items using textcolor() as the default color of the + text. + + - Fix suggested by Stuart Levy to fix scrolling when + deleting items from the browser. + + - Replaced the -$(MAKEFLAGS) with $(MFLAGS) as per the + gmake documenation. Apperntly this works with other + make programs and MAKEFLAGS is passed invisibly by + gmake, though the documenation is not too clear... + + +CHANGES SINCE FLTK 1.0.8 + + - More documentation fixes. + - GLUT_STROKE_*_ROMAN in glut.h are defined as 0,1 on + WIN32 to match the glut header files there. + - Added Fl::has_timeout() and Fl::has_idle() functions. + - Added new Fl::repeat_timeout() method that + measures time from when the last timeout was called. + This has slightly less overhead and allows accurate + spacing of timeouts. + - More Cygwin changes + - FLUID could crash with identifiers with trailing + whitespace. + - Fixed the XPM loading code in FLUID to handle files + longer than 2048 lines. + - Added a bunch of missing FL_EXTERN's to glut.h to + eliminate GLUT linking errors under WIN32. + - Fix for sliders so that clicking on one with a small + (or zero) slider_size will not move the slider. + - fl_shortcut.cxx didn't export fl_old_shortcut() in the + WIN32 DLL. + - Fixed xpaint link in the documentation. + - Included Fl_Input word-wrap fixes from Alexander Rabi + Beels. This will not affect things much because + word-wrap is normally disabled. + - Patch from Stuart Levy so the *last* widget in an + Fl_Pack may be resizable. This should be compatable + because resizable didn't do anything before so there + was no reason to set it. + - Cleaned up the timeout and Fl::wait() code. The new + code calls the clock function less than half as much, + which results in a noticable performance improvement + in some apps. + - Fl::wait(time) with a time greater than the system can + handle (24.855 days on NT, the same on some Unix + systems) will now act as though the time is infinity. + Before it would do unpredictable things. + - "USE_POLL" now compiles and works, although it is + disabled by default. poll() is an alternative to the + UNIX select() call which is available on some version + of UNIX and may be faster depending on the platform; + try it by editing config.h. + - The WIN32 USE_ASYNC_SELECT code now does translation + and dispatching of the select events; this makes + Windows a lot happier. + - Added a check for an open display in Fl::wait() so + that you don't need an open window under X to call it. + + [changes in snapshot 2] + + - fl_old_shortcut() wasn't being exported in the WIN32 DLL + project. + - Updated Cygwin and Mingw makefiles. + - Updated the BC++ project file. + - You can no longer insert control chars into Fl_Int/Float_Input. + - Fl_Multiline_Input now resets the horizontal position when + focus is changed; this caused problems when multiple multiline + widgets were used in an application. + - All handle() methods are now public, and all draw() methods are + now protected in FLTK widgets. + - More fixes to the OpenGL overlay code on win32. This now + seems to work quite reliably on several different pieces of + hardware. Apparently doing SetLayerPaletteEntries with a + palette larger than the overlay size caused the drivers to + screw up in unpredictable ways. Also SwapBuffers swapped both + the overlay and main window, which is not what fltk's + interface wanted, this was easy to fix however. + - Patch for full scrollbars so that clicking on them does not + move anything. + - Documentation fixes. + - Better horizontal scrolling of Fl_Input when cursor is near + the end of the line. + - Fl_Input::value(x) selects all text. + - Fl_Output and Fl_Multiline_Output would scroll to the end + of the text. + - filename_isdir() now drops any trailing slash from the + filename (needed for Windows) + - Added return type for main() function in line_style demo. + - Running FLUID with the "-cs" option writes the I18N message + file. + - The WIN32 version of XParseGeometry() didn't initialize some + variables. This caused a compiler warning but did not affect + the actual code. + + [changes in snapshot 1] + + - EMail changes - fltk-bugs@easysw.com now officially + fltk-bugs@fltk.org. + - The FLTK DLL project file didn't include fl_compose.cxx + - Dropped the GCC -fno-rtti option since it caused problems + with existing programs. + - Moved the .fl rules back to the test directory. + - Fixed some makefile and spec file problems. + - Fixed hardware overlays. The problem was the new + fl_clipped() code, which tests against the current window + size. The hardware overlay code did not set the current + window when drawing the overlay. I needed hardware overlay + for DD's code, I'm not sure if these fixes are good enough to + enable this in our general release. Hardware overlay still + only works on SGI Irix. + - Some patches to turn off the MSVC++ -Oa (assumme no aliasing) + optimization flag. Suprisingly this only broke a few parts + of fltk, or at least these are the only ones I found. + - Does not unmap child windows when the main window is + iconized. This reduces flashing when the window is + deiconized. + - Fl::key() is set to zero by all events except key down/up. + This will allow you to reliably test if an event or callback + was produced by a keystroke. Fixes the bug posted about + stopping Escape from closing the window. + - User defined cursors on OpenGL windows slowed down NT a + *LOT*. Some attempts to fix this by turning off the cursor + while drawing the window. + - Filename completion in the file chooser works better on NT. + Typing TAB fixes the case of everything you typed to match + the shortest name that can be completed. + + +CHANGES SINCE FLTK 1.0.7 + + - Many documentation changes/fixes/improvements. + - FLUID didn't save Fl_Double_Window's as + double-buffered windows. + - Fl_Menu_ text color is used if Fl_Menu_Item text color + is not set. + - Added Fl::first_window(window) method to change the + "top" window that is used when showing modal windows. + By default it is the window the user last + clicked/typed in. + - The Fl_Menu::global() handler now uses the current top + window instead of the menu bar for modal stuff. + - Added fl_line_style() function to set the line style. + Note that user-defined line styles ONLY WORK UNDER X11 + and Windows NT/2000. Windows 95/98 do, however, + support the "standard" line styles. + - Fl::wait() does not return immediately when no windows + - XForms keyboard shortcuts using hex keycode constants + now work. + - Updated the configure script for *BSD and to turn off + exceptions and RTTI in the FLTK library itself (does + not affect applications which use these things) + - FLUID now supports I18N using the POSIX or GNU + mechanisms. + - Fixed definition of glutBitmapWidth to match header + file. + - Does not turn visible() on when a window is iconized() + or if a modal window is shown and it's parent is + iconized. This allows the code "while (w->visible() + && w->damage()) Fl::check();" to reliably wait for the + window to be mapped and drawn the first time. + - Setting box(FL_NO_BOX) on a button makes it an + invisible overlay + - FL_NORMAL_SIZE is now a global variable so you can + change the default text size prior to creating your + widgets. + - Menus now draw properly with a box type of + FL_FLAT_BOX. + - Cygwin fixes to compile in POSIX mode. + - Fl_Value_Input callback can call value() or + destructor. + - OpenGL overlays now work under Windows NT! + - Fl_Slider and Fl_Scrollbar could cause a divide by + zero. + - Clicking in an Fl_Input field no longer selects the + whole field, it just moves the text cursor. + - Tru64 UNIX fixes for filename_list() + - Fl_Browser now draws itself properly when deactivated. + - FLUID GUIs now use Courier font for all code input. + - The FLUID OK and Cancel buttons are now all shown in + the same order in all windows. + - Fixes to compile under GCC 2.95.2 + - Fixed the BC5 project files. + - FL_LEFT_MOUSE and friends are now in + <FL/Enumerations.H> + - Fixes for fake OpenGL overlay code under WIN32. + - Message windows are now resizeable. + - On WIN32 non_modal (but not modal) windows have the + close and size boxes. + - Fl_Button and friends didn't honor the + FL_WHEN_NOT_CHANGED condition. + - Disabled XDBE on all platforms. + - XGetDefault patch from James Roth + - New fl_open_display(Display *) function to allow FLTK + to share a display connection with another toolkit + (like Xt, GTK, etc.) + - Shortcut labels for special keys should now display + properly under WIN32. + - fl_set_fonts() did not reuse fonts. + - Fixed shortcut problem under WIN32 when the focus + window changes. + - "dead" keys should now work under X11. + - Fixes to make FLTK compile with GCC 2.95.2 + - FL_SHORTCUT fix for I18N. + - Fixed cut/paste problems under WIN32 + - FLUID now produces correct code for nested class + destructors. + - Nested windows should now redraw properly under WIN32. + - "table" is now static in fl_cursor.cxx + - Fl_Chart used the textcolor() and not the color() for + horizontal bar charts. + - Now set the input hint for TWM and TWM-derived window + managers. + - Now look for TrueColor visual if FLTK is compiled with + USE_COLORMAP == 0. + - Fl_Scrollbar could generate a divide-by-0 error if the + min and max values were the same. + - Fl_Menu_::remove() now removes whole submenus if + needed. + - Scrollbar buttons now draw themselves pushed in as + needed. + - Fixed the gl_overlay demo (and gl overlays in general) + when they are faked with no hardware and the window is + resized. + - Selections weren't shown in Fl_Browser widgets when an + item used the @B (background) format. + - Windows can now be resized by the program under X11 + for more window managers. + - OS/2 makeinclude updates. + - Added Fl.H required by an inline function in + Fl_Repeat_Button.H + - Fl_add_idle adds new functions to the end of the queue + ring, rather than the start, so they are executed in + the order added, and a callback that adds itself does + not prevent others from being called. + - FLUID lets you type in code that starts with '#' for + cpp directives. + - XBell() could be called before the X11 display was + opened, causing a segfault. + - Fixed Fl_Gl_Window::ortho() - Borland C++ doesn't + define GLint to "int", but instead to "long"... + - Fixed Fl_Browser scrollbars within an Fl_Scroll + widget. + - Fl_Output (and non-focused Fl_Input) now scroll in + response to position() + - Fl_Input now does not scroll horizontally if the + entire string will fit in the widget. + - Fl_Scrollbar didn't push the right arrow buttons when + you clicked outside the scroller. + - Now use WSAAsyncSelect() for better socket performance + with Fl::add_fd() + + +CHANGES SINCE FLTK 1.0.6 + + - Fixed Fl_Input_ bug under WIN32 - no longer stop accepting input + when one of the "Windows" keys is pressed. + - Now call TranslateEvent for all events under WIN32. + - Fixes for OpenBSD and NetBSD + - The FL_CURSOR_HAND cursor now uses the IDC_HAND cursor instead of + IDC_UPARROW under Windows 98 and 2000. + - Fl_Scrollbar now does a page-up/down when you click outside the + scroller. + - Fl_Window::show(0, NULL) causes core dump + - Fixed a compile-time error in fl_call_main.c for Borland C++. + - "fluid -c filename.fl" would try to open an X display if the + FLUID file contained an Fl_Browser widget. + - Fl_Browser now correctly measures items with @C or @B color + formatting commands. + - Fixed a bitmap drawing bug for WIN32 (bit reversal table was wrong) + - fl_xyz() dialogs now set a title in the title bar. + - fl_alert() sounds the bell under X11. + - fl_xyz() dialogs now call MessageBeep() under WIN32. + - Fl_Browser_ didn't draw the selection box with the inactive color + when the browser wasn't activated. + - Fl_Browser now responds to FL_KEYBOARD as well as FL_SHORTCUT. If + you subclass it to accept focus then keyboard navigation will work. + - Fl_Tile and Fl_Tabs do their callback when the user changes their + display. + - Made some of the private methods of Fl_Browser protected. + - Now set win_gravity correctly, this helps some X + window managers that use it position the window where + FLTK wants it to be. + - 0-width browsers crashed. + - Minor change: if the X window manager does not do + anything else with windows that don't have their + position specified, the windows appear centered in the + screen, rather than in the top-left corner. This + happened with modal windows under Irix 4Dwm. This + also causes windows to be centered when no window + manager is running, which might be useful for + installation gui programs? + - Clicking in an Fl_Input field the first time selects the entire + field. + - Clicking the middle mouse button in an Fl_Input field now inserts + the text at the indicated position instead of the cursor position. + - Drag-selecting text in an Fl_Input field now copies the text + automatically. + - Fl::flush() no longer calls the draw() method for invisible windows. + - Calling deactivate() on an invisible widget could cause an + infinite loop in some obscure cases. + - Added #pragma's for SGI C++ compilers - the 6.{23} X headers had + errors in them. + - Fl_Gl_Window::ortho() changed so that text and images + are not erased if the origin is off the left/bottom of the + window. + - Small change to Fl_Input so that a click that gives it + the focus also selects all the text. + - Fixed a slider drawing problem. + - You can now add/delete children of Fl_Tabs widgets whether or + not they are visible. + - Now embed woff options for SGI C++ compilers (gets rid of X11 + header warnings) + - draw_pixmap used a cast that the Digital UNIX C++ compiler didn't + like. + - The GLUT function key constants were off by one. + - The XPM reading code didn't handle RGB colors other than #rrggbb. + + +CHANGES SINCE FLTK 1.0.5 + + - Fl_win32.cxx defined WM_MOUSE_LEAVE instead of WM_MOUSELEAVE. + - Fl_get_key_win32.cxx needed to include <ctype.h> + - gl_draw_pixmap.cxx needed a pointer cast for ANSI C++. + - Fl_Repeat_Button didn't always delete its timeout. + - Now keep track of the current OpenGL context; this provides + significant performance improvements for OpenGL applications + with a single context. + + +CHANGES SINCE FLTK 1.0.4 + + - Fl_Roller didn't handle a width and height of 0. + - filename_list() fix for FreeBSD. + - Fixed RPM install docos - needed "--install" option... + - Fl_Browser_ wouldn't draw the vertical scrollbar right away if it + added a horizontal one which covered the last line. + - Fl_Tabs problems - single-character labels don't show up (problem in + measure_tabs() or measure_label() methods?), and doesn't clear top + tab area before drawing tabs. + - Fl_Browser needs a destructor. + - fl_draw_label() quoted characters between 0x80 and 0xa0, which + caused problems for some programs using the WinANSI character set. + - FLUID didn't handle declared class destructors. + - Fixed another WIN32 cut/paste bug. + - Fl_Tabs didn't work properly when there was only 1 tab. + - Fl_Menu::add() didn't delete the old array. + - Fl_Repeat_Button didn't delete its timeout when disabled. + - fl_draw() would crash if no font was set (now defaults to + a 14-pixel Helvetica font) + - Can't forward declare classes; need to check for "class ", "struct ", + "union ", etc. See Bill's message + - Added #pragma around xlib.h for IRIX + - FL_KEYBOARD events have the correct x/y when sent to child X + windows. Note that if you worked around this bug by adjusting the + x/y yourself you will have to change your code. In addition all + events have the correct x/y when sent to the grab() widget. And + the code to do all this was simplified a lot. + - The XPM code didn't handle named colors with spaces in the names. + - Pressing ESCape closed the window with pointer focus, even if there + was a modal window open (now closes the modal window). + - FLUID no longer produces trigraphs accidentally in the image data. + - FLUID uses string constant concatenation to produce shorter image + data. + - The Fl_Group deletion code crashed if there was exactly one child + widget. + - Simulated overlays in single-buffered Fl_Gl_Windows now draw + correctly (though very slowly as it requires the entire window to + be redrawn to erase the overlay). This fix ported our Digital + Domain programs better to systems with no overlay hardware. + - Added support for extern "C" declarations in FLUID. + - Added Fl_Pack support to FLUID. + - Fixed the order of #include's in FLUID generated header files. + - Fixed detection of vsnprintf and snprintf under HP-UX 10.20 once + and for all. + - The checkers demo did not compile with GCC 2.95 + - FLUID didn't output virtual destructors properly. + - Added inline "make_visible()" method to Fl_Browser. + - Fl::wait() now returns immediately if any timeouts are + called. + - 16-bit XPM files are now properly handled. + - Fl_Window::resize() was missing FL_EXPORT (caused problems + with Windows DLLs) + - FLUID was writing extern declarations twice. + - New FLUID arrow key functionality: arrows move by one pixel, shift+arrow + resizes, ctrl+arrow steps by grid + + +CHANGES SINCE FLTK 1.0.3 + + - Documentation updates + - Fl_Browser::bottomline(size) didn't scroll to the bottom + if the second-to-last line was visible. + - fl_wait() didn't poll FDs properly for WIN32. + - Fixed DLL definitions for BC++. + - FLUID now handles nested classes properly. + - The "connect" demo now does a wait() for the PPP process + so that you aren't left with a lot of zombie processes. + - Fixed the FLTK colormap to use FF instead of F4 for full + intensity values. + - Minor change to scrollbar drawing code to match other + toolkits. + - New selections would cancel themselves out in WIN32. + - The header file links were broken in the IRIX + distributions. + - fl_elapsed() now always uses GetClockTick() for WIN32. + - fl_display is now initialized to GetModuleHandle(NULL) - + this fixes problems people had with Cygwin and MingW32. + - WinMain() is no longer compiled in with Cygwin and + MingW32; it wasn't being used for those compilers anyways. + - Added Solaris compiler options to configure script. + - Fl_Value_Input wouldn't update properly if you set the + value from a callback. + - Fl_Tile wouldn't resize if the resizeable widget was the + last child. + - Was missing #include <ctype.h> and #include <stdlib.h> in + several files, which caused problems on some platforms. + - Fixed another case where Fl_Browser_ could get in an + infinite resizing loop. + - Fl_win32.cxx now includes <FL/filename.H> to export missing + DLL symbols. + - FLUID didn't handle member functions that include the + scope operator. + - Fl_Chart was dividing by 0 if there were no data samples + or if they were all the same (min == max). + + +CHANGES SINCE FLTK 1.0.2 + + - XDBE is now enabled for IRIX 6.[234] as well as 6.5. + - FLUID didn't write the when() condition properly. + - Tab/space/backtab/backspace can be used to navigate + through menus. + - Changed $(DSONAME) in the src/Makefile to "libfltk.so.1 + libfltk.sl.1". + - Fl_Browser could read past the end of the string when + computing the item height. + - Fl_Browser could get in an infinite loop when checking to + see if scrollbars needed to be displayed. + - FLUID now honors the return type of the outermost widget. + This was a problem when substituting Fl_Group in an + Fl_Window widget. + - Fl_Menu_::copy() wasn't allocating a power of 2 for the + array size. + - FLWM would crash if fl_xmousewin was deleted. + - The fast_slow demo now uses output widgets. + - Timers under WIN32 were unreliable. + + +CHANGES SINCE FLTK 1.0.1 + + - Documentation updates + - The Visual C++ project files didn't include fl_add_idle.cxx. + - LIBRARY/DSO name inconsistencies in src/Makefile. + - src/Makefile didn't clean the DSO. + - The valuator demo now has only a single callback. + - The code looked for HAVE_SYS_SELECT_H, but the + config file uses HAVE_SYS_SELECT. + - Fl_Image redraw not quite right under X11 or WIN32 + - Problems with timeouts & cube demo under WIN32 + - FLUID problems with inline functions. + - Documentation fixes... + - Fl_Browser::item_height() didn't handle blank lines or + non-default fonts properly. + - FL/math.h didn't have #ifndef...#define...#endif guards + against multiple inclusion... + - Fl_Menu_::copy() fix - didn't allocate power of 2... + - Fl::damage() now remains true until all windows are actually + redrawn. + - Fl_Widget destructor, hide(), and deactivate() methods no longer + send FL_LEAVE, FL_RELEASE, or FL_UNFOCUS events to the widget + (which could cause applications to crash). + - FLUID now outputs symbolic names for align() and when(). + - Fixed select() to use maxfd + 1 instead of maxfd. + - Added "Fl::remove_fd(fd, when)" function so you can remove the + read and write callbacks separately. + - The Fl::add_fd() and Fl::add_timeout() arrays are now dynamically + allocated. + - FLUID didn't always turn the FL_SUBMENU flag on for submenu titles. + - The "extra code" in FLUID now is placed before the "o->end()" call + for Fl_Group and its derived classes. + - You can now set a FL_Window widget's class in FLUID to Fl_Group to + generate a function or class that builds part of a GUI (i.e. no window). + - FLUID now displays "Save file before exiting?" with the standard yes, + no, and cancel buttons rather than "Discard changes?". + - Fl_Menu_::add() now works with any type of menu, even one set with + the menu() method. + - The keypad keys were not always decoded properly under X11. + - Some pointers were not being turned off when widgets were deleted, + which caused some applications (like FLWM) to crash. + + +CHANGES SINCE FLTK 1.0 + + - Documentation fixes. + - Fl::check() didn't return the correct value, breaking a number + of applications. + - Fixed fluid bug that caused styles patch to crash when you delete + a menu item. + - Updated valuators demo to put the values in the gui box. + - Fl_Browser_::item_height() didn't always compute the correct + value. + - Fixed the alignment of Fl_Choice text. + - Fixes for OS/2. + - Fl_Menu_Item::clear() didn't clear value. + - Added some changes to make FLTK work with Borland C++. + - ANSI C++ fixes. + - Plugged a memory leak in the fractal demo. + - Fl::add_timeout() didn't work under WIN32 with small values. + - The configure script and makefiles now define DSONAME and + use the static library for all example programs. diff --git a/Utilities/FLTK/CMake/CheckFunctionWithHeaderExists.cmake b/Utilities/FLTK/CMake/CheckFunctionWithHeaderExists.cmake new file mode 100644 index 0000000000..46694e82a5 --- /dev/null +++ b/Utilities/FLTK/CMake/CheckFunctionWithHeaderExists.cmake @@ -0,0 +1,54 @@ +# +# Check if the symbol exists in include files +# +# CHECK_FUNCTIONWITHHEADER_EXISTS - macro which checks the symbol exists in include files. +# SYMBOL - symbol +# FILES - include files to check +# VARIABLE - variable to return result +# + +MACRO(CHECK_FUNCTIONWITHHEADER_EXISTS SYMBOL FILES VARIABLE) + IF("${VARIABLE}" MATCHES "^${VARIABLE}$") + SET(CHECK_SYMBOL_EXISTS_CONTENT "/* */\n") + SET(MACRO_CHECK_SYMBOL_EXISTS_FLAGS ${CMAKE_REQUIRED_FLAGS}) + IF(CMAKE_REQUIRED_LIBRARIES) + SET(CHECK_SYMBOL_EXISTS_LIBS + "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}") + ENDIF(CMAKE_REQUIRED_LIBRARIES) + FOREACH(FILE ${FILES}) + SET(CHECK_SYMBOL_EXISTS_CONTENT + "${CHECK_SYMBOL_EXISTS_CONTENT}#include <${FILE}>\n") + ENDFOREACH(FILE) + SET(CHECK_SYMBOL_EXISTS_CONTENT + "${CHECK_SYMBOL_EXISTS_CONTENT}\nint main()\n{\n${SYMBOL};return 0;\n}\n") + + FILE(WRITE ${CMAKE_BINARY_DIR}/CMakeTmp/CheckSymbolExists.c + "${CHECK_SYMBOL_EXISTS_CONTENT}") + + MESSAGE(STATUS "Looking for ${SYMBOL}") + TRY_COMPILE(${VARIABLE} + ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}/CMakeTmp/CheckSymbolExists.c + CMAKE_FLAGS + -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_SYMBOL_EXISTS_FLAGS} + "${CHECK_SYMBOL_EXISTS_LIBS}" + OUTPUT_VARIABLE OUTPUT) + IF(${VARIABLE}) + MESSAGE(STATUS "Looking for ${SYMBOL} - found") + SET(${VARIABLE} 1 CACHE INTERNAL "Have symbol ${SYMBOL}") + FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeOutput.log + "Determining if the ${SYMBOL} " + "exist passed with the following output:\n" + "${OUTPUT}\nFile ${CMAKE_BINARY_DIR}/CMakeTmp/CheckSymbolExists.c:\n" + "${CHECK_SYMBOL_EXISTS_CONTENT}\n") + ELSE(${VARIABLE}) + MESSAGE(STATUS "Looking for ${SYMBOL} - not found.") + SET(${VARIABLE} "" CACHE INTERNAL "Have symbol ${SYMBOL}") + FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeError.log + "Determining if the ${SYMBOL} " + "exist failed with the following output:\n" + "${OUTPUT}\nFile ${CMAKE_BINARY_DIR}/CMakeTmp/CheckSymbolExists.c:\n" + "${CHECK_SYMBOL_EXISTS_CONTENT}\n") + ENDIF(${VARIABLE}) + ENDIF("${VARIABLE}" MATCHES "^${VARIABLE}$") +ENDMACRO(CHECK_FUNCTIONWITHHEADER_EXISTS) diff --git a/Utilities/FLTK/CMake/FLTKConfig.cmake.in b/Utilities/FLTK/CMake/FLTKConfig.cmake.in new file mode 100644 index 0000000000..6cbd3f6d25 --- /dev/null +++ b/Utilities/FLTK/CMake/FLTKConfig.cmake.in @@ -0,0 +1,39 @@ +#----------------------------------------------------------------------------- +# +# FLTKConfig.cmake - FLTK CMake configuration file for external projects. +# +# This file is configured by FLTK and used by the UseFLTK.cmake module +# to load FLTK's settings for an external project. + +# The FLTK source tree. +SET(FLTK_SOURCE_DIR "@FLTK_SOURCE_DIR@") + +# The FLTK include file directories. +SET(FLUID_COMMAND "@FLTK_FLUID_COMMAND@") +SET(FLTK_EXECUTABLE_DIRS "@FLTK_EXECUTABLE_DIRS@") +SET(FLTK_LIBRARY_DIRS "@FLTK_LIBRARY_DIRS@") +SET(FLTK_LIBRARIES "@FLTK_LIBRARIES@") +SET(FLTK_INCLUDE_DIRS "@FLTK_INCLUDE_DIRS@") +# OTB Add +SET(FLTK_PLATFORM_DEPENDENT_LIBS "@FLTK_PLATFORM_DEPENDENT_LIBS@") + +# The C and C++ flags added by FLTK to the cmake-configured flags. +SET(FLTK_REQUIRED_C_FLAGS "@FLTK_REQUIRED_C_FLAGS@") +SET(FLTK_REQUIRED_CXX_FLAGS "@FLTK_REQUIRED_CXX_FLAGS@") + +# The FLTK version number +SET(FLTK_VERSION_MAJOR "@FLTK_VERSION_MAJOR@") +SET(FLTK_VERSION_MINOR "@FLTK_VERSION_MINOR@") +SET(FLTK_VERSION_PATCH "@FLTK_VERSION_PATCH@") + +# Is FLTK using shared libraries? +SET(FLTK_BUILD_SHARED_LIBS "@BUILD_SHARED_LIBS@") +SET(FLTK_BUILD_SETTINGS_FILE "@FLTK_BUILD_SETTINGS_FILE@") + +# The location of the UseFLTK.cmake file. +SET(FLTK11_USE_FILE "@FLTK_USE_FILE@") + +# The ExodusII library dependencies. +IF(NOT FLTK_NO_LIBRARY_DEPENDS) + INCLUDE("@FLTK_LIBRARY_DEPENDS_FILE@") +ENDIF(NOT FLTK_NO_LIBRARY_DEPENDS) diff --git a/Utilities/FLTK/CMake/FLTKUse.cmake b/Utilities/FLTK/CMake/FLTKUse.cmake new file mode 100644 index 0000000000..3512b5ef97 --- /dev/null +++ b/Utilities/FLTK/CMake/FLTKUse.cmake @@ -0,0 +1,68 @@ +IF(NOT FLTK11_FOUND) + MESSAGE(FATAL_ERROR "Something went wrong. You are including FLTKUse.cmake but FLTK was not found") +ENDIF(NOT FLTK11_FOUND) + +# ------------------------------------------------------------- +# This macro automates wrapping of Fluid files +# Specify the output variable name and the list of sources +# The output variable can be directly added to the target. +# +# For example: +# FLTK_WRAP_FLUID(CubeView_SRCS CubeViewUI.fl) +# ADD_EXECUTABLE(CubeView CubeMain.cxx CubeView.cxx CubeView.h ${CubeView_SRCS}) +# ------------------------------------------------------------- +MACRO(FLTK_WRAP_FLUID VARIABLE) + FOREACH(src ${ARGN}) + IF("${src}" MATCHES ".fl$") + GET_FILENAME_COMPONENT(fname ${src} NAME_WE) + GET_FILENAME_COMPONENT(fpath ${src} PATH) + GET_SOURCE_FILE_PROPERTY(gen ${src} GENERATED) + IF(gen) + SET(fluid_name "${src}") + ELSE(gen) + SET(fluid_name "${CMAKE_CURRENT_SOURCE_DIR}/${fpath}/${fname}.fl") + IF(NOT EXISTS "${fluid_name}") + SET(fluid_name "${CMAKE_CURRENT_BINARY_DIR}/${fpath}/${fname}.fl") + IF(NOT EXISTS "${fluid_name}") + SET(fluid_name "${fpath}/${fname}.fl") + IF(NOT EXISTS "${fluid_name}") + MESSAGE(SEND_ERROR "Cannot find Fluid source file: ${fpath}/${fname}.fl") + ENDIF(NOT EXISTS "${fluid_name}") + ENDIF(NOT EXISTS "${fluid_name}") + ENDIF(NOT EXISTS "${fluid_name}") + ENDIF(gen) + SET(cxx_name "${CMAKE_CURRENT_BINARY_DIR}/${fname}.cxx") + SET(h_name "${CMAKE_CURRENT_BINARY_DIR}/${fname}.h") + SET(${VARIABLE} "${${VARIABLE}};${cxx_name}") + ADD_CUSTOM_COMMAND( + OUTPUT ${cxx_name} + DEPENDS "${fluid_name}" "${FLUID_COMMAND}" + COMMAND ${FLUID_COMMAND} + ARGS -c ${fluid_name}) + ADD_CUSTOM_COMMAND( + OUTPUT ${h_name} + DEPENDS "${fluid_name}" "${FLUID_COMMAND}" + COMMAND ${FLUID_COMMAND} + ARGS -c ${fluid_name}) + ENDIF("${src}" MATCHES ".fl$") + ENDFOREACH(src) +ENDMACRO(FLTK_WRAP_FLUID VARIABLE) + + +# Make FLTK easier to use +INCLUDE_DIRECTORIES(${FLTK_INCLUDE_DIRS}) +LINK_DIRECTORIES(${FLTK_LIBRARY_DIRS}) + +# Load the compiler settings used for FLTK. +IF(FLTK_BUILD_SETTINGS_FILE) + INCLUDE(CMakeImportBuildSettings) + CMAKE_IMPORT_BUILD_SETTINGS(${FLTK_BUILD_SETTINGS_FILE}) +ENDIF(FLTK_BUILD_SETTINGS_FILE) + +# Add compiler flags needed to use FLTK. +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLTK_REQUIRED_C_FLAGS}") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLTK_REQUIRED_CXX_FLAGS}") +SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLTK_REQUIRED_EXE_LINKER_FLAGS}") +SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLTK_REQUIRED_SHARED_LINKER_FLAGS}") +SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${FLTK_REQUIRED_MODULE_LINKER_FLAGS}") + diff --git a/Utilities/FLTK/CMake/PlatformTests.cxx b/Utilities/FLTK/CMake/PlatformTests.cxx new file mode 100644 index 0000000000..bfe97ac951 --- /dev/null +++ b/Utilities/FLTK/CMake/PlatformTests.cxx @@ -0,0 +1,81 @@ +#ifdef HAVE_LIBZ + +#include <zlib.h> + +int main() +{ + unsigned long compressedSize = 0; + unsigned char cd[100]; + const unsigned char ud[100] = ""; + unsigned long uncompressedSize = 0; + + // Call zlib's compress function. + if(compress(cd, &compressedSize, ud, uncompressedSize) != Z_OK) + { + return 0; + } + return 1; +} + + +#endif + +#ifdef HAVE_LIBJPEG + +#include <stdio.h> +#include <jpeglib.h> + +int main() +{ + struct jpeg_decompress_struct cinfo; + jpeg_create_decompress(&cinfo); + jpeg_read_header(&cinfo, TRUE); + return 1; +} + +#endif + +#ifdef HAVE_LIBPNG +#include <png.h> +int main() +{ + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)NULL, + NULL, NULL); + png_infop info_ptr = png_create_info_struct(png_ptr); + png_set_sig_bytes(png_ptr, 8); + png_read_info(png_ptr, info_ptr); + + return 0; +} +#endif + +#ifdef HAVE_PNG_H +#include <png.h> +int main() { retunr 0;} +#endif + +#ifdef HAVE_PNG_GET_VALID +#include <png.h> +int main() +{ + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)NULL, + NULL, NULL); + png_infop info_ptr = png_create_info_struct(png_ptr); + png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS); + return 0; +} +#endif + +#ifdef HAVE_PNG_SET_TRNS_TO_ALPHA +#include <png.h> +int main() +{ + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)NULL, + NULL, NULL); + png_set_tRNS_to_alpha(png_ptr); + return 0; +} +#endif diff --git a/Utilities/FLTK/CMakeLists.txt b/Utilities/FLTK/CMakeLists.txt new file mode 100644 index 0000000000..4461ac0a22 --- /dev/null +++ b/Utilities/FLTK/CMakeLists.txt @@ -0,0 +1,410 @@ +# Main CMakeLists.txt to build the FLTK project using CMake (www.cmake.org) +# Written by Andy Cedilnik and Julien Jomier + +PROJECT(FLTK) +CMAKE_MINIMUM_REQUIRED(VERSION 2.0) + +# The FLTK version +SET(FLTK_VERSION_MAJOR "1") +SET(FLTK_VERSION_MINOR "1") +SET(FLTK_VERSION_PATCH "7") +SET(FLTK_VERSION "${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR}") +SET(FLTK_VERSION_FULL "${FLTK_VERSION}.${FLTK_VERSION_PATCH}") + +SET(FLTK_LIBRARIES "fltk_images;fltk;fltk_gl;fltk_forms") + +# Executables and libraries should just go to bin +SET(EXECUTABLE_OUTPUT_PATH "${OTB_BINARY_DIR}/bin" CACHE INTERNAL + "Where to put the executables for FLTK" + ) +SET(LIBRARY_OUTPUT_PATH "${OTB_BINARY_DIR}/bin" CACHE INTERNAL + "Where to put the libraries for FLTK" + ) + +# Allow building shared libraries +OPTION(BUILD_SHARED_LIBS "Build FLTK as a shared library" OFF) + +# Search for modules in the FLTK source dir first +SET(CMAKE_MODULE_PATH "${FLTK_SOURCE_DIR}/CMake") + +#----------------------------------------------------------------------------- +# Test for some required system information. +FIND_PACKAGE(Threads) +SET (CMAKE_USE_PTHREADS + "${CMAKE_USE_PTHREADS_INIT}" CACHE BOOL "Use the pthreads library.") + +# We need ansi c-flags, especially on HP +SET(CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS}") +SET(CMAKE_REQUIRED_FLAGS ${CMAKE_ANSI_CFLAGS}) + +IF(WIN32) + IF(NOT CYGWIN) + IF(BORLAND) + SET( FLTK_PLATFORM_DEPENDENT_LIBS import32 ) + ELSE(BORLAND) + SET( FLTK_PLATFORM_DEPENDENT_LIBS wsock32 comctl32 ) + ENDIF(BORLAND) + ENDIF(NOT CYGWIN) +ENDIF(WIN32) + +SET(FLTK_X11 1) +SET(FLTK_APPLE 0) +IF(APPLE) + OPTION(FLTK_APPLE_X11 "Use X11 on Mac instead of Carbon" OFF) + MARK_AS_ADVANCED(FLTK_APPLE_X11) + IF(NOT FLTK_APPLE_X11) + SET(FLTK_APPLE 1) + SET(FLTK_X11 0) + OPTION(FLTK_QUARTZ "Use Quartz instead of Quickdraw" OFF) + ENDIF(NOT FLTK_APPLE_X11) +ENDIF(APPLE) + +IF(UNIX) + FIND_PACKAGE(X11) + SET( FLTK_PLATFORM_DEPENDENT_LIBS ${X11_LIBRARIES} -lm) +ENDIF(UNIX) + +IF(APPLE AND NOT FLTK_APPLE_X11) + SET( FLTK_PLATFORM_DEPENDENT_LIBS + "-framework Carbon -framework Cocoa -framework ApplicationServices -lz") +ENDIF(APPLE AND NOT FLTK_APPLE_X11) + +IF(CYGWIN) + ADD_DEFINITIONS(-DWIN32) + SET( FLTK_PLATFORM_DEPENDENT_LIBS ole32 uuid comctl32 wsock32 supc++ -lm -lgdi32) +ENDIF(CYGWIN) + +IF(MINGW) + ADD_DEFINITIONS(-DWIN32) + SET( FLTK_PLATFORM_DEPENDENT_LIBS ole32 uuid wsock32 gdi32 comdlg32) +ENDIF(MINGW) + +INCLUDE(CheckIncludeFiles) +# Check if header file exists and add it to the list. +MACRO(CHECK_INCLUDE_FILE_CONCAT FILE VARIABLE) + CHECK_INCLUDE_FILES("${PROJECT_INCLUDES};${FILE}" ${VARIABLE}) + IF(${VARIABLE}) + SET(PROJECT_INCLUDES ${PROJECT_INCLUDES} ${FILE}) + ENDIF(${VARIABLE}) +ENDMACRO(CHECK_INCLUDE_FILE_CONCAT) +CHECK_INCLUDE_FILE_CONCAT("GL/glu.h" HAVE_GL_GLU_H) +CHECK_INCLUDE_FILE_CONCAT("OpenGL/glu.h" HAVE_OPENGL_GLU_H) +CHECK_INCLUDE_FILE_CONCAT("dirent.h" HAVE_DIRENT_H) +CHECK_INCLUDE_FILE_CONCAT("stdio.h" HAVE_STDIO_H) +CHECK_INCLUDE_FILE_CONCAT("strings.h" HAVE_STRINGS_H) +CHECK_INCLUDE_FILE_CONCAT("sys/dir.h" HAVE_SYS_DIR_H) +CHECK_INCLUDE_FILE_CONCAT("sys/ndir.h" HAVE_SYS_NDIR_H) +CHECK_INCLUDE_FILE_CONCAT("sys/select.h" HAVE_SYS_SELECT_H) +CHECK_INCLUDE_FILE_CONCAT("sys/stdtypes.h" HAVE_SYS_STDTYPES_H) +CHECK_INCLUDE_FILE("pthread.h" CMAKE_HAVE_PTHREAD_H) + +FIND_PACKAGE(ZLIB) +FIND_PACKAGE(PNG) +FIND_PACKAGE(JPEG) + +INCLUDE(CheckSymbolExists) +INCLUDE(CheckFunctionWithHeaderExists) + +CHECK_FUNCTIONWITHHEADER_EXISTS("int strcasecmp()" "${PROJECT_INCLUDES}" HAVE_STRCASECMP) + +CHECK_SYMBOL_EXISTS(strlcat "${PROJECT_INCLUDES}" HAVE_STRLCAT) +CHECK_SYMBOL_EXISTS(strlcpy "${PROJECT_INCLUDES}" HAVE_STRLCPY) +CHECK_SYMBOL_EXISTS(vsnprintf "${PROJECT_INCLUDES}" HAVE_VSNPRINTF) +CHECK_SYMBOL_EXISTS(snprintf "${PROJECT_INCLUDES}" HAVE_SNPRINTF) +CHECK_SYMBOL_EXISTS(scandir "${PROJECT_INCLUDES}" HAVE_SCANDIR) + +INCLUDE(CheckTypeSize) + +CHECK_TYPE_SIZE(short SIZEOF_SHORT) +CHECK_TYPE_SIZE(int SIZEOF_INT) +CHECK_TYPE_SIZE(long SIZEOF_LONG) + +IF(${SIZEOF_SHORT} MATCHES "^2$") + SET(U16 "unsigned short") +ENDIF(${SIZEOF_SHORT} MATCHES "^2$") + +IF(${SIZEOF_INT} MATCHES "^4$") + SET(U32 "unsigned") +ELSE(${SIZEOF_INT} MATCHES "^4$") + IF(${SIZEOF_LONG} MATCHES "^4$") + SET(U32 "unsigned long") + ENDIF(${SIZEOF_LONG} MATCHES "^4$") +ENDIF(${SIZEOF_INT} MATCHES "^4$") + +IF(${SIZEOF_INT} MATCHES "^8$") + SET(U64 "unsigned") +ELSE(${SIZEOF_INT} MATCHES "^8$") + IF(${SIZEOF_LONG} MATCHES "^8$") + SET(U64 "unsigned long") + ENDIF(${SIZEOF_LONG} MATCHES "^8$") +ENDIF(${SIZEOF_INT} MATCHES "^8$") + +# Set an option to build FLTK with OpenGL support +SET(HAVE_GL 0) +OPTION(USE_OPENGL "OpenGL Support" ON) +# OTB Adds +MARK_AS_ADVANCED(USE_OPENGL) + +IF(USE_OPENGL) + FIND_PACKAGE(OpenGL) + IF(OPENGL_FOUND) + SET(HAVE_GL 1) + INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR}) + ENDIF(OPENGL_FOUND) +ENDIF(USE_OPENGL) + +# +# Perform the FLTK specific test with status output +# +MACRO(PERFORM_CMAKE_TEST FILE TEST) + IF("${TEST}" MATCHES "^${TEST}$") + # Perform test + SET(MACRO_CHECK_FUNCTION_DEFINITIONS + "-D${TEST} ${CMAKE_REQUIRED_FLAGS}") + IF(CMAKE_REQUIRED_LIBRARIES) + SET(TEST_ADD_LIBRARIES + "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}") + ENDIF(CMAKE_REQUIRED_LIBRARIES) + MESSAGE(STATUS "Performing Test ${TEST}") + + TRY_COMPILE(${TEST} + ${CMAKE_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} + CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} + -DLINK_LIBRARIES:STRING=${CMAKE_TEST_SPECIAL_LIBRARIES} + "${TEST_ADD_LIBRARIES}" + OUTPUT_VARIABLE OUTPUT) + IF(${TEST}) + SET(${TEST} 1 CACHE INTERNAL "CMake test ${FUNCTION}") + MESSAGE(STATUS "Performing Test ${TEST} - Success") + ELSE(${TEST}) + MESSAGE(STATUS "Performing Test ${TEST} - Failed") + SET(${TEST} 0 CACHE INTERNAL "Test ${FUNCTION}") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeError.log + "Performing Test ${TEST} failed with the following output:\n" + "${OUTPUT}\n" APPEND) + ENDIF(${TEST}) + ENDIF("${TEST}" MATCHES "^${TEST}$") +ENDMACRO(PERFORM_CMAKE_TEST FILE TEST) + +# Set an option to build the zlib library or not +OPTION(FLTK_USE_SYSTEM_ZLIB "Use's system zlib" OFF) +# OTB Adds +MARK_AS_ADVANCED(FLTK_USE_SYSTEM_ZLIBUS) +IF(FLTK_USE_SYSTEM_ZLIB) + IF(ZLIB_FOUND) + SET(CMAKE_TEST_SPECIAL_LIBRARIES ${ZLIB_LIBRARIES}) + SET(FLTK_ZLIB_LIBRARIES ${ZLIB_LIBRARIES}) + PERFORM_CMAKE_TEST(CMake/PlatformTests.cxx HAVE_LIBZ) + ENDIF(ZLIB_FOUND) + # We build the fltk zlib +ELSE(FLTK_USE_SYSTEM_ZLIB) + MARK_AS_ADVANCED(ZLIB_INCLUDE_DIR) + MARK_AS_ADVANCED(ZLIB_LIBRARY) + SUBDIRS(zlib) + SET(HAVE_LIBZ 1) + SET(FLTK_ZLIB_LIBRARIES fltk_zlib) + SET(FLTK_LIBRARIES "${FLTK_LIBRARIES};fltk_zlib") + INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/zlib") +ENDIF(FLTK_USE_SYSTEM_ZLIB) + +# Set an option to build the jpeg library or not +OPTION(FLTK_USE_SYSTEM_JPEG "Use's system jpeg" OFF) +# OTB Adds +MARK_AS_ADVANCED(FLTK_USE_SYSTEM_JPEG) + +IF(FLTK_USE_SYSTEM_JPEG) + IF(JPEG_FOUND) + SET(CMAKE_TEST_SPECIAL_LIBRARIES ${JPEG_LIBRARIES}) + SET(FLTK_JPEG_LIBRARIES ${JPEG_LIBRARIES}) + PERFORM_CMAKE_TEST(CMake/PlatformTests.cxx HAVE_LIBJPEG) + ENDIF(JPEG_FOUND) + # We build the fltk png +ELSE(FLTK_USE_SYSTEM_JPEG) + MARK_AS_ADVANCED(JPEG_INCLUDE_DIR) + MARK_AS_ADVANCED(JPEG_LIBRARY) + SUBDIRS(jpeg) + SET(HAVE_LIBJPEG 1) + SET(FLTK_JPEG_LIBRARIES fltk_jpeg) + SET(FLTK_LIBRARIES "${FLTK_LIBRARIES};fltk_jpeg") + INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/jpeg") +ENDIF(FLTK_USE_SYSTEM_JPEG) + +# Set an option to build the png library or not +OPTION(FLTK_USE_SYSTEM_PNG "Use's system png" OFF) +# OTB Adds +MARK_AS_ADVANCED(FLTK_USE_SYSTEM_PNG) +IF(FLTK_USE_SYSTEM_PNG) + IF(PNG_FOUND) + SET(CMAKE_TEST_SPECIAL_LIBRARIES ${PNG_LIBRARIES}) + SET(FLTK_PNG_LIBRARIES ${PNG_LIBRARIES}) + PERFORM_CMAKE_TEST(CMake/PlatformTests.cxx HAVE_LIBPNG) + PERFORM_CMAKE_TEST(CMake/PlatformTests.cxx HAVE_PNG_GET_VALID) + PERFORM_CMAKE_TEST(CMake/PlatformTests.cxx HAVE_PNG_SET_TRNS_TO_ALPHA) + SET(HAVE_PNG_H 1) + ENDIF(PNG_FOUND) + # We build the fltk png +ELSE(FLTK_USE_SYSTEM_PNG) + MARK_AS_ADVANCED(PNG_INCLUDE_DIR) + MARK_AS_ADVANCED(PNG_LIBRARY) + SUBDIRS(png) + SET(HAVE_LIBPNG 1) + SET(HAVE_PNG_H 1) + SET(FLTK_PNG_LIBRARIES fltk_png) + SET(FLTK_LIBRARIES "${FLTK_LIBRARIES};fltk_png") + INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/png") +ENDIF(FLTK_USE_SYSTEM_PNG) + +SET(FLTK_DATADIR "${CMAKE_INSTALL_PREFIX}/share/FLTK") +SET(FLTK_DOCDIR "${CMAKE_INSTALL_PREFIX}/share/doc/FLTK") + +# Write out configuration header file +CONFIGURE_FILE(${FLTK_SOURCE_DIR}/configh.cmake.in +# OTB Modifications: conflict name file with the OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h +# ${FLTK_BINARY_DIR}/config.h) + ${FLTK_BINARY_DIR}/fltk-config.h) + +# On unix create symlinks for backward compatibility +SET(FLTK_CREATE_SYMLINKS 1) +IF(WIN32) + IF(NOT UNIX) + SET(FLTK_CREATE_SYMLINKS 0) + ENDIF(NOT UNIX) +ENDIF(WIN32) + +MACRO(SAFE_CREATE_SYMLINK SOURCE DESTINATION) + IF(EXISTS "${DESTINATION}") + ELSE(EXISTS "${DESTINATION}") + MESSAGE(STATUS "Create symlink from: \"${SOURCE}\" to \"${DESTINATION}\"") + # The quoting here does seems unnatural, but this is to prevent bug in CMake + EXEC_PROGRAM(ln ARGS + "-s \"${SOURCE}\" \"${DESTINATION}\"" OUTPUT_VARIABLE ln_output + RETURN_VALUE ln_retval) + IF("${ln_retval}" GREATER 0) + MESSAGE(FATAL_ERROR "Problem creatin symlink from \"${SOURCE}\" to \"${DESTINATION}\":\n${ln_output}") + ENDIF("${ln_retval}" GREATER 0) + ENDIF(EXISTS "${DESTINATION}") +ENDMACRO(SAFE_CREATE_SYMLINK SOURCE DESTINATION) + +# If this is out-of-source build, then copy FL directory +FILE(GLOB FLTK_HEADER_FILES "${FLTK_SOURCE_DIR}/FL/*.[hHr]") +FOREACH(file ${FLTK_HEADER_FILES}) + GET_FILENAME_COMPONENT(ext "${file}" EXT) + GET_FILENAME_COMPONENT(namewe "${file}" NAME_WE) + GET_FILENAME_COMPONENT(name "${file}" NAME) + STRING(COMPARE EQUAL "${ext}" ".h" lower_case_h) + STRING(COMPARE EQUAL "${ext}" ".H" upper_case_h) + IF(lower_case_h OR upper_case_h) + SET(outfile_h "${FLTK_BINARY_DIR}/FL/${namewe}.h") + SET(outfile_H "${FLTK_BINARY_DIR}/FL/${namewe}.H") + CONFIGURE_FILE("${file}" "${outfile_H}" COPYONLY IMMEDIATE) + CONFIGURE_FILE("${file}" "${outfile_h}" COPYONLY IMMEDIATE) +# IF(FLTK_CREATE_SYMLINKS) +# SAFE_CREATE_SYMLINK("${outfile_H}" "${outfile_h}") +# ENDIF(FLTK_CREATE_SYMLINKS) + ELSE(lower_case_h OR upper_case_h) + STRING(COMPARE EQUAL "${ext}" ".r" mac_resource_file) + IF(mac_resource_file) + SET(outfile "${FLTK_BINARY_DIR}/FL/${name}") + CONFIGURE_FILE("${file}" "${outfile}" COPYONLY IMMEDIATE) + ENDIF(mac_resource_file) + ENDIF(lower_case_h OR upper_case_h) +ENDFOREACH(file) + +IF(FLTK_CREATE_SYMLINKS) + SAFE_CREATE_SYMLINK( + "${FLTK_BINARY_DIR}/FL" + "${FLTK_BINARY_DIR}/Fl") + + SAFE_CREATE_SYMLINK( + "${FLTK_BINARY_DIR}/FL/gl.H" + "${FLTK_BINARY_DIR}/FL/gl.h") + + # Create the symlinks + FILE(READ ${FLTK_SOURCE_DIR}/fltk.list.in SYMLINKSFILE) + STRING(REGEX MATCHALL "(l 0000 root sys .includedir/)([^(\n)])+" + SYMLINKS ${SYMLINKSFILE}) + FOREACH(var ${SYMLINKS} ) + IF("${var}" MATCHES ".H") + STRING(REGEX MATCH "(/F)([^(\n)])+" tmp ${var}) + STRING(REGEX MATCH "(/F)([^( )])+" in ${tmp}) + STRING(REGEX MATCH "( )([^(\n)])+" out ${tmp}) + STRING(REGEX REPLACE "( )" "" out ${out}) + SAFE_CREATE_SYMLINK("${FLTK_BINARY_DIR}/FL/${out}" "${FLTK_BINARY_DIR}/${in}") + ENDIF("${var}" MATCHES ".H") + ENDFOREACH(var) +ENDIF(FLTK_CREATE_SYMLINKS) + +# Set the fluid executable path +UTILITY_SOURCE(FLUID_COMMAND fluid fluid fluid.cxx) +SET(FLUID_COMMAND "${FLUID_COMMAND}" CACHE INTERNAL "" FORCE) + +# Include header files in fltk binary tree +INCLUDE_DIRECTORIES(${FLTK_BINARY_DIR}) + +# Do the build of fltk libraries and fluid +SUBDIRS(src) +SUBDIRS(fluid) + + +#----------------------------------------------------------------------------- +# Help outside projects build FLTK projects. +INCLUDE(CMakeExportBuildSettings) +EXPORT_LIBRARY_DEPENDENCIES(${FLTK_BINARY_DIR}/FLTKLibraryDepends.cmake) +CMAKE_EXPORT_BUILD_SETTINGS(${FLTK_BINARY_DIR}/FLTKBuildSettings.cmake) +SET(FL_MAJOR_VERSION "${FLTK_VERSION_MAJOR}") +SET(FL_MINOR_VERSION "${FLTK_VERSION_MINOR}") +SET(FL_PATCH_VERSION "${FLTK_VERSION_PATCH}") + +SET(CFLAGS "${CMAKE_C_FLAGS}") +SET(CXXFLAGS "${CMAKE_CXX_FLAGS}") +SET(CC "${CMAKE_C_COMPILER}") +SET(CXX "${CMAKE_CXX_COMPILER}") + +# For build tree usage +SET(FLTK_FLUID_COMMAND "${FLUID_COMMAND}") +SET(FLTK_LIBRARY_DEPENDS_FILE ${FLTK_BINARY_DIR}/FLTKLibraryDepends.cmake) +SET(FLTK_EXECUTABLE_DIRS ${EXECUTABLE_OUTPUT_PATH}) +SET(FLTK_LIBRARY_DIRS ${LIBRARY_OUTPUT_PATH}) +SET(FLTK_USE_FILE ${FLTK_SOURCE_DIR}/CMake/FLTKUse.cmake) +SET(FLTK_INCLUDE_DIRS "${FLTK_BINARY_DIR}/") +SET(FLTK_BUILD_SETTINGS_FILE ${FLTK_BINARY_DIR}/FLTKBuildSettings.cmake) +SET(prefix "${FLTK_BINARY_DIR}") +SET(exec_prefix "${prefix}") +SET(exec_prefix_set "no") +SET(bindir "${prefix}/bin") +SET(includedir "${prefix}") +SET(libdir "${prefix}/bin") +SET(srcdir "${FLTK_SOURCE_DIR}") + +CONFIGURE_FILE("${FLTK_SOURCE_DIR}/CMake/FLTKConfig.cmake.in" + "${FLTK_BINARY_DIR}/FLTKConfig.cmake" @ONLY IMMEDIATE) +CONFIGURE_FILE("${FLTK_SOURCE_DIR}/fltk-config.in" + "${FLTK_BINARY_DIR}/fltk-config" @ONLY IMMEDIATE) + +# For installed tree usage +SET(FLTK_FLUID_COMMAND "${CMAKE_INSTALL_PREFIX}/bin/fluid") +SET(FLTK_LIBRARY_DEPENDS_FILE ${CMAKE_INSTALL_PREFIX}/lib/FLTK-${FLTK_VERSION}/FLTKLibraryDepends.cmake) +SET(FLTK_EXECUTABLE_DIRS "${CMAKE_INSTALL_PREFIX}/bin") +SET(FLTK_LIBRARY_DIRS "${CMAKE_INSTALL_PREFIX}/lib") +SET(FLTK_USE_FILE "${CMAKE_INSTALL_PREFIX}/lib/FLTK-${FLTK_VERSION}/FLTKUse.cmake") +SET(FLTK_INCLUDE_DIRS "${CMAKE_INSTALL_PREFIX}/") +SET(FLTK_BUILD_SETTINGS_FILE ${CMAKE_INSTALL_PREFIX}/lib/FLTK-${FLTK_VERSION}/FLTKBuildSettings.cmake) +SET(prefix "${CMAKE_INSTALL_PREFIX}") +SET(exec_prefix "${prefix}") +SET(exec_prefix_set "no") +SET(bindir "${prefix}/bin") +SET(includedir "${prefix}") +SET(libdir "${prefix}/lib") +SET(srcdir ".") + +CONFIGURE_FILE("${FLTK_SOURCE_DIR}/CMake/FLTKConfig.cmake.in" + "${FLTK_BINARY_DIR}/CMake/FLTKConfig.cmake" @ONLY IMMEDIATE) +CONFIGURE_FILE("${FLTK_SOURCE_DIR}/fltk-config.in" + "${FLTK_BINARY_DIR}/CMake/fltk-config" @ONLY IMMEDIATE) + +INSTALL_FILES(/include/otb/Utilities/FLTK/FL FILES ${FLTK_HEADER_FILES}) +#INSTALL_FILES(/lib/FLTK-${FLTK_VERSION} FILES "${FLTK_SOURCE_DIR}/CMake/FLTKUse.cmake") +#INSTALL_FILES(/lib/FLTK-${FLTK_VERSION} FILES "${FLTK_BINARY_DIR}/FLTKBuildSettings.cmake") +#INSTALL_FILES(/lib/FLTK-${FLTK_VERSION} FILES "${FLTK_BINARY_DIR}/FLTKLibraryDepends.cmake") +#INSTALL_FILES(/lib/FLTK-${FLTK_VERSION} FILES "${FLTK_BINARY_DIR}/CMake/FLTKConfig.cmake") diff --git a/Utilities/FLTK/COPYING b/Utilities/FLTK/COPYING new file mode 100644 index 0000000000..0dd0e80d38 --- /dev/null +++ b/Utilities/FLTK/COPYING @@ -0,0 +1,528 @@ + FLTK License + December 11, 2001 + +The FLTK library and included programs are provided under the terms +of the GNU Library General Public License (LGPL) with the following +exceptions: + + 1. Modifications to the FLTK configure script, config + header file, and makefiles by themselves to support + a specific platform do not constitute a modified or + derivative work. + + The authors do request that such modifications be + contributed to the FLTK project - send all + contributions to "fltk-bugs@fltk.org". + + 2. Widgets that are subclassed from FLTK widgets do not + constitute a derivative work. + + 3. Static linking of applications and widgets to the + FLTK library does not constitute a derivative work + and does not require the author to provide source + code for the application or widget, use the shared + FLTK libraries, or link their applications or + widgets against a user-supplied version of FLTK. + + If you link the application or widget to a modified + version of FLTK, then the changes to FLTK must be + provided under the terms of the LGPL in sections + 1, 2, and 4. + + 4. You do not have to provide a copy of the FLTK license + with programs that are linked to the FLTK library, nor + do you have to identify the FLTK license in your + program or documentation as required by section 6 + of the LGPL. + + However, programs must still identify their use of FLTK. + The following example statement can be included in user + documentation to satisfy this requirement: + + [program/widget] is based in part on the work of + the FLTK project (http://www.fltk.org). + +----------------------------------------------------------------------- + + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + [This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. 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 not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library 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 +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/Utilities/FLTK/CREDITS b/Utilities/FLTK/CREDITS new file mode 100644 index 0000000000..b8aac7caa5 --- /dev/null +++ b/Utilities/FLTK/CREDITS @@ -0,0 +1,53 @@ +CREDITS - Fast Light Tool Kit (FLTK) Version 1.1.5 +-------------------------------------------------- + + This file lists the people responsible for the toolkit you + are now using. If you've looking for your name in lights + but we've forgotten you here, please send an email to + "fltk-bugs@fltk.org" and we'll update this file accordingly. + + +CORE DEVELOPERS + + The following people do the day-to-day development of FLTK: + + Craig P. Earls + Curtis Edwards (trilec@users.sourceforge.net) + Gustavo Hime (hime@users.sourceforge.net) + Talbot Hughes + Robert Kesterson (robertk@users.sourceforge.net) + Matthias Melcher (matthias@users.sourceforge.net) + James Dean Palmer (jamespalmer@users.sourceforge.net) + Vincent Penne (vincentp@users.sourceforge.net) + Bill Spitzak (spitzak@users.sourceforge.net) + Michael Sweet (easysw@users.sourceforge.net) + Carl Thompson (clip@users.sourceforge.net) + Nafees Bin Zafar (nafees@users.sourceforge.net) + + +OTHER CONTRIBUTORS + + The following people have contributed fixes or enhancements + for FLTK: + + Teun Burgers + Paul Chambers + Fabien Costantini + Stephen Davies + Greg Ercolano + Yuri Fedorchenko + George Garvey + Mikael Hultgren + Stuart Levy + Howard Lightstone + Mike Lindner + Alexander Mai + Alexander Rabi + James Roth + Albrecht Schlosser + Andrea Suatoni + Paul Sydney + Aaron Ucko + Emanuele Vicentini + Jim Wilson + Ken Yarnall diff --git a/Utilities/FLTK/DartConfig.cmake b/Utilities/FLTK/DartConfig.cmake new file mode 100644 index 0000000000..90e1ff6639 --- /dev/null +++ b/Utilities/FLTK/DartConfig.cmake @@ -0,0 +1,38 @@ +# Dashboard is opened for submissions for a 24 hour period starting at +# the specified NIGHLY_START_TIME. Time is specified in 24 hour format. +SET (NIGHTLY_START_TIME "21:00:00 EDT") + +# Dart server to submit results (used by client) +SET (DROP_METHOD "http") +SET (DROP_SITE "public.kitware.com") +SET (DROP_LOCATION "/cgi-bin/HTTPUploadDartFile.cgi") +SET (TRIGGER_SITE "http://${DROP_SITE}/cgi-bin/Submit-Fltk-TestingResults.pl") + +# Project Home Page +SET (PROJECT_URL "http://www.fltk.org") + +# Dart server configuration +SET (ROLLUP_URL "http://${DROP_SITE}/cgi-bin/fltk-rollup-dashboard.sh") +SET (CVS_WEB_URL "http://cvs.sourceforge.net/viewcvs.py/fltk/fltk/") +SET (CVS_WEB_CVSROOT "fltk") + +SET (USE_GNATS "On") +SET (GNATS_WEB_URL "http://www.fltk.org/str.php") + +# Continuous email delivery variables +SET (CONTINUOUS_FROM "fltk-dashboard@public.kitware.com") +SET (SMTP_MAILHOST "public.kitware.com") +SET (CONTINUOUS_MONITOR_LIST "fltk-dashboard@public.kitware.com") +SET (CONTINUOUS_BASE_URL "http://public.kitware.com/Fltk/Testing") + +SET (DELIVER_BROKEN_BUILD_EMAIL_WITH_TEST_FAILURES ON) +SET (DELIVER_BROKEN_BUILD_EMAIL "Continuous Nightly") +SET (EMAIL_FROM "fltk-dashboard@public.kitware.com") +SET (DARTBOARD_BASE_URL "http://public.kitware.com/Fltk/Testing") + +SET (DELIVER_BROKEN_BUILD_EMAIL_WITH_CONFIGURE_FAILURES 1) +SET (DELIVER_BROKEN_BUILD_EMAIL_WITH_BUILD_ERRORS 1) +SET (DELIVER_BROKEN_BUILD_EMAIL_WITH_BUILD_WARNINGS 1) +SET (DELIVER_BROKEN_BUILD_EMAIL_WITH_TEST_NOT_RUNS 1) +SET (DELIVER_BROKEN_BUILD_EMAIL_WITH_TEST_FAILURES 1) + diff --git a/Utilities/FLTK/FL/Enumerations.H b/Utilities/FLTK/FL/Enumerations.H new file mode 100644 index 0000000000..4c3337cacd --- /dev/null +++ b/Utilities/FLTK/FL/Enumerations.H @@ -0,0 +1,428 @@ +// +// "$Id: Enumerations.H 4288 2005-04-16 00:13:17Z mike $" +// +// Enumerations for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Enumerations_H +#define Fl_Enumerations_H + +# include "Fl_Export.H" + + +// +// The FLTK version number; this is changed slightly from the beta versions +// because the old "const double" definition would not allow for conditional +// compilation... +// +// FL_VERSION is a double that describes the major and minor version numbers. +// Version 1.1 is actually stored as 1.01 to allow for more than 9 minor +// releases. +// +// The FL_MAJOR_VERSION, FL_MINOR_VERSION, and FL_PATCH_VERSION constants +// give the integral values for the major, minor, and patch releases +// respectively. +// + +#define FL_MAJOR_VERSION 1 +#define FL_MINOR_VERSION 1 +#define FL_PATCH_VERSION 7 +#define FL_VERSION ((double)FL_MAJOR_VERSION + \ + (double)FL_MINOR_VERSION * 0.01 + \ + (double)FL_PATCH_VERSION * 0.0001) + +typedef unsigned char uchar; +typedef unsigned long ulong; + +enum Fl_Event { // events + FL_NO_EVENT = 0, + FL_PUSH = 1, + FL_RELEASE = 2, + FL_ENTER = 3, + FL_LEAVE = 4, + FL_DRAG = 5, + FL_FOCUS = 6, + FL_UNFOCUS = 7, + FL_KEYDOWN = 8, + FL_KEYUP = 9, + FL_CLOSE = 10, + FL_MOVE = 11, + FL_SHORTCUT = 12, + FL_DEACTIVATE = 13, + FL_ACTIVATE = 14, + FL_HIDE = 15, + FL_SHOW = 16, + FL_PASTE = 17, + FL_SELECTIONCLEAR = 18, + FL_MOUSEWHEEL = 19, + FL_DND_ENTER = 20, + FL_DND_DRAG = 21, + FL_DND_LEAVE = 22, + FL_DND_RELEASE = 23 +}; +#define FL_KEYBOARD FL_KEYDOWN + +enum Fl_When { // Fl_Widget::when(): + FL_WHEN_NEVER = 0, + FL_WHEN_CHANGED = 1, + FL_WHEN_RELEASE = 4, + FL_WHEN_RELEASE_ALWAYS= 6, + FL_WHEN_ENTER_KEY = 8, + FL_WHEN_ENTER_KEY_ALWAYS=10, + FL_WHEN_ENTER_KEY_CHANGED=11, + FL_WHEN_NOT_CHANGED = 2 // modifier bit to disable changed() test +}; + +// Fl::event_key() and Fl::get_key(n) (use ascii letters for all other keys): +#define FL_Button 0xfee8 // use Fl_Button+FL_*_MOUSE +#define FL_BackSpace 0xff08 +#define FL_Tab 0xff09 +#define FL_Enter 0xff0d +#define FL_Pause 0xff13 +#define FL_Scroll_Lock 0xff14 +#define FL_Escape 0xff1b +#define FL_Home 0xff50 +#define FL_Left 0xff51 +#define FL_Up 0xff52 +#define FL_Right 0xff53 +#define FL_Down 0xff54 +#define FL_Page_Up 0xff55 +#define FL_Page_Down 0xff56 +#define FL_End 0xff57 +#define FL_Print 0xff61 +#define FL_Insert 0xff63 +#define FL_Menu 0xff67 // the "menu/apps" key on XFree86 +#define FL_Help 0xff68 // the 'help' key on Mac keyboards +#define FL_Num_Lock 0xff7f +#define FL_KP 0xff80 // use FL_KP+'x' for 'x' on numeric keypad +#define FL_KP_Enter 0xff8d // same as Fl_KP+'\r' +#define FL_KP_Last 0xffbd // use to range-check keypad +#define FL_F 0xffbd // use FL_F+n for function key n +#define FL_F_Last 0xffe0 // use to range-check function keys +#define FL_Shift_L 0xffe1 +#define FL_Shift_R 0xffe2 +#define FL_Control_L 0xffe3 +#define FL_Control_R 0xffe4 +#define FL_Caps_Lock 0xffe5 +#define FL_Meta_L 0xffe7 // the left MSWindows key on XFree86 +#define FL_Meta_R 0xffe8 // the right MSWindows key on XFree86 +#define FL_Alt_L 0xffe9 +#define FL_Alt_R 0xffea +#define FL_Delete 0xffff + +// Fl::event_button(): +#define FL_LEFT_MOUSE 1 +#define FL_MIDDLE_MOUSE 2 +#define FL_RIGHT_MOUSE 3 + +// Fl::event_state(): +#define FL_SHIFT 0x00010000 +#define FL_CAPS_LOCK 0x00020000 +#define FL_CTRL 0x00040000 +#define FL_ALT 0x00080000 +#define FL_NUM_LOCK 0x00100000 // most X servers do this? +#define FL_META 0x00400000 // correct for XFree86 +#define FL_SCROLL_LOCK 0x00800000 // correct for XFree86 +#define FL_BUTTON1 0x01000000 +#define FL_BUTTON2 0x02000000 +#define FL_BUTTON3 0x04000000 +#define FL_BUTTONS 0x7f000000 // All possible buttons +#define FL_BUTTON(n) (0x00800000<<(n)) + +#ifdef __APPLE__ +# define FL_COMMAND FL_META +#else +# define FL_COMMAND FL_CTRL +#endif // __APPLE__ + +enum Fl_Boxtype { // boxtypes (if you change these you must fix fl_boxtype.C): + FL_NO_BOX = 0, FL_FLAT_BOX, + + FL_UP_BOX, FL_DOWN_BOX, + FL_UP_FRAME, FL_DOWN_FRAME, + FL_THIN_UP_BOX, FL_THIN_DOWN_BOX, + FL_THIN_UP_FRAME, FL_THIN_DOWN_FRAME, + FL_ENGRAVED_BOX, FL_EMBOSSED_BOX, + FL_ENGRAVED_FRAME, FL_EMBOSSED_FRAME, + FL_BORDER_BOX, _FL_SHADOW_BOX, + FL_BORDER_FRAME, _FL_SHADOW_FRAME, + _FL_ROUNDED_BOX, _FL_RSHADOW_BOX, + _FL_ROUNDED_FRAME, _FL_RFLAT_BOX, + _FL_ROUND_UP_BOX, _FL_ROUND_DOWN_BOX, + _FL_DIAMOND_UP_BOX, _FL_DIAMOND_DOWN_BOX, + _FL_OVAL_BOX, _FL_OSHADOW_BOX, + _FL_OVAL_FRAME, _FL_OFLAT_BOX, + _FL_PLASTIC_UP_BOX, _FL_PLASTIC_DOWN_BOX, + _FL_PLASTIC_UP_FRAME, _FL_PLASTIC_DOWN_FRAME, + _FL_PLASTIC_THIN_UP_BOX, _FL_PLASTIC_THIN_DOWN_BOX, + _FL_PLASTIC_ROUND_UP_BOX, _FL_PLASTIC_ROUND_DOWN_BOX, + FL_FREE_BOXTYPE +}; +extern FL_EXPORT Fl_Boxtype fl_define_FL_ROUND_UP_BOX(); +#define FL_ROUND_UP_BOX fl_define_FL_ROUND_UP_BOX() +#define FL_ROUND_DOWN_BOX (Fl_Boxtype)(fl_define_FL_ROUND_UP_BOX()+1) +extern FL_EXPORT Fl_Boxtype fl_define_FL_SHADOW_BOX(); +#define FL_SHADOW_BOX fl_define_FL_SHADOW_BOX() +#define FL_SHADOW_FRAME (Fl_Boxtype)(fl_define_FL_SHADOW_BOX()+2) +extern FL_EXPORT Fl_Boxtype fl_define_FL_ROUNDED_BOX(); +#define FL_ROUNDED_BOX fl_define_FL_ROUNDED_BOX() +#define FL_ROUNDED_FRAME (Fl_Boxtype)(fl_define_FL_ROUNDED_BOX()+2) +extern FL_EXPORT Fl_Boxtype fl_define_FL_RFLAT_BOX(); +#define FL_RFLAT_BOX fl_define_FL_RFLAT_BOX() +extern FL_EXPORT Fl_Boxtype fl_define_FL_RSHADOW_BOX(); +#define FL_RSHADOW_BOX fl_define_FL_RSHADOW_BOX() +extern FL_EXPORT Fl_Boxtype fl_define_FL_DIAMOND_BOX(); +#define FL_DIAMOND_UP_BOX fl_define_FL_DIAMOND_BOX() +#define FL_DIAMOND_DOWN_BOX (Fl_Boxtype)(fl_define_FL_DIAMOND_BOX()+1) +extern FL_EXPORT Fl_Boxtype fl_define_FL_OVAL_BOX(); +#define FL_OVAL_BOX fl_define_FL_OVAL_BOX() +#define FL_OSHADOW_BOX (Fl_Boxtype)(fl_define_FL_OVAL_BOX()+1) +#define FL_OVAL_FRAME (Fl_Boxtype)(fl_define_FL_OVAL_BOX()+2) +#define FL_OFLAT_BOX (Fl_Boxtype)(fl_define_FL_OVAL_BOX()+3) + +extern FL_EXPORT Fl_Boxtype fl_define_FL_PLASTIC_UP_BOX(); +#define FL_PLASTIC_UP_BOX fl_define_FL_PLASTIC_UP_BOX() +#define FL_PLASTIC_DOWN_BOX (Fl_Boxtype)(fl_define_FL_PLASTIC_UP_BOX()+1) +#define FL_PLASTIC_UP_FRAME (Fl_Boxtype)(fl_define_FL_PLASTIC_UP_BOX()+2) +#define FL_PLASTIC_DOWN_FRAME (Fl_Boxtype)(fl_define_FL_PLASTIC_UP_BOX()+3) +#define FL_PLASTIC_THIN_UP_BOX (Fl_Boxtype)(fl_define_FL_PLASTIC_UP_BOX()+4) +#define FL_PLASTIC_THIN_DOWN_BOX (Fl_Boxtype)(fl_define_FL_PLASTIC_UP_BOX()+5) +#define FL_PLASTIC_ROUND_UP_BOX (Fl_Boxtype)(fl_define_FL_PLASTIC_UP_BOX()+6) +#define FL_PLASTIC_ROUND_DOWN_BOX (Fl_Boxtype)(fl_define_FL_PLASTIC_UP_BOX()+7) + +// conversions of box types to other boxtypes: +inline Fl_Boxtype fl_down(Fl_Boxtype b) {return (Fl_Boxtype)(b|1);} +inline Fl_Boxtype fl_frame(Fl_Boxtype b) {return (Fl_Boxtype)(b|2);} + +// back-compatability box types: +#define FL_FRAME FL_ENGRAVED_FRAME +#define FL_FRAME_BOX FL_ENGRAVED_BOX +#define FL_CIRCLE_BOX FL_ROUND_DOWN_BOX +#define FL_DIAMOND_BOX FL_DIAMOND_DOWN_BOX + +enum Fl_Labeltype { // labeltypes: + FL_NORMAL_LABEL = 0, + FL_NO_LABEL, + _FL_SHADOW_LABEL, + _FL_ENGRAVED_LABEL, + _FL_EMBOSSED_LABEL, + _FL_MULTI_LABEL, + _FL_ICON_LABEL, + _FL_IMAGE_LABEL, + + FL_FREE_LABELTYPE +}; +#define FL_SYMBOL_LABEL FL_NORMAL_LABEL +extern Fl_Labeltype FL_EXPORT fl_define_FL_SHADOW_LABEL(); +#define FL_SHADOW_LABEL fl_define_FL_SHADOW_LABEL() +extern Fl_Labeltype FL_EXPORT fl_define_FL_ENGRAVED_LABEL(); +#define FL_ENGRAVED_LABEL fl_define_FL_ENGRAVED_LABEL() +extern Fl_Labeltype FL_EXPORT fl_define_FL_EMBOSSED_LABEL(); +#define FL_EMBOSSED_LABEL fl_define_FL_EMBOSSED_LABEL() + +enum Fl_Align { // align() values + FL_ALIGN_CENTER = 0, + FL_ALIGN_TOP = 1, + FL_ALIGN_BOTTOM = 2, + FL_ALIGN_LEFT = 4, + FL_ALIGN_RIGHT = 8, + FL_ALIGN_INSIDE = 16, + FL_ALIGN_TEXT_OVER_IMAGE = 32, + FL_ALIGN_IMAGE_OVER_TEXT = 0, + FL_ALIGN_CLIP = 64, + FL_ALIGN_WRAP = 128, + FL_ALIGN_TOP_LEFT = FL_ALIGN_TOP | FL_ALIGN_LEFT, + FL_ALIGN_TOP_RIGHT = FL_ALIGN_TOP | FL_ALIGN_RIGHT, + FL_ALIGN_BOTTOM_LEFT = FL_ALIGN_BOTTOM | FL_ALIGN_LEFT, + FL_ALIGN_BOTTOM_RIGHT = FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT, + FL_ALIGN_LEFT_TOP = FL_ALIGN_TOP_LEFT, + FL_ALIGN_RIGHT_TOP = FL_ALIGN_TOP_RIGHT, + FL_ALIGN_LEFT_BOTTOM = FL_ALIGN_BOTTOM_LEFT, + FL_ALIGN_RIGHT_BOTTOM = FL_ALIGN_BOTTOM_RIGHT, + FL_ALIGN_NOWRAP = 0 // for back compatability +}; + +enum Fl_Font { // standard fonts + FL_HELVETICA = 0, + FL_HELVETICA_BOLD, + FL_HELVETICA_ITALIC, + FL_HELVETICA_BOLD_ITALIC, + FL_COURIER, + FL_COURIER_BOLD, + FL_COURIER_ITALIC, + FL_COURIER_BOLD_ITALIC, + FL_TIMES, + FL_TIMES_BOLD, + FL_TIMES_ITALIC, + FL_TIMES_BOLD_ITALIC, + FL_SYMBOL, + FL_SCREEN, + FL_SCREEN_BOLD, + FL_ZAPF_DINGBATS, + + FL_FREE_FONT = 16, // first one to allocate + FL_BOLD = 1, // add this to helvetica, courier, or times + FL_ITALIC = 2 // add this to helvetica, courier, or times +}; + +extern FL_EXPORT int FL_NORMAL_SIZE; + +enum Fl_Color { // standard colors + // These are used as default colors in widgets and altered as necessary + FL_FOREGROUND_COLOR = 0, + FL_BACKGROUND2_COLOR = 7, + FL_INACTIVE_COLOR = 8, + FL_SELECTION_COLOR = 15, + + // boxtypes generally limit themselves to these colors so + // the whole ramp is not allocated: + FL_GRAY0 = 32, // 'A' + FL_DARK3 = 39, // 'H' + FL_DARK2 = 45, // 'N' + FL_DARK1 = 47, // 'P' + FL_BACKGROUND_COLOR = 49, // 'R' default background color + FL_LIGHT1 = 50, // 'S' + FL_LIGHT2 = 52, // 'U' + FL_LIGHT3 = 54, // 'W' + + // FLTK provides a 5x8x5 color cube that is used with colormap visuals + FL_BLACK = 56, + FL_RED = 88, + FL_GREEN = 63, + FL_YELLOW = 95, + FL_BLUE = 216, + FL_MAGENTA = 248, + FL_CYAN = 223, + FL_DARK_RED = 72, + + FL_DARK_GREEN = 60, + FL_DARK_YELLOW = 76, + FL_DARK_BLUE = 136, + FL_DARK_MAGENTA = 152, + FL_DARK_CYAN = 140, + + FL_WHITE = 255 +}; + +#define FL_FREE_COLOR (Fl_Color)16 +#define FL_NUM_FREE_COLOR 16 +#define FL_GRAY_RAMP (Fl_Color)32 +#define FL_NUM_GRAY 24 +#define FL_GRAY FL_BACKGROUND_COLOR +#define FL_COLOR_CUBE (Fl_Color)56 +#define FL_NUM_RED 5 +#define FL_NUM_GREEN 8 +#define FL_NUM_BLUE 5 + +FL_EXPORT Fl_Color fl_inactive(Fl_Color c); +FL_EXPORT Fl_Color fl_contrast(Fl_Color fg, Fl_Color bg); +FL_EXPORT Fl_Color fl_color_average(Fl_Color c1, Fl_Color c2, float weight); +inline Fl_Color fl_lighter(Fl_Color c) { return fl_color_average(c, FL_WHITE, .67f); } +inline Fl_Color fl_darker(Fl_Color c) { return fl_color_average(c, FL_BLACK, .67f); } +inline Fl_Color fl_rgb_color(uchar r, uchar g, uchar b) { + if (!r && !g && !b) return FL_BLACK; + else return (Fl_Color)(((((r << 8) | g) << 8) | b) << 8); +} +inline Fl_Color fl_rgb_color(uchar g) { + if (!g) return FL_BLACK; + else return (Fl_Color)(((((g << 8) | g) << 8) | g) << 8); +} +inline Fl_Color fl_gray_ramp(int i) {return (Fl_Color)(i+FL_GRAY_RAMP);} +inline Fl_Color fl_color_cube(int r, int g, int b) { + return (Fl_Color)((b*FL_NUM_RED + r) * FL_NUM_GREEN + g + FL_COLOR_CUBE);} + +enum Fl_Cursor { // standard cursors + FL_CURSOR_DEFAULT = 0, + FL_CURSOR_ARROW = 35, + FL_CURSOR_CROSS = 66, + FL_CURSOR_WAIT = 76, + FL_CURSOR_INSERT = 77, + FL_CURSOR_HAND = 31, + FL_CURSOR_HELP = 47, + FL_CURSOR_MOVE = 27, + // fltk provides bitmaps for these: + FL_CURSOR_NS = 78, + FL_CURSOR_WE = 79, + FL_CURSOR_NWSE = 80, + FL_CURSOR_NESW = 81, + FL_CURSOR_NONE = 255, + // for back compatability (non MSWindows ones): + FL_CURSOR_N = 70, + FL_CURSOR_NE = 69, + FL_CURSOR_E = 49, + FL_CURSOR_SE = 8, + FL_CURSOR_S = 9, + FL_CURSOR_SW = 7, + FL_CURSOR_W = 36, + FL_CURSOR_NW = 68 + //FL_CURSOR_NS = 22, + //FL_CURSOR_WE = 55, +}; + +enum { // values for "when" passed to Fl::add_fd() + FL_READ = 1, + FL_WRITE = 4, + FL_EXCEPT = 8 +}; + +enum Fl_Mode { // visual types and Fl_Gl_Window::mode() (values match Glut) + FL_RGB = 0, + FL_INDEX = 1, + FL_SINGLE = 0, + FL_DOUBLE = 2, + FL_ACCUM = 4, + FL_ALPHA = 8, + FL_DEPTH = 16, + FL_STENCIL = 32, + FL_RGB8 = 64, + FL_MULTISAMPLE= 128, + FL_STEREO = 256, + FL_FAKE_SINGLE = 512 // Fake single buffered windows using double-buffer +}; + +// damage masks + +enum Fl_Damage { + FL_DAMAGE_CHILD = 0x01, + FL_DAMAGE_EXPOSE = 0x02, + FL_DAMAGE_SCROLL = 0x04, + FL_DAMAGE_OVERLAY = 0x08, + FL_DAMAGE_USER1 = 0x10, + FL_DAMAGE_USER2 = 0x20, + FL_DAMAGE_ALL = 0x80 +}; + +// FLTK 1.0.x compatibility definitions... +# ifdef FLTK_1_0_COMPAT +# define contrast fl_contrast +# define down fl_down +# define frame fl_frame +# define inactive fl_inactive +# endif // FLTK_1_0_COMPAT + +#endif + +// +// End of "$Id: Enumerations.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl.H b/Utilities/FLTK/FL/Fl.H new file mode 100644 index 0000000000..455ed42ce3 --- /dev/null +++ b/Utilities/FLTK/FL/Fl.H @@ -0,0 +1,280 @@ +// +// "$Id: Fl.H 4223 2005-03-31 16:01:24Z mike $" +// +// Main header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_H +# define Fl_H + +# include "Enumerations.H" +# ifndef Fl_Object +# define Fl_Object Fl_Widget +# endif + +# ifdef check +# undef check +# endif + +class Fl_Widget; +class Fl_Window; +class Fl_Image; +struct Fl_Label; +typedef void (Fl_Label_Draw_F)(const Fl_Label*, int,int,int,int, Fl_Align); +typedef void (Fl_Label_Measure_F)(const Fl_Label*, int&, int&); +typedef void (Fl_Box_Draw_F)(int,int,int,int, Fl_Color); + +typedef void (*Fl_Timeout_Handler)(void*); + +class FL_EXPORT Fl { + Fl() {}; // no constructor! + +public: // should be private! + + static int e_number; + static int e_x; + static int e_y; + static int e_x_root; + static int e_y_root; + static int e_dx; + static int e_dy; + static int e_state; + static int e_clicks; + static int e_is_click; + static int e_keysym; + static char* e_text; + static int e_length; + static Fl_Widget* belowmouse_; + static Fl_Widget* pushed_; + static Fl_Widget* focus_; + static int damage_; + static Fl_Widget* selection_owner_; + static Fl_Window* modal_; + static Fl_Window* grab_; + static int compose_state; + static int visible_focus_; + static int dnd_text_ops_; + static void damage(int d) {damage_ = d;} + + static void (*idle)(); + + static const char* scheme_; + static Fl_Image* scheme_bg_; + +public: + + // API version number + static double version(); + + // argument parsers: + static int arg(int, char**, int&); + static int args(int, char**, int&, int (*)(int,char**,int&) = 0); + static const char* const help; + static void args(int, char**); + + // things called by initialization: + static void display(const char*); + static int visual(int); + static int gl_visual(int, int *alist=0); + static void own_colormap(); + static void get_system_colors(); + static void foreground(uchar, uchar, uchar); + static void background(uchar, uchar, uchar); + static void background2(uchar, uchar, uchar); + + // schemes: + static int scheme(const char*); + static const char* scheme() {return scheme_;} + static int reload_scheme(); + + // execution: + static int wait(); + static double wait(double time); + static int check(); + static int ready(); + static int run(); + static Fl_Widget* readqueue(); + static void add_timeout(double t, Fl_Timeout_Handler,void* = 0); + static void repeat_timeout(double t, Fl_Timeout_Handler,void* = 0); + static int has_timeout(Fl_Timeout_Handler, void* = 0); + static void remove_timeout(Fl_Timeout_Handler, void* = 0); + static void add_check(Fl_Timeout_Handler, void* = 0); + static int has_check(Fl_Timeout_Handler, void* = 0); + static void remove_check(Fl_Timeout_Handler, void* = 0); + static void add_fd(int fd, int when, void (*cb)(int,void*),void* =0); + static void add_fd(int fd, void (*cb)(int, void*), void* = 0); + static void remove_fd(int, int when); + static void remove_fd(int); + static void add_idle(void (*cb)(void*), void* = 0); + static int has_idle(void (*cb)(void*), void* = 0); + static void remove_idle(void (*cb)(void*), void* = 0); + static int damage() {return damage_;} + static void redraw(); + static void flush(); + static void (*warning)(const char*, ...); + static void (*error)(const char*, ...); + static void (*fatal)(const char*, ...); + static Fl_Window* first_window(); + static void first_window(Fl_Window*); + static Fl_Window* next_window(const Fl_Window*); + static Fl_Window* modal() {return modal_;} + static Fl_Window* grab() {return grab_;} + static void grab(Fl_Window*); + + // event information: + static int event() {return e_number;} + static int event_x() {return e_x;} + static int event_y() {return e_y;} + static int event_x_root() {return e_x_root;} + static int event_y_root() {return e_y_root;} + static int event_dx() {return e_dx;} + static int event_dy() {return e_dy;} + static void get_mouse(int &,int &); + static int event_clicks() {return e_clicks;} + static void event_clicks(int i) {e_clicks = i;} + static int event_is_click() {return e_is_click;} + static void event_is_click(int i) {e_is_click = i;} // only 0 works! + static int event_button() {return e_keysym-FL_Button;} + static int event_state() {return e_state;} + static int event_state(int i) {return e_state&i;} + static int event_key() {return e_keysym;} + static int event_key(int); + static int get_key(int); + static const char* event_text() {return e_text;} + static int event_length() {return e_length;} + static int compose(int &del); + static void compose_reset() {compose_state = 0;} + static int event_inside(int,int,int,int); + static int event_inside(const Fl_Widget*); + static int test_shortcut(int); + + // event destinations: + static int handle(int, Fl_Window*); + static Fl_Widget* belowmouse() {return belowmouse_;} + static void belowmouse(Fl_Widget*); + static Fl_Widget* pushed() {return pushed_;} + static void pushed(Fl_Widget*); + static Fl_Widget* focus() {return focus_;} + static void focus(Fl_Widget*); + static void add_handler(int (*h)(int)); + static void remove_handler(int (*h)(int)); + + // cut/paste: + static void copy(const char* stuff, int len, int clipboard = 0); + static void paste(Fl_Widget &receiver, int clipboard /*=0*/); + static int dnd(); + // These are for back-compatability only: + static Fl_Widget* selection_owner() {return selection_owner_;} + static void selection_owner(Fl_Widget*); + static void selection(Fl_Widget &owner, const char*, int len); + static void paste(Fl_Widget &receiver); + + // screen size: +#if defined(WIN32) || defined(__APPLE__) + static int x(); + static int y(); +#else + static int x() {return 0;} + static int y() {return 0;} +#endif /* WIN32 || __APPLE__ */ + static int w(); + static int h(); + + // multi-head support: + static int screen_count(); + static void screen_xywh(int &x, int &y, int &w, int &h) { + screen_xywh(x, y, w, h, e_x_root, e_y_root); + } + static void screen_xywh(int &x, int &y, int &w, int &h, int mx, int my); + static void screen_xywh(int &x, int &y, int &w, int &h, int n); + + // color map: + static void set_color(Fl_Color, uchar, uchar, uchar); + static void set_color(Fl_Color, unsigned); + static unsigned get_color(Fl_Color); + static void get_color(Fl_Color, uchar&, uchar&, uchar&); + static void free_color(Fl_Color, int overlay = 0); + + // fonts: + static const char* get_font(Fl_Font); + static const char* get_font_name(Fl_Font, int* attributes = 0); + static int get_font_sizes(Fl_Font, int*& sizep); + static void set_font(Fl_Font, const char*); + static void set_font(Fl_Font, Fl_Font); + static Fl_Font set_fonts(const char* = 0); + + // labeltypes: + static void set_labeltype(Fl_Labeltype,Fl_Label_Draw_F*,Fl_Label_Measure_F*); + static void set_labeltype(Fl_Labeltype, Fl_Labeltype from); + + // boxtypes: + static Fl_Box_Draw_F *get_boxtype(Fl_Boxtype); + static void set_boxtype(Fl_Boxtype, Fl_Box_Draw_F*,uchar,uchar,uchar,uchar); + static void set_boxtype(Fl_Boxtype, Fl_Boxtype from); + static int box_dx(Fl_Boxtype); + static int box_dy(Fl_Boxtype); + static int box_dw(Fl_Boxtype); + static int box_dh(Fl_Boxtype); + static int draw_box_active(); + + // back compatability: + static void set_abort(void (*f)(const char*,...)) {fatal = f;} + static void (*atclose)(Fl_Window*,void*); + static void default_atclose(Fl_Window*,void*); + static void set_atclose(void (*f)(Fl_Window*,void*)) {atclose = f;} + static int event_shift() {return e_state&FL_SHIFT;} + static int event_ctrl() {return e_state&FL_CTRL;} + static int event_alt() {return e_state&FL_ALT;} + static int event_buttons() {return e_state&0x7f000000;} + static int event_button1() {return e_state&FL_BUTTON1;} + static int event_button2() {return e_state&FL_BUTTON2;} + static int event_button3() {return e_state&FL_BUTTON3;} + static void set_idle(void (*cb)()) {idle = cb;} + static void grab(Fl_Window&win) {grab(&win);} + static void release() {grab(0);} + + // Visible focus methods... + static void visible_focus(int v) { visible_focus_ = v; } + static int visible_focus() { return visible_focus_; } + + // Drag-n-drop text operation methods... + static void dnd_text_ops(int v) { dnd_text_ops_ = v; } + static int dnd_text_ops() { return dnd_text_ops_; } + + // Multithreading support: + static void lock(); + static void unlock(); + static void awake(void* message = 0); + static void* thread_message(); + + // Widget deletion: + static void delete_widget(Fl_Widget *w); + static void do_widget_deletion(); +}; + +#endif // !Fl_H + +// +// End of "$Id: Fl.H 4223 2005-03-31 16:01:24Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Adjuster.H b/Utilities/FLTK/FL/Fl_Adjuster.H new file mode 100644 index 0000000000..466283ae8a --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Adjuster.H @@ -0,0 +1,55 @@ +// +// "$Id: Fl_Adjuster.H 4288 2005-04-16 00:13:17Z mike $" +// +// Adjuster widget header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// 3-button "slider", made for Nuke + +#ifndef Fl_Adjuster_H +#define Fl_Adjuster_H + +#ifndef Fl_Valuator_H +#include "Fl_Valuator.H" +#endif + +class FL_EXPORT Fl_Adjuster : public Fl_Valuator { + int drag; + int ix; + int soft_; +protected: + void draw(); + int handle(int); + void value_damage(); +public: + Fl_Adjuster(int X,int Y,int W,int H,const char *l=0); + void soft(int s) {soft_ = s;} + int soft() const {return soft_;} +}; + +#endif + +// +// End of "$Id: Fl_Adjuster.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_BMP_Image.H b/Utilities/FLTK/FL/Fl_BMP_Image.H new file mode 100644 index 0000000000..30bdcc4e7b --- /dev/null +++ b/Utilities/FLTK/FL/Fl_BMP_Image.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_BMP_Image.H 4288 2005-04-16 00:13:17Z mike $" +// +// BMP image header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_BMP_Image_H +#define Fl_BMP_Image_H +# include "Fl_Image.H" + +class FL_EXPORT Fl_BMP_Image : public Fl_RGB_Image { + + public: + + Fl_BMP_Image(const char* filename); +}; + +#endif + +// +// End of "$Id: Fl_BMP_Image.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Bitmap.H b/Utilities/FLTK/FL/Fl_Bitmap.H new file mode 100644 index 0000000000..e8686b09de --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Bitmap.H @@ -0,0 +1,64 @@ +// +// "$Id: Fl_Bitmap.H 4288 2005-04-16 00:13:17Z mike $" +// +// Bitmap header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Bitmap_H +#define Fl_Bitmap_H +# include "Fl_Image.H" + +class Fl_Widget; +struct Fl_Menu_Item; + +class FL_EXPORT Fl_Bitmap : public Fl_Image { + public: + + const uchar *array; + int alloc_array; // Non-zero if data was allocated +#if defined(__APPLE__) || defined(WIN32) + void *id; // for internal use +#else + unsigned id; // for internal use +#endif // __APPLE__ || WIN32 + + Fl_Bitmap(const uchar *bits, int W, int H) : + Fl_Image(W,H,0), array(bits), alloc_array(0), id(0) {data((const char **)&array, 1);} + Fl_Bitmap(const char *bits, int W, int H) : + Fl_Image(W,H,0), array((const uchar *)bits), alloc_array(0), id(0) {data((const char **)&array, 1);} + virtual ~Fl_Bitmap(); + virtual Fl_Image *copy(int W, int H); + Fl_Image *copy() { return copy(w(), h()); } + virtual void draw(int X, int Y, int W, int H, int cx=0, int cy=0); + void draw(int X, int Y) {draw(X, Y, w(), h(), 0, 0);} + virtual void label(Fl_Widget*w); + virtual void label(Fl_Menu_Item*m); + virtual void uncache(); +}; + +#endif + +// +// End of "$Id: Fl_Bitmap.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Box.H b/Utilities/FLTK/FL/Fl_Box.H new file mode 100644 index 0000000000..36fdc0f0cf --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Box.H @@ -0,0 +1,51 @@ +// +// "$Id: Fl_Box.H 4288 2005-04-16 00:13:17Z mike $" +// +// Box header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Box_H +#define Fl_Box_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +class FL_EXPORT Fl_Box : public Fl_Widget { +protected: + void draw(); +public: + Fl_Box(int X, int Y, int W, int H, const char *l=0) + : Fl_Widget(X,Y,W,H,l) {} + Fl_Box(Fl_Boxtype b, int X, int Y, int W, int H, const char *l) + : Fl_Widget(X,Y,W,H,l) {box(b);} + + virtual int handle(int); +}; + +#endif + +// +// End of "$Id: Fl_Box.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Browser.H b/Utilities/FLTK/FL/Fl_Browser.H new file mode 100644 index 0000000000..ed0af811d4 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Browser.H @@ -0,0 +1,132 @@ +// +// "$Id: Fl_Browser.H 4288 2005-04-16 00:13:17Z mike $" +// +// Browser header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Forms-compatable browser. Probably useful for other +// lists of textual data. Notice that the line numbers +// start from 1, and 0 means "no line". + +#ifndef Fl_Browser_H +#define Fl_Browser_H + +#include "Fl_Browser_.H" + +struct FL_BLINE; + +class FL_EXPORT Fl_Browser : public Fl_Browser_ { + + FL_BLINE *first; // the array of lines + FL_BLINE *last; + FL_BLINE *cache; + int cacheline; // line number of cache + int lines; // Number of lines + int full_height_; + const int* column_widths_; + char format_char_; // alternative to @-sign + char column_char_; // alternative to tab + +protected: + + // required routines for Fl_Browser_ subclass: + void* item_first() const ; + void* item_next(void*) const ; + void* item_prev(void*) const ; + int item_selected(void*) const ; + void item_select(void*, int); + int item_height(void*) const ; + int item_width(void*) const ; + void item_draw(void*, int, int, int, int) const ; + int full_height() const ; + int incr_height() const ; + + FL_BLINE* find_line(int) const ; + FL_BLINE* _remove(int) ; + void insert(int, FL_BLINE*); + int lineno(void*) const ; + void swap(FL_BLINE *a, FL_BLINE *b); + +public: + + void remove(int); + void add(const char*, void* = 0); + void insert(int, const char*, void* = 0); + void move(int to, int from); + int load(const char* filename); + void swap(int a, int b); + void clear(); + + int size() const {return lines;} + void size(int W, int H) { Fl_Widget::size(W, H); } + + int topline() const ; + enum Fl_Line_Position { TOP, BOTTOM, MIDDLE }; + void lineposition(int, Fl_Line_Position); + void topline(int l) { lineposition(l, TOP); } + void bottomline(int l) { lineposition(l, BOTTOM); } + void middleline(int l) { lineposition(l, MIDDLE); } + + int select(int, int=1); + int selected(int) const ; + void show(int n); + void show() {Fl_Widget::show();} + void hide(int n); + void hide() {Fl_Widget::hide();} + int visible(int n) const ; + + int value() const ; + void value(int v) {select(v);} + const char* text(int) const ; + void text(int, const char*); + void* data(int) const ; + void data(int, void* v); + + Fl_Browser(int, int, int, int, const char* = 0); + ~Fl_Browser() { clear(); } + + char format_char() const {return format_char_;} + void format_char(char c) {format_char_ = c;} + char column_char() const {return column_char_;} + void column_char(char c) {column_char_ = c;} + const int* column_widths() const {return column_widths_;} + void column_widths(const int* l) {column_widths_ = l;} + + int displayed(int n) const {return Fl_Browser_::displayed(find_line(n));} + void make_visible(int n) { + if (n < 1) Fl_Browser_::display(find_line(1)); + else if (n > lines) Fl_Browser_::display(find_line(lines)); + else Fl_Browser_::display(find_line(n)); + } + + // for back compatability only: + void replace(int a, const char* b) {text(a, b);} + void display(int, int=1); +}; + +#endif + +// +// End of "$Id: Fl_Browser.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Browser_.H b/Utilities/FLTK/FL/Fl_Browser_.H new file mode 100644 index 0000000000..c66d414edc --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Browser_.H @@ -0,0 +1,153 @@ +// +// "$Id: Fl_Browser_.H 4288 2005-04-16 00:13:17Z mike $" +// +// Common browser header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// This is the base class for browsers. To be useful it must +// be subclassed and several virtual functions defined. The +// Forms-compatable browser and the file chooser's browser are +// subclassed off of this. + +// Yes, I know this should be a template... + +#ifndef Fl_Browser__H +#define Fl_Browser__H + +#ifndef Fl_Group_H +#include "Fl_Group.H" +#endif +#include "Fl_Scrollbar.H" + +#define FL_NORMAL_BROWSER 0 +#define FL_SELECT_BROWSER 1 +#define FL_HOLD_BROWSER 2 +#define FL_MULTI_BROWSER 3 + +class FL_EXPORT Fl_Browser_ : public Fl_Group { + int position_; // where user wants it scrolled to + int real_position_; // the current vertical scrolling position + int hposition_; // where user wants it panned to + int real_hposition_; // the current horizontal scrolling position + int offset_; // how far down top_ item the real_position is + int max_width; // widest object seen so far + uchar has_scrollbar_; // which scrollbars are enabled + uchar textfont_, textsize_; + unsigned textcolor_; + void* top_; // which item scrolling position is in + void* selection_; // which is selected (except for FL_MULTI_BROWSER) + void *redraw1,*redraw2; // minimal update pointers + void* max_width_item; // which item has max_width_ + + static int scrollbar_width_; + + void update_top(); + +protected: + + // All of the following must be supplied by the subclass: + virtual void *item_first() const = 0; + virtual void *item_next(void *) const = 0; + virtual void *item_prev(void *) const = 0; + virtual int item_height(void *) const = 0; + virtual int item_width(void *) const = 0; + virtual int item_quick_height(void *) const ; + virtual void item_draw(void *,int,int,int,int) const = 0; + // you don't have to provide these but it may help speed it up: + virtual int full_width() const ; // current width of all items + virtual int full_height() const ; // current height of all items + virtual int incr_height() const ; // average height of an item + // These only need to be done by subclass if you want a multi-browser: + virtual void item_select(void *,int=1); + virtual int item_selected(void *) const ; + + // things the subclass may want to call: + void *top() const {return top_;} + void *selection() const {return selection_;} + void new_list(); // completely clobber all data, as though list replaced + void deleting(void *a); // get rid of any pointers to a + void replacing(void *a,void *b); // change a pointers to b + void inserting(void *a,void *b); // insert b near a + int displayed(void *) const ; // true if this line is visible + void redraw_line(void *); // minimal update, no change in size + void redraw_lines() {damage(FL_DAMAGE_SCROLL);} // redraw all of them + void bbox(int&,int&,int&,int&) const; + int leftedge() const; // x position after scrollbar & border + void *find_item(int my); // item under mouse + void draw(int,int,int,int); + int handle(int,int,int,int,int); + + void draw(); + Fl_Browser_(int,int,int,int,const char * = 0); + +public: + + Fl_Scrollbar scrollbar; // Vertical scrollbar + Fl_Scrollbar hscrollbar; // Horizontal scrollbar + + int handle(int); + void resize(int,int,int,int); + + int select(void *,int=1,int docallbacks=0); + int select_only(void *,int docallbacks=0); + int deselect(int docallbacks=0); + int position() const {return position_;} + int hposition() const {return hposition_;} + void position(int); // scroll to here + void hposition(int); // pan to here + void display(void*); // scroll so this item is shown + + uchar has_scrollbar() const {return has_scrollbar_;} + void has_scrollbar(uchar i) {has_scrollbar_ = i;} + enum { // values for has_scrollbar() + HORIZONTAL = 1, + VERTICAL = 2, + BOTH = 3, + ALWAYS_ON = 4, + HORIZONTAL_ALWAYS = 5, + VERTICAL_ALWAYS = 6, + BOTH_ALWAYS = 7 + }; + + Fl_Font textfont() const {return (Fl_Font)textfont_;} + void textfont(uchar s) {textfont_ = s;} + uchar textsize() const {return textsize_;} + void textsize(uchar s) {textsize_ = s;} + Fl_Color textcolor() const {return (Fl_Color)textcolor_;} + void textcolor(unsigned n) {textcolor_ = n;} + + static void scrollbar_width(int b) {scrollbar_width_ = b;} + static int scrollbar_width() {return scrollbar_width_;} + + // for back compatability: + void scrollbar_right() {scrollbar.align(FL_ALIGN_RIGHT);} + void scrollbar_left() {scrollbar.align(FL_ALIGN_LEFT);} + +}; + +#endif + +// +// End of "$Id: Fl_Browser_.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Button.H b/Utilities/FLTK/FL/Fl_Button.H new file mode 100644 index 0000000000..15510b137d --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Button.H @@ -0,0 +1,78 @@ +// +// "$Id: Fl_Button.H 4288 2005-04-16 00:13:17Z mike $" +// +// Button header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Button_H +#define Fl_Button_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +// values for type() +#define FL_NORMAL_BUTTON 0 +#define FL_TOGGLE_BUTTON 1 +#define FL_RADIO_BUTTON (FL_RESERVED_TYPE+2) +#define FL_HIDDEN_BUTTON 3 // for Forms compatability + +extern FL_EXPORT int fl_old_shortcut(const char*); + +class FL_EXPORT Fl_Button : public Fl_Widget { + + int shortcut_; + char value_; + char oldval; + uchar down_box_; + +protected: + + virtual void draw(); + +public: + + virtual int handle(int); + Fl_Button(int,int,int,int,const char * = 0); + int value(int); + char value() const {return value_;} + int set() {return value(1);} + int clear() {return value(0);} + void setonly(); // this should only be called on FL_RADIO_BUTTONs + int shortcut() const {return shortcut_;} + void shortcut(int s) {shortcut_ = s;} + Fl_Boxtype down_box() const {return (Fl_Boxtype)down_box_;} + void down_box(Fl_Boxtype b) {down_box_ = b;} + + // back compatability: + void shortcut(const char *s) {shortcut(fl_old_shortcut(s));} + Fl_Color down_color() const {return selection_color();} + void down_color(unsigned c) {selection_color(c);} +}; + +#endif + +// +// End of "$Id: Fl_Button.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Chart.H b/Utilities/FLTK/FL/Fl_Chart.H new file mode 100644 index 0000000000..a705930991 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Chart.H @@ -0,0 +1,93 @@ +// +// "$Id: Fl_Chart.H 4288 2005-04-16 00:13:17Z mike $" +// +// Forms chart header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Chart_H +#define Fl_Chart_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +// values for type() +#define FL_BAR_CHART 0 +#define FL_HORBAR_CHART 1 +#define FL_LINE_CHART 2 +#define FL_FILL_CHART 3 +#define FL_SPIKE_CHART 4 +#define FL_PIE_CHART 5 +#define FL_SPECIALPIE_CHART 6 + +#define FL_FILLED_CHART FL_FILL_CHART // compatibility + +#define FL_CHART_MAX 128 +#define FL_CHART_LABEL_MAX 18 + +struct FL_CHART_ENTRY { + float val; + unsigned col; + char str[FL_CHART_LABEL_MAX+1]; +}; + +class FL_EXPORT Fl_Chart : public Fl_Widget { + int numb; + int maxnumb; + int sizenumb; + FL_CHART_ENTRY *entries; + double min,max; + uchar autosize_; + uchar textfont_,textsize_; + unsigned textcolor_; +protected: + void draw(); +public: + Fl_Chart(int,int,int,int,const char * = 0); + ~Fl_Chart(); + void clear(); + void add(double, const char * =0, unsigned=0); + void insert(int, double, const char * =0, unsigned=0); + void replace(int, double, const char * =0, unsigned=0); + void bounds(double *a,double *b) const {*a = min; *b = max;} + void bounds(double a,double b); + int size() const {return numb;} + void size(int W, int H) { Fl_Widget::size(W, H); } + int maxsize() const {return maxnumb;} + void maxsize(int); + Fl_Font textfont() const {return (Fl_Font)textfont_;} + void textfont(uchar s) {textfont_ = s;} + uchar textsize() const {return textsize_;} + void textsize(uchar s) {textsize_ = s;} + Fl_Color textcolor() const {return (Fl_Color)textcolor_;} + void textcolor(unsigned n) {textcolor_ = n;} + uchar autosize() const {return autosize_;} + void autosize(uchar n) {autosize_ = n;} +}; + +#endif + +// +// End of "$Id: Fl_Chart.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Check_Browser.H b/Utilities/FLTK/FL/Fl_Check_Browser.H new file mode 100644 index 0000000000..f474a03a0c --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Check_Browser.H @@ -0,0 +1,98 @@ +// +// "$Id: Fl_Check_Browser.H 4461 2005-08-05 13:31:02Z dejan $" +// +// Fl_Check_Browser header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Check_Browser_H +#define Fl_Check_Browser_H + +#include "Fl.H" +#include "Fl_Browser_.H" + +class FL_EXPORT Fl_Check_Browser : public Fl_Browser_ { + /* required routines for Fl_Browser_ subclass: */ + + void *item_first() const; + void *item_next(void *) const; + void *item_prev(void *) const; + int item_height(void *) const; + int item_width(void *) const; + void item_draw(void *, int, int, int, int) const; + void item_select(void *, int); + int item_selected(void *) const; + + /* private data */ + + public: // IRIX 5.3 C++ compiler doesn't support private structures... + + struct cb_item { + cb_item *next; + cb_item *prev; + char checked; + char selected; + char *text; + }; + + private: + + cb_item *first; + cb_item *last; + cb_item *cache; + int cached_item; + int nitems_; + int nchecked_; + cb_item *find_item(int) const; + int lineno(cb_item *) const; + + public: + + Fl_Check_Browser(int x, int y, int w, int h, const char *l = 0); + ~Fl_Check_Browser() { clear(); } + int add(char *s); // add an (unchecked) item + int add(char *s, int b); // add an item and set checked + // both return the new nitems() + + // inline const char * methods to avoid breaking binary compatibility... + int add(const char *s) { return add((char *)s); } + int add(const char *s, int b) { return add((char *)s, b); } + + void clear(); // delete all items + int nitems() const { return nitems_; } + int nchecked() const { return nchecked_; } + int checked(int item) const; + void checked(int item, int b); + void set_checked(int item) { checked(item, 1); } + void check_all(); + void check_none(); + int value() const; // currently selected item + char *text(int item) const; // returns pointer to internal buffer +}; + +#endif // Fl_Check_Browser_H + +// +// End of "$Id: Fl_Check_Browser.H 4461 2005-08-05 13:31:02Z dejan $". +// + diff --git a/Utilities/FLTK/FL/Fl_Check_Button.H b/Utilities/FLTK/FL/Fl_Check_Button.H new file mode 100644 index 0000000000..4064cf5b91 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Check_Button.H @@ -0,0 +1,42 @@ +// +// "$Id: Fl_Check_Button.H 4288 2005-04-16 00:13:17Z mike $" +// +// Check button header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Check_Button_H +#define Fl_Check_Button_H + +#include "Fl_Light_Button.H" + +class FL_EXPORT Fl_Check_Button : public Fl_Light_Button { +public: + Fl_Check_Button(int x,int y,int w,int h,const char *l = 0); +}; + +#endif + +// +// End of "$Id: Fl_Check_Button.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Choice.H b/Utilities/FLTK/FL/Fl_Choice.H new file mode 100644 index 0000000000..64e59b68f6 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Choice.H @@ -0,0 +1,48 @@ +// +// "$Id: Fl_Choice.H 4288 2005-04-16 00:13:17Z mike $" +// +// Choice header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Choice_H +#define Fl_Choice_H + +#include "Fl_Menu_.H" + +class FL_EXPORT Fl_Choice : public Fl_Menu_ { +protected: + void draw(); +public: + int handle(int); + Fl_Choice(int,int,int,int,const char * = 0); + int value(const Fl_Menu_Item*); + int value(int i); + int value() const {return Fl_Menu_::value();} +}; + +#endif + +// +// End of "$Id: Fl_Choice.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Clock.H b/Utilities/FLTK/FL/Fl_Clock.H new file mode 100644 index 0000000000..261470c9f4 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Clock.H @@ -0,0 +1,75 @@ +// +// "$Id: Fl_Clock.H 4288 2005-04-16 00:13:17Z mike $" +// +// Clock header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Clock_H +#define Fl_Clock_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +// values for type: +#define FL_SQUARE_CLOCK 0 +#define FL_ROUND_CLOCK 1 +#define FL_ANALOG_CLOCK FL_SQUARE_CLOCK +#define FL_DIGITAL_CLOCK FL_SQUARE_CLOCK // nyi + +// a Fl_Clock_Output can be used to display a program-supplied time: + +class FL_EXPORT Fl_Clock_Output : public Fl_Widget { + int hour_, minute_, second_; + ulong value_; + void drawhands(Fl_Color,Fl_Color); // part of draw +protected: + void draw(int, int, int, int); + void draw(); +public: + Fl_Clock_Output(int x,int y,int w,int h, const char *l = 0); + void value(ulong v); // set to this Unix time + void value(int,int,int); // set hour, minute, second + ulong value() const {return value_;} + int hour() const {return hour_;} + int minute() const {return minute_;} + int second() const {return second_;} +}; + +// a Fl_Clock displays the current time always by using a timeout: + +class FL_EXPORT Fl_Clock : public Fl_Clock_Output { +public: + int handle(int); + void update(); + Fl_Clock(int x,int y,int w,int h, const char *l = 0); + Fl_Clock(uchar t,int x,int y,int w,int h, const char *l); + ~Fl_Clock(); +}; + +#endif + +// +// End of "$Id: Fl_Clock.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Color_Chooser.H b/Utilities/FLTK/FL/Fl_Color_Chooser.H new file mode 100644 index 0000000000..2ef7250631 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Color_Chooser.H @@ -0,0 +1,104 @@ +// +// "$Id: Fl_Color_Chooser.H 4288 2005-04-16 00:13:17Z mike $" +// +// Color chooser header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// The color chooser object and the color chooser popup. The popup +// is just a window containing a single color chooser and some boxes +// to indicate the current and cancelled color. + +#ifndef Fl_Color_Chooser_H +#define Fl_Color_Chooser_H + +#include <FL/Fl_Group.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Return_Button.H> +#include <FL/Fl_Choice.H> +#include <FL/Fl_Value_Input.H> + +class FL_EXPORT Flcc_HueBox : public Fl_Widget { + int px, py; +protected: + void draw(); + int handle_key(int); +public: + int handle(int); + Flcc_HueBox(int X, int Y, int W, int H) : Fl_Widget(X,Y,W,H) { + px = py = 0;} +}; + +class FL_EXPORT Flcc_ValueBox : public Fl_Widget { + int py; +protected: + void draw(); + int handle_key(int); +public: + int handle(int); + Flcc_ValueBox(int X, int Y, int W, int H) : Fl_Widget(X,Y,W,H) { + py = 0;} +}; + +class FL_EXPORT Flcc_Value_Input : public Fl_Value_Input { +public: + int format(char*); + Flcc_Value_Input(int X, int Y, int W, int H) : Fl_Value_Input(X,Y,W,H) {} +}; + +class FL_EXPORT Fl_Color_Chooser : public Fl_Group { + Flcc_HueBox huebox; + Flcc_ValueBox valuebox; + Fl_Choice choice; + Flcc_Value_Input rvalue; + Flcc_Value_Input gvalue; + Flcc_Value_Input bvalue; + Fl_Box resize_box; + double hue_, saturation_, value_; + double r_, g_, b_; + void set_valuators(); + static void rgb_cb(Fl_Widget*, void*); + static void mode_cb(Fl_Widget*, void*); +public: + int mode() {return choice.value();} + double hue() const {return hue_;} + double saturation() const {return saturation_;} + double value() const {return value_;} + double r() const {return r_;} + double g() const {return g_;} + double b() const {return b_;} + int hsv(double,double,double); + int rgb(double,double,double); + static void hsv2rgb(double, double, double,double&,double&,double&); + static void rgb2hsv(double, double, double,double&,double&,double&); + Fl_Color_Chooser(int,int,int,int,const char* = 0); +}; + +FL_EXPORT int fl_color_chooser(const char* name, double& r, double& g, double& b); +FL_EXPORT int fl_color_chooser(const char* name, uchar& r, uchar& g, uchar& b); + +#endif + +// +// End of "$Id: Fl_Color_Chooser.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Counter.H b/Utilities/FLTK/FL/Fl_Counter.H new file mode 100644 index 0000000000..73781a8b80 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Counter.H @@ -0,0 +1,76 @@ +// +// "$Id: Fl_Counter.H 4288 2005-04-16 00:13:17Z mike $" +// +// Counter header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// A numerical value with up/down step buttons. From Forms. + +#ifndef Fl_Counter_H +#define Fl_Counter_H + +#ifndef Fl_Valuator_H +#include "Fl_Valuator.H" +#endif + +// values for type(): +#define FL_NORMAL_COUNTER 0 +#define FL_SIMPLE_COUNTER 1 + +class FL_EXPORT Fl_Counter : public Fl_Valuator { + + uchar textfont_, textsize_; + unsigned textcolor_; + double lstep_; + uchar mouseobj; + static void repeat_callback(void *); + int calc_mouseobj(); + void increment_cb(); + +protected: + + void draw(); + +public: + + int handle(int); + Fl_Counter(int,int,int,int,const char * = 0); + ~Fl_Counter(); + void lstep(double a) {lstep_ = a;} + void step(double a,double b) {Fl_Valuator::step(a); lstep_ = b;} + void step(double a) {Fl_Valuator::step(a);} + Fl_Font textfont() const {return (Fl_Font)textfont_;} + void textfont(uchar s) {textfont_ = s;} + uchar textsize() const {return textsize_;} + void textsize(uchar s) {textsize_ = s;} + Fl_Color textcolor() const {return (Fl_Color)textcolor_;} + void textcolor(unsigned s) {textcolor_ = s;} + +}; + +#endif + +// +// End of "$Id: Fl_Counter.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Dial.H b/Utilities/FLTK/FL/Fl_Dial.H new file mode 100644 index 0000000000..f067036ff8 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Dial.H @@ -0,0 +1,67 @@ +// +// "$Id: Fl_Dial.H 4288 2005-04-16 00:13:17Z mike $" +// +// Dial header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Dial_H +#define Fl_Dial_H + +#ifndef Fl_Valuator_H +#include "Fl_Valuator.H" +#endif + +// values for type(): +#define FL_NORMAL_DIAL 0 +#define FL_LINE_DIAL 1 +#define FL_FILL_DIAL 2 + +class FL_EXPORT Fl_Dial : public Fl_Valuator { + + short a1,a2; + +protected: + + // these allow subclasses to put the dial in a smaller area: + void draw(int, int, int, int); + int handle(int, int, int, int, int); + void draw(); + +public: + + int handle(int); + Fl_Dial(int x,int y,int w,int h, const char *l = 0); + short angle1() const {return a1;} + void angle1(short a) {a1 = a;} + short angle2() const {return a2;} + void angle2(short a) {a2 = a;} + void angles(short a, short b) {a1 = a; a2 = b;} + +}; + +#endif + +// +// End of "$Id: Fl_Dial.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Double_Window.H b/Utilities/FLTK/FL/Fl_Double_Window.H new file mode 100644 index 0000000000..635c7cb3c4 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Double_Window.H @@ -0,0 +1,54 @@ +// +// "$Id: Fl_Double_Window.H 4288 2005-04-16 00:13:17Z mike $" +// +// Double-buffered window header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Double_Window_H +#define Fl_Double_Window_H + +#include "Fl_Window.H" + +class FL_EXPORT Fl_Double_Window : public Fl_Window { +protected: + void flush(int eraseoverlay); + char force_doublebuffering_; // force db, even if the OS already buffers windows (overlays need that on MacOS and Windows2000) +public: + void show(); + void show(int a, char **b) {Fl_Window::show(a,b);} + void flush(); + void resize(int,int,int,int); + void hide(); + ~Fl_Double_Window(); + Fl_Double_Window(int W, int H, const char *l = 0) + : Fl_Window(W,H,l), force_doublebuffering_(0) { type(FL_DOUBLE_WINDOW); } + Fl_Double_Window(int X, int Y, int W, int H, const char *l = 0) + : Fl_Window(X,Y,W,H,l), force_doublebuffering_(0) { type(FL_DOUBLE_WINDOW); } +}; + +#endif + +// +// End of "$Id: Fl_Double_Window.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Export.H b/Utilities/FLTK/FL/Fl_Export.H new file mode 100644 index 0000000000..267f632224 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Export.H @@ -0,0 +1,49 @@ +/* + * "$Id: Fl_Export.H 4288 2005-04-16 00:13:17Z mike $" + * + * WIN32 DLL export definitions for the Fast Light Tool Kit (FLTK). + * + * Copyright 1998-2005 by Bill Spitzak and others. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems on the following page: + * + * http://www.fltk.org/str.php + */ + +#ifndef Fl_Export_H +# define Fl_Export_H + +/* + * The following is only used when building DLLs under WIN32... + */ + +# if defined(FL_DLL) && (defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__) || __GNUC__ >= 3) +# ifdef FL_LIBRARY +# define FL_EXPORT __declspec(dllexport) +# else +# define FL_EXPORT __declspec(dllimport) +# endif /* FL_LIBRARY */ +# else +# define FL_EXPORT +# endif /* FL_DLL */ + +#endif /* !Fl_Export_H */ + +/* + * End of "$Id: Fl_Export.H 4288 2005-04-16 00:13:17Z mike $". + */ diff --git a/Utilities/FLTK/FL/Fl_File_Browser.H b/Utilities/FLTK/FL/Fl_File_Browser.H new file mode 100644 index 0000000000..3efbecc6ad --- /dev/null +++ b/Utilities/FLTK/FL/Fl_File_Browser.H @@ -0,0 +1,81 @@ +// +// "$Id: Fl_File_Browser.H 4288 2005-04-16 00:13:17Z mike $" +// +// FileBrowser definitions. +// +// Copyright 1999-2005 by Michael Sweet. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// +// Include necessary header files... +// + +#ifndef _Fl_File_Browser_H_ +# define _Fl_File_Browser_H_ + +# include "Fl_Browser.H" +# include "Fl_File_Icon.H" +# include "filename.H" + + +// +// Fl_File_Browser class... +// + +class FL_EXPORT Fl_File_Browser : public Fl_Browser +{ + int filetype_; + const char *directory_; + uchar iconsize_; + const char *pattern_; + + int full_height() const; + int item_height(void *) const; + int item_width(void *) const; + void item_draw(void *, int, int, int, int) const; + int incr_height() const { return (item_height(0)); } + +public: + enum { FILES, DIRECTORIES }; + + Fl_File_Browser(int, int, int, int, const char * = 0); + + uchar iconsize() const { return (iconsize_); }; + void iconsize(uchar s) { iconsize_ = s; redraw(); }; + + void filter(const char *pattern); + const char *filter() const { return (pattern_); }; + + int load(const char *directory, Fl_File_Sort_F *sort = fl_numericsort); + + uchar textsize() const { return (Fl_Browser::textsize()); }; + void textsize(uchar s) { Fl_Browser::textsize(s); iconsize_ = (uchar)(3 * s / 2); }; + + int filetype() const { return (filetype_); }; + void filetype(int t) { filetype_ = t; }; +}; + +#endif // !_Fl_File_Browser_H_ + +// +// End of "$Id: Fl_File_Browser.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_File_Chooser.H b/Utilities/FLTK/FL/Fl_File_Chooser.H new file mode 100644 index 0000000000..4382698aae --- /dev/null +++ b/Utilities/FLTK/FL/Fl_File_Chooser.H @@ -0,0 +1,186 @@ +// +// "$Id: Fl_File_Chooser.H 4473 2005-08-08 00:50:02Z mike $" +// +// Fl_File_Chooser dialog for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// generated by Fast Light User Interface Designer (fluid) version 1.0107 + +#ifndef Fl_File_Chooser_H +#define Fl_File_Chooser_H +#include <FL/Fl.H> +#include <FL/Fl_Double_Window.H> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <FL/Fl_Group.H> +#include <FL/Fl_Choice.H> +#include <FL/Fl_Menu_Button.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Preferences.H> +#include <FL/Fl_Tile.H> +#include <FL/Fl_File_Browser.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Check_Button.H> +#include <FL/Fl_File_Input.H> +#include <FL/Fl_Return_Button.H> +#include <FL/fl_ask.H> + +class FL_EXPORT Fl_File_Chooser { +public: + enum { SINGLE = 0, MULTI = 1, CREATE = 2, DIRECTORY = 4 }; +private: + static Fl_Preferences prefs_; + void (*callback_)(Fl_File_Chooser*, void *); + void *data_; + char directory_[1024]; + char pattern_[1024]; + char preview_text_[2048]; + int type_; + void favoritesButtonCB(); + void favoritesCB(Fl_Widget *w); + void fileListCB(); + void fileNameCB(); + void newdir(); + static void previewCB(Fl_File_Chooser *fc); + void showChoiceCB(); + void update_favorites(); + void update_preview(); +public: + Fl_File_Chooser(const char *d, const char *p, int t, const char *title); +private: + Fl_Double_Window *window; + void cb_window_i(Fl_Double_Window*, void*); + static void cb_window(Fl_Double_Window*, void*); + Fl_Choice *showChoice; + void cb_showChoice_i(Fl_Choice*, void*); + static void cb_showChoice(Fl_Choice*, void*); + Fl_Menu_Button *favoritesButton; + void cb_favoritesButton_i(Fl_Menu_Button*, void*); + static void cb_favoritesButton(Fl_Menu_Button*, void*); +public: + Fl_Button *newButton; +private: + void cb_newButton_i(Fl_Button*, void*); + static void cb_newButton(Fl_Button*, void*); + void cb__i(Fl_Tile*, void*); + static void cb_(Fl_Tile*, void*); + Fl_File_Browser *fileList; + void cb_fileList_i(Fl_File_Browser*, void*); + static void cb_fileList(Fl_File_Browser*, void*); + Fl_Box *previewBox; +public: + Fl_Check_Button *previewButton; +private: + void cb_previewButton_i(Fl_Check_Button*, void*); + static void cb_previewButton(Fl_Check_Button*, void*); + Fl_File_Input *fileName; + void cb_fileName_i(Fl_File_Input*, void*); + static void cb_fileName(Fl_File_Input*, void*); + Fl_Return_Button *okButton; + void cb_okButton_i(Fl_Return_Button*, void*); + static void cb_okButton(Fl_Return_Button*, void*); + Fl_Button *cancelButton; + void cb_cancelButton_i(Fl_Button*, void*); + static void cb_cancelButton(Fl_Button*, void*); + Fl_Double_Window *favWindow; + Fl_File_Browser *favList; + void cb_favList_i(Fl_File_Browser*, void*); + static void cb_favList(Fl_File_Browser*, void*); + Fl_Button *favUpButton; + void cb_favUpButton_i(Fl_Button*, void*); + static void cb_favUpButton(Fl_Button*, void*); + Fl_Button *favDeleteButton; + void cb_favDeleteButton_i(Fl_Button*, void*); + static void cb_favDeleteButton(Fl_Button*, void*); + Fl_Button *favDownButton; + void cb_favDownButton_i(Fl_Button*, void*); + static void cb_favDownButton(Fl_Button*, void*); + Fl_Button *favCancelButton; + void cb_favCancelButton_i(Fl_Button*, void*); + static void cb_favCancelButton(Fl_Button*, void*); + Fl_Return_Button *favOkButton; + void cb_favOkButton_i(Fl_Return_Button*, void*); + static void cb_favOkButton(Fl_Return_Button*, void*); +public: + ~Fl_File_Chooser(); + void callback(void (*cb)(Fl_File_Chooser *, void *), void *d = 0); + void color(Fl_Color c); + Fl_Color color(); + int count(); + void directory(const char *d); + char * directory(); + void filter(const char *p); + const char * filter(); + int filter_value(); + void filter_value(int f); + void hide(); + void iconsize(uchar s); + uchar iconsize(); + void label(const char *l); + const char * label(); + void ok_label(const char *l); + const char * ok_label(); + void preview(int e); + int preview() const { return previewButton->value(); }; + void rescan(); + void show(); + int shown(); + void textcolor(Fl_Color c); + Fl_Color textcolor(); + void textfont(uchar f); + uchar textfont(); + void textsize(uchar s); + uchar textsize(); + void type(int t); + int type(); + void * user_data() const; + void user_data(void *d); + const char *value(int f = 1); + void value(const char *filename); + int visible(); + static const char *add_favorites_label; + static const char *all_files_label; + static const char *custom_filter_label; + static const char *existing_file_label; + static const char *favorites_label; + static const char *filename_label; + static const char *filesystems_label; + static const char *manage_favorites_label; + static const char *new_directory_label; + static const char *new_directory_tooltip; + static const char *preview_label; + static const char *save_label; + static const char *show_label; + static Fl_File_Sort_F *sort; +}; +FL_EXPORT char *fl_dir_chooser(const char *message,const char *fname,int relative=0); +FL_EXPORT char *fl_file_chooser(const char *message,const char *pat,const char *fname,int relative=0); +FL_EXPORT void fl_file_chooser_callback(void (*cb)(const char*)); +FL_EXPORT void fl_file_chooser_ok_label(const char*l); +#endif + +// +// End of "$Id: Fl_File_Chooser.H 4473 2005-08-08 00:50:02Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_File_Icon.H b/Utilities/FLTK/FL/Fl_File_Icon.H new file mode 100644 index 0000000000..85201296ab --- /dev/null +++ b/Utilities/FLTK/FL/Fl_File_Icon.H @@ -0,0 +1,115 @@ +// +// "$Id: Fl_File_Icon.H 4288 2005-04-16 00:13:17Z mike $" +// +// Fl_File_Icon definitions. +// +// Copyright 1999-2005 by Michael Sweet. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// +// Include necessary header files... +// + +#ifndef _Fl_Fl_File_Icon_H_ +# define _Fl_Fl_File_Icon_H_ + +# include "Fl.H" + + +// +// Special color value for the icon color. +// + +# define FL_ICON_COLOR (Fl_Color)0xffffffff + + +// +// Fl_File_Icon class... +// + +class FL_EXPORT Fl_File_Icon //// Icon data +{ + static Fl_File_Icon *first_; // Pointer to first icon/filetype + Fl_File_Icon *next_; // Pointer to next icon/filetype + const char *pattern_; // Pattern string + int type_; // Match only if directory or file? + int num_data_; // Number of data elements + int alloc_data_; // Number of allocated elements + short *data_; // Icon data + + public: + + enum // File types + { + ANY, // Any kind of file + PLAIN, // Only plain files + FIFO, // Only named pipes + DEVICE, // Only character and block devices + LINK, // Only symbolic links + DIRECTORY // Only directories + }; + + enum // Data opcodes + { + END, // End of primitive/icon + COLOR, // Followed by color value (2 shorts) + LINE, // Start of line + CLOSEDLINE, // Start of closed line + POLYGON, // Start of polygon + OUTLINEPOLYGON, // Followed by outline color (2 shorts) + VERTEX // Followed by scaled X,Y + }; + + Fl_File_Icon(const char *p, int t, int nd = 0, short *d = 0); + ~Fl_File_Icon(); + + short *add(short d); + short *add_color(Fl_Color c) + { short *d = add((short)COLOR); add((short)(c >> 16)); add((short)c); return (d); } + short *add_vertex(int x, int y) + { short *d = add((short)VERTEX); add((short)x); add((short)y); return (d); } + short *add_vertex(float x, float y) + { short *d = add((short)VERTEX); add((short)(x * 10000.0)); + add((short)(y * 10000.0)); return (d); } + void clear() { num_data_ = 0; } + void draw(int x, int y, int w, int h, Fl_Color ic, int active = 1); + void label(Fl_Widget *w); + static void labeltype(const Fl_Label *o, int x, int y, int w, int h, Fl_Align a); + void load(const char *f); + int load_fti(const char *fti); + int load_image(const char *i); + Fl_File_Icon *next() { return (next_); } + const char *pattern() { return (pattern_); } + int size() { return (num_data_); } + int type() { return (type_); } + short *value() { return (data_); } + + static Fl_File_Icon *find(const char *filename, int filetype = ANY); + static Fl_File_Icon *first() { return (first_); } + static void load_system_icons(void); +}; + +#endif // !_Fl_Fl_File_Icon_H_ + +// +// End of "$Id: Fl_File_Icon.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_File_Input.H b/Utilities/FLTK/FL/Fl_File_Input.H new file mode 100644 index 0000000000..b5ec6f1041 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_File_Input.H @@ -0,0 +1,68 @@ +// +// "$Id: Fl_File_Input.H 4288 2005-04-16 00:13:17Z mike $" +// +// File_Input header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// Original version Copyright 1998 by Curtis Edwards. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_File_Input_H +# define Fl_File_Input_H + +# include <FL/Fl_Input.H> + + +class FL_EXPORT Fl_File_Input : public Fl_Input +{ + Fl_Color errorcolor_; + char ok_entry_; + uchar down_box_; + short buttons_[200]; + short pressed_; + + void draw_buttons(); + int handle_button(int event); + void update_buttons(); + +public: + + Fl_File_Input(int,int,int,int,const char *t=0); + + virtual int handle(int); + virtual void draw(); + + Fl_Boxtype down_box() const { return (Fl_Boxtype)down_box_; } + void down_box(Fl_Boxtype b) { down_box_ = b; } + Fl_Color errorcolor() const { return errorcolor_; } + void errorcolor(Fl_Color c) { errorcolor_ = c; } + int value(const char*); + int value(const char*, int); + const char *value() { return Fl_Input_::value(); } +}; + +#endif // !Fl_File_Input_H + + +// +// End of "$Id: Fl_File_Input.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Fill_Dial.H b/Utilities/FLTK/FL/Fl_Fill_Dial.H new file mode 100644 index 0000000000..2472f6dc42 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Fill_Dial.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Fill_Dial.H 4288 2005-04-16 00:13:17Z mike $" +// +// Filled dial header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Fill_Dial_H +#define Fl_Fill_Dial_H + +#include "Fl_Dial.H" + +class Fl_Fill_Dial : public Fl_Dial { +public: + Fl_Fill_Dial(int x,int y,int w,int h, const char *l = 0) + : Fl_Dial(x,y,w,h,l) {type(FL_FILL_DIAL);} +}; + +#endif + +// +// End of "$Id: Fl_Fill_Dial.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Fill_Slider.H b/Utilities/FLTK/FL/Fl_Fill_Slider.H new file mode 100644 index 0000000000..8635eeb821 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Fill_Slider.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Fill_Slider.H 4288 2005-04-16 00:13:17Z mike $" +// +// Filled slider header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Fill_Slider_H +#define Fl_Fill_Slider_H + +#include "Fl_Slider.H" + +class Fl_Fill_Slider : public Fl_Slider { +public: + Fl_Fill_Slider(int x,int y,int w,int h,const char *l=0) + : Fl_Slider(x,y,w,h,l) {type(FL_VERT_FILL_SLIDER);} +}; + +#endif + +// +// End of "$Id: Fl_Fill_Slider.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Float_Input.H b/Utilities/FLTK/FL/Fl_Float_Input.H new file mode 100644 index 0000000000..526674d2bd --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Float_Input.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Float_Input.H 4288 2005-04-16 00:13:17Z mike $" +// +// Floating point input header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Float_Input_H +#define Fl_Float_Input_H + +#include "Fl_Input.H" + +class Fl_Float_Input : public Fl_Input { +public: + Fl_Float_Input(int X,int Y,int W,int H,const char *l = 0) + : Fl_Input(X,Y,W,H,l) {type(FL_FLOAT_INPUT);} +}; + +#endif + +// +// End of "$Id: Fl_Float_Input.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_FormsBitmap.H b/Utilities/FLTK/FL/Fl_FormsBitmap.H new file mode 100644 index 0000000000..caa3a0734b --- /dev/null +++ b/Utilities/FLTK/FL/Fl_FormsBitmap.H @@ -0,0 +1,48 @@ +// +// "$Id: Fl_FormsBitmap.H 4288 2005-04-16 00:13:17Z mike $" +// +// Forms bitmap header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_FormsBitmap_H +#define Fl_FormsBitmap_H + +#include "Fl_Bitmap.H" + +class FL_EXPORT Fl_FormsBitmap : public Fl_Widget { + Fl_Bitmap *b; +protected: + void draw(); +public: + Fl_FormsBitmap(Fl_Boxtype, int, int, int, int, const char * = 0); + void set(int W, int H, const uchar *bits); + void bitmap(Fl_Bitmap *B) {b = B;} + Fl_Bitmap *bitmap() const {return b;} +}; + +#endif + +// +// End of "$Id: Fl_FormsBitmap.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_FormsPixmap.H b/Utilities/FLTK/FL/Fl_FormsPixmap.H new file mode 100644 index 0000000000..f25bed6d76 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_FormsPixmap.H @@ -0,0 +1,48 @@ +// +// "$Id: Fl_FormsPixmap.H 4288 2005-04-16 00:13:17Z mike $" +// +// Forms pixmap header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_FormsPixmap_H +#define Fl_FormsPixmap_H + +#include "Fl_Pixmap.H" + +class FL_EXPORT Fl_FormsPixmap : public Fl_Widget { + Fl_Pixmap *b; +protected: + void draw(); +public: + Fl_FormsPixmap(Fl_Boxtype, int, int, int, int, const char * = 0); + void set(/*const*/char * const * bits); + void Pixmap(Fl_Pixmap *B) {b = B;} + Fl_Pixmap *Pixmap() const {return b;} +}; + +#endif + +// +// End of "$Id: Fl_FormsPixmap.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Free.H b/Utilities/FLTK/FL/Fl_Free.H new file mode 100644 index 0000000000..7895dfe17b --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Free.H @@ -0,0 +1,66 @@ +// +// "$Id: Fl_Free.H 4288 2005-04-16 00:13:17Z mike $" +// +// Forms free header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Free_H +#define Fl_Free_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +#define FL_NORMAL_FREE 1 +#define FL_SLEEPING_FREE 2 +#define FL_INPUT_FREE 3 +#define FL_CONTINUOUS_FREE 4 +#define FL_ALL_FREE 5 + +typedef int (*FL_HANDLEPTR)(Fl_Widget *, int , float, float, char); + +class FL_EXPORT Fl_Free : public Fl_Widget { + FL_HANDLEPTR hfunc; + static void step(void *); +protected: + void draw(); +public: + int handle(int); + Fl_Free(uchar t,int x,int y,int w,int h,const char *l,FL_HANDLEPTR hdl); + ~Fl_Free(); +}; + +// old event names for compatability: +#define FL_MOUSE FL_DRAG +#define FL_DRAW 100 // NOT USED +#define FL_STEP 101 +#define FL_FREEMEM 102 // NOT USED +#define FL_FREEZE 103 // NOT USED +#define FL_THAW 104 // NOT USED + +#endif + +// +// End of "$Id: Fl_Free.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_GIF_Image.H b/Utilities/FLTK/FL/Fl_GIF_Image.H new file mode 100644 index 0000000000..40a3e692ba --- /dev/null +++ b/Utilities/FLTK/FL/Fl_GIF_Image.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_GIF_Image.H 4288 2005-04-16 00:13:17Z mike $" +// +// GIF image header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_GIF_Image_H +#define Fl_GIF_Image_H +# include "Fl_Pixmap.H" + +class FL_EXPORT Fl_GIF_Image : public Fl_Pixmap { + + public: + + Fl_GIF_Image(const char* filename); +}; + +#endif + +// +// End of "$Id: Fl_GIF_Image.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Gl_Window.H b/Utilities/FLTK/FL/Fl_Gl_Window.H new file mode 100644 index 0000000000..d19e33db44 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Gl_Window.H @@ -0,0 +1,96 @@ +// +// "$Id: Fl_Gl_Window.H 4288 2005-04-16 00:13:17Z mike $" +// +// OpenGL header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +#ifndef Fl_Gl_Window_H +#define Fl_Gl_Window_H + +#include "Fl_Window.H" + +#ifndef GLContext +typedef void* GLContext; // actually a GLXContext or HGLDC +#endif + +class Fl_Gl_Choice; // structure to hold result of glXChooseVisual + +class FL_EXPORT Fl_Gl_Window : public Fl_Window { + + int mode_; + const int *alist; + Fl_Gl_Choice *g; + GLContext context_; + char valid_; + char damage1_; // damage() of back buffer + virtual void draw_overlay(); + void init(); + + void *overlay; + void make_overlay(); + friend class _Fl_Gl_Overlay; + + static int can_do(int, const int *); + int mode(int, const int *); + +public: + + void show(); + void show(int a, char **b) {Fl_Window::show(a,b);} + void flush(); + void hide(); + void resize(int,int,int,int); + + char valid() const {return valid_;} + void valid(char v) {valid_ = v;} + void invalidate(); + + static int can_do(int m) {return can_do(m,0);} + static int can_do(const int *m) {return can_do(0, m);} + int can_do() {return can_do(mode_,alist);} + Fl_Mode mode() const {return (Fl_Mode)mode_;} + int mode(int a) {return mode(a,0);} + int mode(const int *a) {return mode(0, a);} + + void* context() const {return context_;} + void context(void*, int destroy_flag = 0); + void make_current(); + void swap_buffers(); + void ortho(); + + int can_do_overlay(); + void redraw_overlay(); + void hide_overlay(); + void make_overlay_current(); + + ~Fl_Gl_Window(); + Fl_Gl_Window(int W, int H, const char *l=0) : Fl_Window(W,H,l) {init();} + Fl_Gl_Window(int X, int Y, int W, int H, const char *l=0) + : Fl_Window(X,Y,W,H,l) {init();} +}; + +#endif + +// +// End of "$Id: Fl_Gl_Window.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Group.H b/Utilities/FLTK/FL/Fl_Group.H new file mode 100644 index 0000000000..1da36cfe8c --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Group.H @@ -0,0 +1,107 @@ +// +// "$Id: Fl_Group.H 4421 2005-07-15 09:34:53Z matt $" +// +// Group header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Group_H +#define Fl_Group_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +class FL_EXPORT Fl_Group : public Fl_Widget { + + Fl_Widget** array_; + Fl_Widget* savedfocus_; + Fl_Widget* resizable_; + int children_; + short *sizes_; // remembered initial sizes of children + + int navigation(int); + static Fl_Group *current_; + + // unimplemented copy ctor and assignment operator + Fl_Group(const Fl_Group&); + Fl_Group& operator=(const Fl_Group&); + +protected: + + void draw(); + void draw_child(Fl_Widget&) const; + void draw_children(); + void draw_outside_label(const Fl_Widget&) const ; + void update_child(Fl_Widget&) const; + short* sizes(); + +public: + + int handle(int); + void begin(); + void end(); + static Fl_Group *current(); + static void current(Fl_Group *g); + + int children() const {return children_;} + Fl_Widget* child(int n) const {return array()[n];} + int find(const Fl_Widget*) const; + int find(const Fl_Widget& o) const {return find(&o);} + Fl_Widget* const* array() const; + + void resize(int,int,int,int); + Fl_Group(int,int,int,int, const char * = 0); + virtual ~Fl_Group(); + void add(Fl_Widget&); + void add(Fl_Widget* o) {add(*o);} + void insert(Fl_Widget&, int i); + void insert(Fl_Widget& o, Fl_Widget* before) {insert(o,find(before));} + void remove(Fl_Widget&); + void remove(Fl_Widget* o) {remove(*o);} + void clear(); + + void resizable(Fl_Widget& o) {resizable_ = &o;} + void resizable(Fl_Widget* o) {resizable_ = o;} + Fl_Widget* resizable() const {return resizable_;} + void add_resizable(Fl_Widget& o) {resizable_ = &o; add(o);} + void init_sizes(); + + // back compatability function: + void focus(Fl_Widget* o) {o->take_focus();} + Fl_Widget* & _ddfdesign_kludge() {return resizable_;} + void forms_end(); +}; + +// dummy class used to end child groups in constructors for complex +// subclasses of Fl_Group: +class FL_EXPORT Fl_End { +public: + Fl_End() {Fl_Group::current()->end();} +}; + +#endif + +// +// End of "$Id: Fl_Group.H 4421 2005-07-15 09:34:53Z matt $". +// diff --git a/Utilities/FLTK/FL/Fl_Help_Dialog.H b/Utilities/FLTK/FL/Fl_Help_Dialog.H new file mode 100644 index 0000000000..198e2507af --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Help_Dialog.H @@ -0,0 +1,93 @@ +// +// "$Id: Fl_Help_Dialog.H 4582 2005-09-25 16:54:40Z matt $" +// +// Fl_Help_Dialog dialog for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// generated by Fast Light User Interface Designer (fluid) version 1.0107 + +#ifndef Fl_Help_Dialog_H +#define Fl_Help_Dialog_H +#include <FL/Fl.H> +#include <FL/Fl_Double_Window.H> +#include <FL/Fl_Help_View.H> +#include <FL/Fl_Group.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Input.H> + +class FL_EXPORT Fl_Help_Dialog { + int index_; + int max_; + int line_[100]; + char file_[100][256]; + int find_pos_; +public: + Fl_Help_Dialog(); +private: + Fl_Double_Window *window_; + Fl_Help_View *view_; + void cb_view__i(Fl_Help_View*, void*); + static void cb_view_(Fl_Help_View*, void*); + void cb_Close_i(Fl_Button*, void*); + static void cb_Close(Fl_Button*, void*); + Fl_Button *back_; + void cb_back__i(Fl_Button*, void*); + static void cb_back_(Fl_Button*, void*); + Fl_Button *forward_; + void cb_forward__i(Fl_Button*, void*); + static void cb_forward_(Fl_Button*, void*); + Fl_Button *smaller_; + void cb_smaller__i(Fl_Button*, void*); + static void cb_smaller_(Fl_Button*, void*); + Fl_Button *larger_; + void cb_larger__i(Fl_Button*, void*); + static void cb_larger_(Fl_Button*, void*); + Fl_Input *find_; + void cb_find__i(Fl_Input*, void*); + static void cb_find_(Fl_Input*, void*); +public: + ~Fl_Help_Dialog(); + int h(); + void hide(); + void load(const char *f); + void position(int xx, int yy); + void resize(int xx, int yy, int ww, int hh); + void show(); + void show(int argc, char **argv); + void textsize(uchar s); + uchar textsize(); + void topline(const char *n); + void topline(int n); + void value(const char *f); + const char * value() const; + int visible(); + int w(); + int x(); + int y(); +}; +#endif + +// +// End of "$Id: Fl_Help_Dialog.H 4582 2005-09-25 16:54:40Z matt $". +// diff --git a/Utilities/FLTK/FL/Fl_Help_View.H b/Utilities/FLTK/FL/Fl_Help_View.H new file mode 100644 index 0000000000..a0f4fd6d2f --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Help_View.H @@ -0,0 +1,195 @@ +// +// "$Id: Fl_Help_View.H 4288 2005-04-16 00:13:17Z mike $" +// +// Help Viewer widget definitions. +// +// Copyright 1997-2005 by Easy Software Products. +// Image support donated by Matthias Melcher, Copyright 2000. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Help_View_H +# define Fl_Help_View_H + +// +// Include necessary header files... +// + +# include <stdio.h> +# include "Fl.H" +# include "Fl_Group.H" +# include "Fl_Scrollbar.H" +# include "fl_draw.H" +# include "Fl_Shared_Image.H" + + +// +// Fl_Help_Func type - link callback function for files... +// + + +typedef const char *(Fl_Help_Func)(Fl_Widget *, const char *); + + +// +// Fl_Help_Block structure... +// + +struct Fl_Help_Block +{ + const char *start, // Start of text + *end; // End of text + uchar border; // Draw border? + Fl_Color bgcolor; // Background color + int x, // Indentation/starting X coordinate + y, // Starting Y coordinate + w, // Width + h; // Height + int line[32]; // Left starting position for each line +}; + +// +// Fl_Help_Link structure... +// + +struct Fl_Help_Link +{ + char filename[192], // Reference filename + name[32]; // Link target (blank if none) + int x, // X offset of link text + y, // Y offset of link text + w, // Width of link text + h; // Height of link text +}; + +// +// Fl_Help_Target structure... +// + +struct Fl_Help_Target +{ + char name[32]; // Target name + int y; // Y offset of target +}; + +// +// Fl_Help_View class... +// + +class FL_EXPORT Fl_Help_View : public Fl_Group //// Help viewer widget +{ + enum { RIGHT = -1, CENTER, LEFT }; // Alignments + + char title_[1024]; // Title string + Fl_Color defcolor_, // Default text color + bgcolor_, // Background color + textcolor_, // Text color + linkcolor_; // Link color + uchar textfont_, // Default font for text + textsize_; // Default font size + const char *value_; // HTML text value + + int nblocks_, // Number of blocks/paragraphs + ablocks_; // Allocated blocks + Fl_Help_Block *blocks_; // Blocks + + int nfonts_; // Number of fonts in stack + uchar fonts_[100][2]; // Font stack + + Fl_Help_Func *link_; // Link transform function + + int nlinks_, // Number of links + alinks_; // Allocated links + Fl_Help_Link *links_; // Links + + int ntargets_, // Number of targets + atargets_; // Allocated targets + Fl_Help_Target *targets_; // Targets + + char directory_[1024]; // Directory for current file + char filename_[1024]; // Current filename + int topline_, // Top line in document + leftline_, // Lefthand position + size_, // Total document length + hsize_; // Maximum document width + Fl_Scrollbar scrollbar_, // Vertical scrollbar for document + hscrollbar_; // Horizontal scrollbar + + Fl_Help_Block *add_block(const char *s, int xx, int yy, int ww, int hh, uchar border = 0); + void add_link(const char *n, int xx, int yy, int ww, int hh); + void add_target(const char *n, int yy); + static int compare_targets(const Fl_Help_Target *t0, const Fl_Help_Target *t1); + int do_align(Fl_Help_Block *block, int line, int xx, int a, int &l); + void draw(); + void format(); + void format_table(int *table_width, int *columns, const char *table); + int get_align(const char *p, int a); + const char *get_attr(const char *p, const char *n, char *buf, int bufsize); + Fl_Color get_color(const char *n, Fl_Color c); + Fl_Shared_Image *get_image(const char *name, int W, int H); + int get_length(const char *l); + int handle(int); + + void initfont(uchar &f, uchar &s) { nfonts_ = 0; + fl_font(f = fonts_[0][0] = textfont_, + s = fonts_[0][1] = textsize_); } + void pushfont(uchar f, uchar s) { if (nfonts_ < 99) nfonts_ ++; + fl_font(fonts_[nfonts_][0] = f, + fonts_[nfonts_][1] = s); } + void popfont(uchar &f, uchar &s) { if (nfonts_ > 0) nfonts_ --; + fl_font(f = fonts_[nfonts_][0], + s = fonts_[nfonts_][1]); } + + public: + + Fl_Help_View(int xx, int yy, int ww, int hh, const char *l = 0); + ~Fl_Help_View(); + const char *directory() const { if (directory_[0]) return (directory_); + else return ((const char *)0); } + const char *filename() const { if (filename_[0]) return (filename_); + else return ((const char *)0); } + int find(const char *s, int p = 0); + void link(Fl_Help_Func *fn) { link_ = fn; } + int load(const char *f); + void resize(int,int,int,int); + int size() const { return (size_); } + void size(int W, int H) { Fl_Widget::size(W, H); } + void textcolor(Fl_Color c) { if (textcolor_ == defcolor_) textcolor_ = c; defcolor_ = c; } + Fl_Color textcolor() const { return (defcolor_); } + void textfont(uchar f) { textfont_ = f; format(); } + uchar textfont() const { return (textfont_); } + void textsize(uchar s) { textsize_ = s; format(); } + uchar textsize() const { return (textsize_); } + const char *title() { return (title_); } + void topline(const char *n); + void topline(int); + int topline() const { return (topline_); } + void leftline(int); + int leftline() const { return (leftline_); } + void value(const char *v); + const char *value() const { return (value_); } +}; + +#endif // !Fl_Help_View_H + +// +// End of "$Id: Fl_Help_View.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Hold_Browser.H b/Utilities/FLTK/FL/Fl_Hold_Browser.H new file mode 100644 index 0000000000..6286a60bf2 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Hold_Browser.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Hold_Browser.H 4288 2005-04-16 00:13:17Z mike $" +// +// Hold browser header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Hold_Browser_H +#define Fl_Hold_Browser_H + +#include "Fl_Browser.H" + +class Fl_Hold_Browser : public Fl_Browser { +public: + Fl_Hold_Browser(int X,int Y,int W,int H,const char *l=0) + : Fl_Browser(X,Y,W,H,l) {type(FL_HOLD_BROWSER);} +}; + +#endif + +// +// End of "$Id: Fl_Hold_Browser.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Hor_Fill_Slider.H b/Utilities/FLTK/FL/Fl_Hor_Fill_Slider.H new file mode 100644 index 0000000000..a7a87f5ea5 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Hor_Fill_Slider.H @@ -0,0 +1,42 @@ +// +// "$Id: Fl_Hor_Fill_Slider.H 4288 2005-04-16 00:13:17Z mike $" +// +// Horizontal fill slider header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +#ifndef Fl_Hor_Fill_Slider_H +#define Fl_Hor_Fill_Slider_H + +#include "Fl_Slider.H" + +class Fl_Hor_Fill_Slider : public Fl_Slider { +public: + Fl_Hor_Fill_Slider(int x,int y,int w,int h,const char *l=0) + : Fl_Slider(x,y,w,h,l) {type(FL_HOR_FILL_SLIDER);} +}; + +#endif + +// +// End of "$Id: Fl_Hor_Fill_Slider.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Hor_Nice_Slider.H b/Utilities/FLTK/FL/Fl_Hor_Nice_Slider.H new file mode 100644 index 0000000000..bed75a51c0 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Hor_Nice_Slider.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Hor_Nice_Slider.H 4288 2005-04-16 00:13:17Z mike $" +// +// Horizontal "nice" slider header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Hor_Nice_Slider_H +#define Fl_Hor_Nice_Slider_H + +#include "Fl_Slider.H" + +class Fl_Hor_Nice_Slider : public Fl_Slider { +public: + Fl_Hor_Nice_Slider(int x,int y,int w,int h,const char *l=0) + : Fl_Slider(x,y,w,h,l) {type(FL_HOR_NICE_SLIDER); box(FL_FLAT_BOX);} +}; + +#endif + +// +// End of "$Id: Fl_Hor_Nice_Slider.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Hor_Slider.H b/Utilities/FLTK/FL/Fl_Hor_Slider.H new file mode 100644 index 0000000000..34be6961eb --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Hor_Slider.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Hor_Slider.H 4288 2005-04-16 00:13:17Z mike $" +// +// Horizontal slider header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Hor_Slider_H +#define Fl_Hor_Slider_H + +#include "Fl_Slider.H" + +class Fl_Hor_Slider : public Fl_Slider { +public: + Fl_Hor_Slider(int X,int Y,int W,int H,const char *l=0) + : Fl_Slider(X,Y,W,H,l) {type(FL_HOR_SLIDER);} +}; + +#endif + +// +// End of "$Id: Fl_Hor_Slider.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Hor_Value_Slider.H b/Utilities/FLTK/FL/Fl_Hor_Value_Slider.H new file mode 100644 index 0000000000..d499feadfa --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Hor_Value_Slider.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Hor_Value_Slider.H 4288 2005-04-16 00:13:17Z mike $" +// +// Horizontal value slider header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Hor_Value_Slider_H +#define Fl_Hor_Value_Slider_H + +#include "Fl_Value_Slider.H" + +class Fl_Hor_Value_Slider : public Fl_Value_Slider { +public: + Fl_Hor_Value_Slider(int X,int Y,int W,int H,const char *l=0) + : Fl_Value_Slider(X,Y,W,H,l) {type(FL_HOR_SLIDER);} +}; + +#endif + +// +// End of "$Id: Fl_Hor_Value_Slider.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Image.H b/Utilities/FLTK/FL/Fl_Image.H new file mode 100644 index 0000000000..4d6f052d50 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Image.H @@ -0,0 +1,112 @@ +// +// "$Id: Fl_Image.H 4288 2005-04-16 00:13:17Z mike $" +// +// Image header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Image_H +# define Fl_Image_H + +# include "Enumerations.H" + +class Fl_Widget; +struct Fl_Menu_Item; +struct Fl_Label; + +class FL_EXPORT Fl_Image { + int w_, h_, d_, ld_, count_; + const char * const *data_; + + // Forbid use of copy contructor and assign operator + Fl_Image & operator=(const Fl_Image &); + Fl_Image(const Fl_Image &); + + protected: + + void w(int W) {w_ = W;} + void h(int H) {h_ = H;} + void d(int D) {d_ = D;} + void ld(int LD) {ld_ = LD;} + void data(const char * const *p, int c) {data_ = p; count_ = c;} + void draw_empty(int X, int Y); + + static void labeltype(const Fl_Label *lo, int lx, int ly, int lw, int lh, Fl_Align la); + static void measure(const Fl_Label *lo, int &lw, int &lh); + + public: + + int w() const {return w_;} + int h() const {return h_;} + int d() const {return d_;} + int ld() const {return ld_;} + int count() const {return count_;} + const char * const *data() const {return data_;} + + Fl_Image(int W, int H, int D) {w_ = W; h_ = H; d_ = D; ld_ = 0; count_ = 0; data_ = 0;} + virtual ~Fl_Image(); + virtual Fl_Image *copy(int W, int H); + Fl_Image *copy() { return copy(w(), h()); } + virtual void color_average(Fl_Color c, float i); + void inactive() { color_average(FL_GRAY, .33f); } + virtual void desaturate(); + virtual void label(Fl_Widget*w); + virtual void label(Fl_Menu_Item*m); + virtual void draw(int X, int Y, int W, int H, int cx=0, int cy=0); + void draw(int X, int Y) {draw(X, Y, w(), h(), 0, 0);} + virtual void uncache(); +}; + +class FL_EXPORT Fl_RGB_Image : public Fl_Image { + public: + + const uchar *array; + int alloc_array; // Non-zero if array was allocated + +#if defined(__APPLE__) || defined(WIN32) + void *id; // for internal use + void *mask; // for internal use (mask bitmap) +#else + unsigned id; // for internal use + unsigned mask; // for internal use (mask bitmap) +#endif // __APPLE__ || WIN32 + + Fl_RGB_Image(const uchar *bits, int W, int H, int D=3, int LD=0) : + Fl_Image(W,H,D), array(bits), alloc_array(0), id(0), mask(0) {data((const char **)&array, 1); ld(LD);} + virtual ~Fl_RGB_Image(); + virtual Fl_Image *copy(int W, int H); + Fl_Image *copy() { return copy(w(), h()); } + virtual void color_average(Fl_Color c, float i); + virtual void desaturate(); + virtual void draw(int X, int Y, int W, int H, int cx=0, int cy=0); + void draw(int X, int Y) {draw(X, Y, w(), h(), 0, 0);} + virtual void label(Fl_Widget*w); + virtual void label(Fl_Menu_Item*m); + virtual void uncache(); +}; + +#endif // !Fl_Image_H + +// +// End of "$Id: Fl_Image.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Input.H b/Utilities/FLTK/FL/Fl_Input.H new file mode 100644 index 0000000000..7debfddfef --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Input.H @@ -0,0 +1,48 @@ +// +// "$Id: Fl_Input.H 4288 2005-04-16 00:13:17Z mike $" +// +// Input header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Input_H +#define Fl_Input_H + +#include "Fl_Input_.H" + +class FL_EXPORT Fl_Input : public Fl_Input_ { + int handle_key(); + int shift_position(int p); + int shift_up_down_position(int p); + void handle_mouse(int keepmark=0); +public: + void draw(); + int handle(int); + Fl_Input(int,int,int,int,const char * = 0); +}; + +#endif + +// +// End of "$Id: Fl_Input.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Input_.H b/Utilities/FLTK/FL/Fl_Input_.H new file mode 100644 index 0000000000..0c52ce613b --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Input_.H @@ -0,0 +1,145 @@ +// +// "$Id: Fl_Input_.H 4288 2005-04-16 00:13:17Z mike $" +// +// Input base class header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Input__H +#define Fl_Input__H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +#define FL_NORMAL_INPUT 0 +#define FL_FLOAT_INPUT 1 +#define FL_INT_INPUT 2 +#define FL_HIDDEN_INPUT 3 +#define FL_MULTILINE_INPUT 4 +#define FL_SECRET_INPUT 5 +#define FL_INPUT_TYPE 7 +#define FL_INPUT_READONLY 8 +#define FL_NORMAL_OUTPUT (FL_NORMAL_INPUT | FL_INPUT_READONLY) +#define FL_MULTILINE_OUTPUT (FL_MULTILINE_INPUT | FL_INPUT_READONLY) +#define FL_INPUT_WRAP 16 +#define FL_MULTILINE_INPUT_WRAP (FL_MULTILINE_INPUT | FL_INPUT_WRAP) +#define FL_MULTILINE_OUTPUT_WRAP (FL_MULTILINE_INPUT | FL_INPUT_READONLY | FL_INPUT_WRAP) + +class FL_EXPORT Fl_Input_ : public Fl_Widget { + + const char* value_; + char* buffer; + + int size_; + int bufsize; + int position_; + int mark_; + int xscroll_, yscroll_; + int mu_p; + int maximum_size_; + + uchar erase_cursor_only; + uchar textfont_; + uchar textsize_; + unsigned textcolor_; + unsigned cursor_color_; + + const char* expand(const char*, char*) const; + double expandpos(const char*, const char*, const char*, int*) const; + void minimal_update(int, int); + void minimal_update(int p); + void put_in_buffer(int newsize); + + void setfont() const; + +protected: + + int word_start(int i) const; + int word_end(int i) const; + int line_start(int i) const; + int line_end(int i) const; + void drawtext(int, int, int, int); + int up_down_position(int, int keepmark=0); + void handle_mouse(int, int, int, int, int keepmark=0); + int handletext(int e, int, int, int, int); + void maybe_do_callback(); + int xscroll() const {return xscroll_;} + int yscroll() const {return yscroll_;} + +public: + + void resize(int, int, int, int); + + Fl_Input_(int, int, int, int, const char* = 0); + ~Fl_Input_(); + + int value(const char*); + int value(const char*, int); + int static_value(const char*); + int static_value(const char*, int); + const char* value() const {return value_;} + char index(int i) const {return value_[i];} + int size() const {return size_;} + void size(int W, int H) { Fl_Widget::size(W, H); } + int maximum_size() const {return maximum_size_;} + void maximum_size(int m) {maximum_size_ = m;} + + int position() const {return position_;} + int mark() const {return mark_;} + int position(int p, int m); + int position(int p) {return position(p, p);} + int mark(int m) {return position(position(), m);} + int replace(int, int, const char*, int=0); + int cut() {return replace(position(), mark(), 0);} + int cut(int n) {return replace(position(), position()+n, 0);} + int cut(int a, int b) {return replace(a, b, 0);} + int insert(const char* t, int l=0){return replace(position_, mark_, t, l);} + int copy(int clipboard); + int undo(); + int copy_cuts(); + + Fl_Font textfont() const {return (Fl_Font)textfont_;} + void textfont(uchar s) {textfont_ = s;} + uchar textsize() const {return textsize_;} + void textsize(uchar s) {textsize_ = s;} + Fl_Color textcolor() const {return (Fl_Color)textcolor_;} + void textcolor(unsigned n) {textcolor_ = n;} + Fl_Color cursor_color() const {return (Fl_Color)cursor_color_;} + void cursor_color(unsigned n) {cursor_color_ = n;} + + int input_type() const {return type() & FL_INPUT_TYPE; } + void input_type(int t) { type((uchar)(t | readonly())); } + int readonly() const { return type() & FL_INPUT_READONLY; } + void readonly(int b) { if (b) type((uchar)(type() | FL_INPUT_READONLY)); + else type((uchar)(type() & ~FL_INPUT_READONLY)); } + int wrap() const { return type() & FL_INPUT_WRAP; } + void wrap(int b) { if (b) type((uchar)(type() | FL_INPUT_WRAP)); + else type((uchar)(type() & ~FL_INPUT_WRAP)); } +}; + +#endif + +// +// End of "$Id: Fl_Input_.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Input_Choice.H b/Utilities/FLTK/FL/Fl_Input_Choice.H new file mode 100644 index 0000000000..d4acb4462b --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Input_Choice.H @@ -0,0 +1,154 @@ +// +// "$Id$" +// +// An input/chooser widget. +// ______________ ____ +// | || __ | +// | input area || \/ | +// |______________||____| +// +// Copyright 1998-2005 by Bill Spitzak and others. +// Copyright 2004 by Greg Ercolano. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Input_Choice_H +#define Fl_Input_Choice_H + +#include <FL/Fl.H> +#include <FL/Fl_Input.H> +#include <FL/Fl_Menu_Button.H> +#include <FL/fl_draw.H> + +class Fl_Input_Choice : public Fl_Group { + // Private class to handle slightly 'special' behavior of menu button + class InputMenuButton : public Fl_Menu_Button { + void draw() { + draw_box(FL_UP_BOX, color()); + fl_color(active_r() ? labelcolor() : fl_inactive(labelcolor())); + int xc = x()+w()/2, yc=y()+h()/2; + fl_polygon(xc-5,yc-3,xc+5,yc-3,xc,yc+3); + if (Fl::focus() == this) draw_focus(); + } + public: + InputMenuButton(int x,int y,int w,int h,const char*l=0) : + Fl_Menu_Button(x,y,w,h,l) { box(FL_UP_BOX); } + }; + + Fl_Input *inp_; + InputMenuButton *menu_; + + static void menu_cb(Fl_Widget*, void *data) { + Fl_Input_Choice *o=(Fl_Input_Choice *)data; + o->inp_->value(o->menu_->text()); + o->do_callback(); + } + + static void inp_cb(Fl_Widget*, void *data) { + Fl_Input_Choice *o=(Fl_Input_Choice *)data; + o->do_callback(); + } + + // Custom resize behavior -- input stretches, menu button doesn't + inline int inp_x() { return(x() + Fl::box_dx(box())); } + inline int inp_y() { return(y() + Fl::box_dy(box())); } + inline int inp_w() { return(w() - Fl::box_dw(box()) - 20); } + inline int inp_h() { return(h() - Fl::box_dh(box())); } + + inline int menu_x() { return(x() + w() - 20 - Fl::box_dx(box())); } + inline int menu_y() { return(y() + Fl::box_dy(box())); } + inline int menu_w() { return(20); } + inline int menu_h() { return(h() - Fl::box_dh(box())); } + +public: + Fl_Input_Choice (int x,int y,int w,int h,const char*l=0) : Fl_Group(x,y,w,h,l) { + Fl_Group::box(FL_DOWN_BOX); + align(FL_ALIGN_LEFT); // default like Fl_Input + inp_ = new Fl_Input(inp_x(), inp_y(), + inp_w(), inp_h()); + inp_->callback(inp_cb, (void*)this); + inp_->box(FL_FLAT_BOX); // cosmetic + menu_ = new InputMenuButton(menu_x(), menu_y(), + menu_w(), menu_h()); + menu_->callback(menu_cb, (void*)this); + menu_->box(FL_FLAT_BOX); // cosmetic + end(); + } + void add(const char *s) { + menu_->add(s); + } + void clear() { + menu_->clear(); + } + Fl_Boxtype down_box() const { + return (menu_->down_box()); + } + void down_box(Fl_Boxtype b) { + menu_->down_box(b); + } + const Fl_Menu_Item *menu() { + return (menu_->menu()); + } + void menu(const Fl_Menu_Item *m) { + menu_->menu(m); + } + void resize(int X, int Y, int W, int H) { + Fl_Group::resize(X,Y,W,H); + inp_->resize(inp_x(), inp_y(), inp_w(), inp_h()); + menu_->resize(menu_x(), menu_y(), menu_w(), menu_h()); + } + Fl_Color textcolor() const { + return (inp_->textcolor()); + } + void textcolor(Fl_Color c) { + inp_->textcolor(c); + } + uchar textfont() const { + return (inp_->textfont()); + } + void textfont(uchar f) { + inp_->textfont(f); + } + uchar textsize() const { + return (inp_->textsize()); + } + void textsize(uchar s) { + inp_->textsize(s); + } + const char* value() const { + return (inp_->value()); + } + void value(const char *val) { + inp_->value(val); + } + void value(int val) { + menu_->value(val); + inp_->value(menu_->text(val)); + } + Fl_Menu_Button *menubutton() { return menu_; } + Fl_Input *input() { return inp_; } +}; + +#endif // !Fl_Input_Choice_H + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/FL/Fl_Int_Input.H b/Utilities/FLTK/FL/Fl_Int_Input.H new file mode 100644 index 0000000000..641ad1639a --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Int_Input.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Int_Input.H 4288 2005-04-16 00:13:17Z mike $" +// +// Integer input header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Int_Input_H +#define Fl_Int_Input_H + +#include "Fl_Input.H" + +class Fl_Int_Input : public Fl_Input { +public: + Fl_Int_Input(int X,int Y,int W,int H,const char *l = 0) + : Fl_Input(X,Y,W,H,l) {type(FL_INT_INPUT);} +}; + +#endif + +// +// End of "$Id: Fl_Int_Input.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_JPEG_Image.H b/Utilities/FLTK/FL/Fl_JPEG_Image.H new file mode 100644 index 0000000000..234c8bbebf --- /dev/null +++ b/Utilities/FLTK/FL/Fl_JPEG_Image.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_JPEG_Image.H 4288 2005-04-16 00:13:17Z mike $" +// +// JPEG image header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_JPEG_Image_H +#define Fl_JPEG_Image_H +# include "Fl_Image.H" + +class FL_EXPORT Fl_JPEG_Image : public Fl_RGB_Image { + + public: + + Fl_JPEG_Image(const char* filename); +}; + +#endif + +// +// End of "$Id: Fl_JPEG_Image.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Light_Button.H b/Utilities/FLTK/FL/Fl_Light_Button.H new file mode 100644 index 0000000000..f056a3001d --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Light_Button.H @@ -0,0 +1,45 @@ +// +// "$Id: Fl_Light_Button.H 4288 2005-04-16 00:13:17Z mike $" +// +// Lighted button header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Light_Button_H +#define Fl_Light_Button_H + +#include "Fl_Button.H" + +class FL_EXPORT Fl_Light_Button : public Fl_Button { +protected: + virtual void draw(); +public: + virtual int handle(int); + Fl_Light_Button(int x,int y,int w,int h,const char *l = 0); +}; + +#endif + +// +// End of "$Id: Fl_Light_Button.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Line_Dial.H b/Utilities/FLTK/FL/Fl_Line_Dial.H new file mode 100644 index 0000000000..301bff9def --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Line_Dial.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Line_Dial.H 4288 2005-04-16 00:13:17Z mike $" +// +// Line dial header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Line_Dial_H +#define Fl_Line_Dial_H + +#include "Fl_Dial.H" + +class Fl_Line_Dial : public Fl_Dial { +public: + Fl_Line_Dial(int x,int y,int w,int h, const char *l = 0) + : Fl_Dial(x,y,w,h,l) {type(FL_LINE_DIAL);} +}; + +#endif + +// +// End of "$Id: Fl_Line_Dial.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Menu.H b/Utilities/FLTK/FL/Fl_Menu.H new file mode 100644 index 0000000000..9d77980173 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Menu.H @@ -0,0 +1,33 @@ +// +// "$Id: Fl_Menu.H 4288 2005-04-16 00:13:17Z mike $" +// +// Old menu header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// this include file is for back compatability only +#include "Fl_Menu_Item.H" + +// +// End of "$Id: Fl_Menu.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Menu_.H b/Utilities/FLTK/FL/Fl_Menu_.H new file mode 100644 index 0000000000..b04e4e93d9 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Menu_.H @@ -0,0 +1,102 @@ +// +// "$Id: Fl_Menu_.H 4288 2005-04-16 00:13:17Z mike $" +// +// Menu base class header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Menu__H +#define Fl_Menu__H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif +#include "Fl_Menu_Item.H" + +class FL_EXPORT Fl_Menu_ : public Fl_Widget { + + Fl_Menu_Item *menu_; + const Fl_Menu_Item *value_; + +protected: + + uchar alloc; + uchar down_box_; + uchar textfont_; + uchar textsize_; + unsigned textcolor_; + +public: + Fl_Menu_(int,int,int,int,const char * =0); + ~Fl_Menu_(); + + int item_pathname(char *name, int namelen, const Fl_Menu_Item *finditem=0) const; + const Fl_Menu_Item* picked(const Fl_Menu_Item*); + const Fl_Menu_Item* find_item(const char *name); + + const Fl_Menu_Item* test_shortcut() {return picked(menu()->test_shortcut());} + void global(); + + const Fl_Menu_Item *menu() const {return menu_;} + void menu(const Fl_Menu_Item *m); + void copy(const Fl_Menu_Item *m, void* user_data = 0); + int add(const char*, int shortcut, Fl_Callback*, void* = 0, int = 0); + int add(const char* a, const char* b, Fl_Callback* c, + void* d = 0, int e = 0) {return add(a,fl_old_shortcut(b),c,d,e);} + int size() const ; + void size(int W, int H) { Fl_Widget::size(W, H); } + void clear(); + int add(const char *); + void replace(int,const char *); + void remove(int); + void shortcut(int i, int s) {menu_[i].shortcut(s);} + void mode(int i,int fl) {menu_[i].flags = fl;} + int mode(int i) const {return menu_[i].flags;} + + const Fl_Menu_Item *mvalue() const {return value_;} + int value() const {return value_ ? (int)(value_-menu_) : -1;} + int value(const Fl_Menu_Item*); + int value(int i) {return value(menu_+i);} + const char *text() const {return value_ ? value_->text : 0;} + const char *text(int i) const {return menu_[i].text;} + + Fl_Font textfont() const {return (Fl_Font)textfont_;} + void textfont(uchar c) {textfont_=c;} + uchar textsize() const {return textsize_;} + void textsize(uchar c) {textsize_=c;} + Fl_Color textcolor() const {return (Fl_Color)textcolor_;} + void textcolor(unsigned c) {textcolor_=c;} + + Fl_Boxtype down_box() const {return (Fl_Boxtype)down_box_;} + void down_box(Fl_Boxtype b) {down_box_ = b;} + + // back compatability: + Fl_Color down_color() const {return selection_color();} + void down_color(unsigned c) {selection_color(c);} +}; + +#endif + +// +// End of "$Id: Fl_Menu_.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Menu_Bar.H b/Utilities/FLTK/FL/Fl_Menu_Bar.H new file mode 100644 index 0000000000..ab240da7a7 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Menu_Bar.H @@ -0,0 +1,46 @@ +// +// "$Id: Fl_Menu_Bar.H 4288 2005-04-16 00:13:17Z mike $" +// +// Menu bar header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Menu_Bar_H +#define Fl_Menu_Bar_H + +#include "Fl_Menu_.H" + +class FL_EXPORT Fl_Menu_Bar : public Fl_Menu_ { +protected: + void draw(); +public: + int handle(int); + Fl_Menu_Bar(int X, int Y, int W, int H,const char *l=0) + : Fl_Menu_(X,Y,W,H,l) {} +}; + +#endif + +// +// End of "$Id: Fl_Menu_Bar.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Menu_Button.H b/Utilities/FLTK/FL/Fl_Menu_Button.H new file mode 100644 index 0000000000..39a2665a09 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Menu_Button.H @@ -0,0 +1,48 @@ +// +// "$Id: Fl_Menu_Button.H 4288 2005-04-16 00:13:17Z mike $" +// +// Menu button header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Menu_Button_H +#define Fl_Menu_Button_H + +#include "Fl_Menu_.H" + +class FL_EXPORT Fl_Menu_Button : public Fl_Menu_ { +protected: + void draw(); +public: + // values for type: + enum {POPUP1 = 1, POPUP2, POPUP12, POPUP3, POPUP13, POPUP23, POPUP123}; + int handle(int); + const Fl_Menu_Item* popup(); + Fl_Menu_Button(int,int,int,int,const char * =0); +}; + +#endif + +// +// End of "$Id: Fl_Menu_Button.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Menu_Item.H b/Utilities/FLTK/FL/Fl_Menu_Item.H new file mode 100644 index 0000000000..33e520a670 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Menu_Item.H @@ -0,0 +1,167 @@ +// +// "$Id: Fl_Menu_Item.H 4288 2005-04-16 00:13:17Z mike $" +// +// Menu item header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Menu_Item_H +#define Fl_Menu_Item_H + +# include "Fl_Widget.H" +# include "Fl_Image.H" + +# if defined(__APPLE__) && defined(check) +# undef check +# endif + +enum { // values for flags: + FL_MENU_INACTIVE = 1, + FL_MENU_TOGGLE= 2, + FL_MENU_VALUE = 4, + FL_MENU_RADIO = 8, + FL_MENU_INVISIBLE = 0x10, + FL_SUBMENU_POINTER = 0x20, + FL_SUBMENU = 0x40, + FL_MENU_DIVIDER = 0x80, + FL_MENU_HORIZONTAL = 0x100 +}; + +extern FL_EXPORT int fl_old_shortcut(const char*); + +class Fl_Menu_; + +struct FL_EXPORT Fl_Menu_Item { + const char *text; // label() + int shortcut_; + Fl_Callback *callback_; + void *user_data_; + int flags; + uchar labeltype_; + uchar labelfont_; + uchar labelsize_; + unsigned labelcolor_; + + // advance N items, skipping submenus: + const Fl_Menu_Item *next(int=1) const; + Fl_Menu_Item *next(int i=1) { + return (Fl_Menu_Item*)(((const Fl_Menu_Item*)this)->next(i));} + const Fl_Menu_Item *first() const { return next(0); } + Fl_Menu_Item *first() { return next(0); } + + // methods on menu items: + const char* label() const {return text;} + void label(const char* a) {text=a;} + void label(Fl_Labeltype a,const char* b) {labeltype_ = a; text = b;} + Fl_Labeltype labeltype() const {return (Fl_Labeltype)labeltype_;} + void labeltype(Fl_Labeltype a) {labeltype_ = a;} + Fl_Color labelcolor() const {return (Fl_Color)labelcolor_;} + void labelcolor(unsigned a) {labelcolor_ = a;} + Fl_Font labelfont() const {return (Fl_Font)labelfont_;} + void labelfont(uchar a) {labelfont_ = a;} + uchar labelsize() const {return labelsize_;} + void labelsize(uchar a) {labelsize_ = a;} + Fl_Callback_p callback() const {return callback_;} + void callback(Fl_Callback* c, void* p) {callback_=c; user_data_=p;} + void callback(Fl_Callback* c) {callback_=c;} + void callback(Fl_Callback0*c) {callback_=(Fl_Callback*)c;} + void callback(Fl_Callback1*c, long p=0) {callback_=(Fl_Callback*)c; user_data_=(void*)p;} + void* user_data() const {return user_data_;} + void user_data(void* v) {user_data_ = v;} + long argument() const {return (long)user_data_;} + void argument(long v) {user_data_ = (void*)v;} + int shortcut() const {return shortcut_;} + void shortcut(int s) {shortcut_ = s;} + int submenu() const {return flags&(FL_SUBMENU|FL_SUBMENU_POINTER);} + int checkbox() const {return flags&FL_MENU_TOGGLE;} + int radio() const {return flags&FL_MENU_RADIO;} + int value() const {return flags&FL_MENU_VALUE;} + void set() {flags |= FL_MENU_VALUE;} + void clear() {flags &= ~FL_MENU_VALUE;} + void setonly(); + int visible() const {return !(flags&FL_MENU_INVISIBLE);} + void show() {flags &= ~FL_MENU_INVISIBLE;} + void hide() {flags |= FL_MENU_INVISIBLE;} + int active() const {return !(flags&FL_MENU_INACTIVE);} + void activate() {flags &= ~FL_MENU_INACTIVE;} + void deactivate() {flags |= FL_MENU_INACTIVE;} + int activevisible() const {return !(flags&0x11);} + + // compatibility for FLUID so it can set the image of a menu item... + void image(Fl_Image* a) {a->label(this);} + void image(Fl_Image& a) {a.label(this);} + + // used by menubar: + int measure(int* h, const Fl_Menu_*) const; + void draw(int x, int y, int w, int h, const Fl_Menu_*, int t=0) const; + + // popup menus without using an Fl_Menu_ widget: + const Fl_Menu_Item* popup( + int X, int Y, + const char *title = 0, + const Fl_Menu_Item* picked=0, + const Fl_Menu_* = 0) const; + const Fl_Menu_Item* pulldown( + int X, int Y, int W, int H, + const Fl_Menu_Item* picked = 0, + const Fl_Menu_* = 0, + const Fl_Menu_Item* title = 0, + int menubar=0) const; + const Fl_Menu_Item* test_shortcut() const; + const Fl_Menu_Item* find_shortcut(int *ip=0) const; + + void do_callback(Fl_Widget* o) const {callback_(o, user_data_);} + void do_callback(Fl_Widget* o,void* arg) const {callback_(o, arg);} + void do_callback(Fl_Widget* o,long arg) const {callback_(o, (void*)arg);} + + // back-compatability, do not use: + int checked() const {return flags&FL_MENU_VALUE;} + void check() {flags |= FL_MENU_VALUE;} + void uncheck() {flags &= ~FL_MENU_VALUE;} + int add(const char*, int shortcut, Fl_Callback*, void* =0, int = 0); + int add(const char*a, const char* b, Fl_Callback* c, + void* d = 0, int e = 0) { + return add(a,fl_old_shortcut(b),c,d,e);} + int size() const ; +}; + +typedef Fl_Menu_Item Fl_Menu; // back compatability + +enum { // back-compatability enum: + FL_PUP_NONE = 0, + FL_PUP_GREY = FL_MENU_INACTIVE, + FL_PUP_GRAY = FL_MENU_INACTIVE, + FL_MENU_BOX = FL_MENU_TOGGLE, + FL_PUP_BOX = FL_MENU_TOGGLE, + FL_MENU_CHECK = FL_MENU_VALUE, + FL_PUP_CHECK = FL_MENU_VALUE, + FL_PUP_RADIO = FL_MENU_RADIO, + FL_PUP_INVISIBLE = FL_MENU_INVISIBLE, + FL_PUP_SUBMENU = FL_SUBMENU_POINTER +}; + +#endif + +// +// End of "$Id: Fl_Menu_Item.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Menu_Window.H b/Utilities/FLTK/FL/Fl_Menu_Window.H new file mode 100644 index 0000000000..1056fb2e0c --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Menu_Window.H @@ -0,0 +1,54 @@ +// +// "$Id: Fl_Menu_Window.H 4288 2005-04-16 00:13:17Z mike $" +// +// Menu window header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Menu_Window_H +#define Fl_Menu_Window_H + +#include "Fl_Single_Window.H" + +class FL_EXPORT Fl_Menu_Window : public Fl_Single_Window { + enum {NO_OVERLAY = 128}; +public: + void show(); + void erase(); + void flush(); + void hide(); + int overlay() {return !(flags()&NO_OVERLAY);} + void set_overlay() {clear_flag(NO_OVERLAY);} + void clear_overlay() {set_flag(NO_OVERLAY);} + ~Fl_Menu_Window(); + Fl_Menu_Window(int W, int H, const char *l = 0) + : Fl_Single_Window(W,H,l) { image(0); } + Fl_Menu_Window(int X, int Y, int W, int H, const char *l = 0) + : Fl_Single_Window(X,Y,W,H,l) { image(0); } +}; + +#endif + +// +// End of "$Id: Fl_Menu_Window.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Multi_Browser.H b/Utilities/FLTK/FL/Fl_Multi_Browser.H new file mode 100644 index 0000000000..c1646dc05a --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Multi_Browser.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Multi_Browser.H 4288 2005-04-16 00:13:17Z mike $" +// +// Multi browser header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Multi_Browser_H +#define Fl_Multi_Browser_H + +#include "Fl_Browser.H" + +class Fl_Multi_Browser : public Fl_Browser { +public: + Fl_Multi_Browser(int X,int Y,int W,int H,const char *L=0) + : Fl_Browser(X,Y,W,H,L) {type(FL_MULTI_BROWSER);} +}; + +#endif + +// +// End of "$Id: Fl_Multi_Browser.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Multi_Label.H b/Utilities/FLTK/FL/Fl_Multi_Label.H new file mode 100644 index 0000000000..f4f915112f --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Multi_Label.H @@ -0,0 +1,47 @@ +// +// "$Id: Fl_Multi_Label.H 4288 2005-04-16 00:13:17Z mike $" +// +// Multi-label header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Multi_Label_H +#define Fl_Multi_Label_H + +class Fl_Widget; +struct Fl_Menu_Item; + +struct FL_EXPORT Fl_Multi_Label { + const char* labela; + const char* labelb; + uchar typea; + uchar typeb; + void label(Fl_Widget*); + void label(Fl_Menu_Item*); +}; + +#endif + +// +// End of "$Id: Fl_Multi_Label.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Multiline_Input.H b/Utilities/FLTK/FL/Fl_Multiline_Input.H new file mode 100644 index 0000000000..0d6d1ddd22 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Multiline_Input.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Multiline_Input.H 4288 2005-04-16 00:13:17Z mike $" +// +// Multiline input header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Multiline_Input_H +#define Fl_Multiline_Input_H + +#include "Fl_Input.H" + +class Fl_Multiline_Input : public Fl_Input { +public: + Fl_Multiline_Input(int X,int Y,int W,int H,const char *l = 0) + : Fl_Input(X,Y,W,H,l) {type(FL_MULTILINE_INPUT);} +}; + +#endif + +// +// End of "$Id: Fl_Multiline_Input.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Multiline_Output.H b/Utilities/FLTK/FL/Fl_Multiline_Output.H new file mode 100644 index 0000000000..6d243587d6 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Multiline_Output.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Multiline_Output.H 4288 2005-04-16 00:13:17Z mike $" +// +// Multi line output header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Multiline_Output_H +#define Fl_Multiline_Output_H + +#include "Fl_Output.H" + +class Fl_Multiline_Output : public Fl_Output { +public: + Fl_Multiline_Output(int X,int Y,int W,int H,const char *l = 0) + : Fl_Output(X,Y,W,H,l) {type(FL_MULTILINE_OUTPUT);} +}; + +#endif + +// +// End of "$Id: Fl_Multiline_Output.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Nice_Slider.H b/Utilities/FLTK/FL/Fl_Nice_Slider.H new file mode 100644 index 0000000000..6a623f9ed0 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Nice_Slider.H @@ -0,0 +1,42 @@ +// +// "$Id: Fl_Nice_Slider.H 4288 2005-04-16 00:13:17Z mike $" +// +// "Nice" slider header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +#ifndef Fl_Nice_Slider_H +#define Fl_Nice_Slider_H + +#include "Fl_Slider.H" + +class Fl_Nice_Slider : public Fl_Slider { +public: + Fl_Nice_Slider(int x,int y,int w,int h,const char *l=0) + : Fl_Slider(x,y,w,h,l) {type(FL_VERT_NICE_SLIDER); box(FL_FLAT_BOX);} +}; + +#endif + +// +// End of "$Id: Fl_Nice_Slider.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Object.H b/Utilities/FLTK/FL/Fl_Object.H new file mode 100644 index 0000000000..e2a040452a --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Object.H @@ -0,0 +1,36 @@ +// +// "$Id: Fl_Object.H 4288 2005-04-16 00:13:17Z mike $" +// +// Old Fl_Object header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// This file is provided for back compatability only. Please use Fl_Widget +#ifndef Fl_Object +#define Fl_Object Fl_Widget +#endif +#include "Fl_Widget.H" + +// +// End of "$Id: Fl_Object.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Output.H b/Utilities/FLTK/FL/Fl_Output.H new file mode 100644 index 0000000000..23414b4023 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Output.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Output.H 4288 2005-04-16 00:13:17Z mike $" +// +// Output header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Output_H +#define Fl_Output_H + +#include "Fl_Input.H" + +class Fl_Output : public Fl_Input { +public: + Fl_Output(int X,int Y,int W,int H, const char *l = 0) + : Fl_Input(X, Y, W, H, l) {type(FL_NORMAL_OUTPUT);} +}; + +#endif + +// +// End of "$Id: Fl_Output.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Overlay_Window.H b/Utilities/FLTK/FL/Fl_Overlay_Window.H new file mode 100644 index 0000000000..bf873d2fbc --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Overlay_Window.H @@ -0,0 +1,56 @@ +// +// "$Id: Fl_Overlay_Window.H 4288 2005-04-16 00:13:17Z mike $" +// +// Overlay window header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Overlay_Window_H +#define Fl_Overlay_Window_H + +#include "Fl_Double_Window.H" + +class FL_EXPORT Fl_Overlay_Window : public Fl_Double_Window { + friend class _Fl_Overlay; + virtual void draw_overlay() = 0; + Fl_Window *overlay_; +public: + void show(); + void flush(); + void hide(); + void resize(int,int,int,int); + ~Fl_Overlay_Window(); + int can_do_overlay(); + void redraw_overlay(); + Fl_Overlay_Window(int W, int H, const char *l=0) + : Fl_Double_Window(W,H,l) {overlay_ = 0; force_doublebuffering_=1; image(0); } + Fl_Overlay_Window(int X, int Y, int W, int H, const char *l=0) + : Fl_Double_Window(X,Y,W,H,l) {overlay_ = 0; force_doublebuffering_=1; image(0); } + void show(int a, char **b) {Fl_Double_Window::show(a,b);} +}; + +#endif + +// +// End of "$Id: Fl_Overlay_Window.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_PNG_Image.H b/Utilities/FLTK/FL/Fl_PNG_Image.H new file mode 100644 index 0000000000..f11e6239fe --- /dev/null +++ b/Utilities/FLTK/FL/Fl_PNG_Image.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_PNG_Image.H 4288 2005-04-16 00:13:17Z mike $" +// +// PNG image header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_PNG_Image_H +#define Fl_PNG_Image_H +# include "Fl_Image.H" + +class FL_EXPORT Fl_PNG_Image : public Fl_RGB_Image { + + public: + + Fl_PNG_Image(const char* filename); +}; + +#endif + +// +// End of "$Id: Fl_PNG_Image.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_PNM_Image.H b/Utilities/FLTK/FL/Fl_PNM_Image.H new file mode 100644 index 0000000000..314c384842 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_PNM_Image.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_PNM_Image.H 4288 2005-04-16 00:13:17Z mike $" +// +// PNM image header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_PNM_Image_H +#define Fl_PNM_Image_H +# include "Fl_Image.H" + +class FL_EXPORT Fl_PNM_Image : public Fl_RGB_Image { + + public: + + Fl_PNM_Image(const char* filename); +}; + +#endif + +// +// End of "$Id: Fl_PNM_Image.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Pack.H b/Utilities/FLTK/FL/Fl_Pack.H new file mode 100644 index 0000000000..8e3c2ba728 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Pack.H @@ -0,0 +1,51 @@ +// +// "$Id: Fl_Pack.H 4288 2005-04-16 00:13:17Z mike $" +// +// Pack header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Pack_H +#define Fl_Pack_H + +#include <FL/Fl_Group.H> + +class FL_EXPORT Fl_Pack : public Fl_Group { + int spacing_; +public: + enum { // values for type(int) + VERTICAL = 0, + HORIZONTAL = 1 + }; + void draw(); + Fl_Pack(int x,int y,int w ,int h,const char *l = 0); + int spacing() const {return spacing_;} + void spacing(int i) {spacing_ = i;} + uchar horizontal() const {return type();} +}; + +#endif + +// +// End of "$Id: Fl_Pack.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Pixmap.H b/Utilities/FLTK/FL/Fl_Pixmap.H new file mode 100644 index 0000000000..97f1f26950 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Pixmap.H @@ -0,0 +1,80 @@ +// +// "$Id: Fl_Pixmap.H 4288 2005-04-16 00:13:17Z mike $" +// +// Pixmap header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Pixmap_H +#define Fl_Pixmap_H +# include "Fl_Image.H" + +class Fl_Widget; +struct Fl_Menu_Item; + +// Older C++ compilers don't support the explicit keyword... :( +# if defined(__sgi) && !defined(_COMPILER_VERSION) +# define explicit +# endif // __sgi && !_COMPILER_VERSION + +class FL_EXPORT Fl_Pixmap : public Fl_Image { + void copy_data(); + void delete_data(); + void set_data(const char * const *p); + + protected: + + void measure(); + + public: + + int alloc_data; // Non-zero if data was allocated +#if defined(__APPLE__) || defined(WIN32) + void *id; // for internal use + void *mask; // for internal use (mask bitmap) +#else + unsigned id; // for internal use + unsigned mask; // for internal use (mask bitmap) +#endif // __APPLE__ || WIN32 + + explicit Fl_Pixmap(char * const * D) : Fl_Image(-1,0,1), alloc_data(0), id(0), mask(0) {set_data((const char*const*)D); measure();} + explicit Fl_Pixmap(uchar* const * D) : Fl_Image(-1,0,1), alloc_data(0), id(0), mask(0) {set_data((const char*const*)D); measure();} + explicit Fl_Pixmap(const char * const * D) : Fl_Image(-1,0,1), alloc_data(0), id(0), mask(0) {set_data((const char*const*)D); measure();} + explicit Fl_Pixmap(const uchar* const * D) : Fl_Image(-1,0,1), alloc_data(0), id(0), mask(0) {set_data((const char*const*)D); measure();} + virtual ~Fl_Pixmap(); + virtual Fl_Image *copy(int W, int H); + Fl_Image *copy() { return copy(w(), h()); } + virtual void color_average(Fl_Color c, float i); + virtual void desaturate(); + virtual void draw(int X, int Y, int W, int H, int cx=0, int cy=0); + void draw(int X, int Y) {draw(X, Y, w(), h(), 0, 0);} + virtual void label(Fl_Widget*w); + virtual void label(Fl_Menu_Item*m); + virtual void uncache(); +}; + +#endif + +// +// End of "$Id: Fl_Pixmap.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Positioner.H b/Utilities/FLTK/FL/Fl_Positioner.H new file mode 100644 index 0000000000..dbd147f377 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Positioner.H @@ -0,0 +1,77 @@ +// +// "$Id: Fl_Positioner.H 4288 2005-04-16 00:13:17Z mike $" +// +// Positioner header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Positioner_H +#define Fl_Positioner_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +class FL_EXPORT Fl_Positioner : public Fl_Widget { + + double xmin, ymin; + double xmax, ymax; + double xvalue_, yvalue_; + double xstep_, ystep_; + +protected: + + // these allow subclasses to put the dial in a smaller area: + void draw(int, int, int, int); + int handle(int, int, int, int, int); + void draw(); + +public: + + int handle(int); + Fl_Positioner(int x,int y,int w,int h, const char *l=0); + double xvalue() const {return xvalue_;} + double yvalue() const {return yvalue_;} + int xvalue(double); + int yvalue(double); + int value(double,double); + void xbounds(double, double); + double xminimum() const {return xmin;} + void xminimum(double a) {xbounds(a,xmax);} + double xmaximum() const {return xmax;} + void xmaximum(double a) {xbounds(xmin,a);} + void ybounds(double, double); + double yminimum() const {return ymin;} + void yminimum(double a) {ybounds(a,ymax);} + double ymaximum() const {return ymax;} + void ymaximum(double a) {ybounds(ymin,a);} + void xstep(double a) {xstep_ = a;} + void ystep(double a) {ystep_ = a;} + +}; + +#endif + +// +// End of "$Id: Fl_Positioner.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Preferences.H b/Utilities/FLTK/FL/Fl_Preferences.H new file mode 100644 index 0000000000..b583d2ea51 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Preferences.H @@ -0,0 +1,169 @@ +// +// "$Id: Fl_Preferences.H 4458 2005-07-26 07:59:01Z matt $" +// +// Preferences definitions for the Fast Light Tool Kit (FLTK). +// +// Copyright 2002-2005 by Matthias Melcher. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Preferences_H +# define Fl_Preferences_H + +# ifdef WIN32 +# include <windows.h> +# endif // WIN32 + +# include <stdio.h> +# include "Fl_Export.H" + + +/** + * Preferences are a data tree containing a root, branches and leafs + */ +class FL_EXPORT Fl_Preferences +{ + +public: + + enum Root { SYSTEM=0, USER }; + // enum Type { win32, macos, fltk }; + + Fl_Preferences( Root root, const char *vendor, const char *application ); + Fl_Preferences( const char *path, const char *vendor, const char *application ); + Fl_Preferences( Fl_Preferences&, const char *group ); + Fl_Preferences( Fl_Preferences*, const char *group ); + ~Fl_Preferences(); + + int groups(); + const char *group( int ); + char groupExists( const char *group ); + char deleteGroup( const char *group ); + + int entries(); + const char *entry( int ); + char entryExists( const char *entry ); + char deleteEntry( const char *entry ); + + char set( const char *entry, int value ); + char set( const char *entry, float value ); + char set( const char *entry, double value ); + char set( const char *entry, const char *value ); + char set( const char *entry, const void *value, int size ); + + char get( const char *entry, int &value, int defaultValue ); + char get( const char *entry, float &value, float defaultValue ); + char get( const char *entry, double &value, double defaultValue ); + char get( const char *entry, char *&value, const char *defaultValue ); + char get( const char *entry, char *value, const char *defaultValue, int maxSize ); + char get( const char *entry, void *&value, const void *defaultValue, int defaultSize ); + char get( const char *entry, void *value, const void *defaultValue, int defaultSize, int maxSize ); + int size( const char *entry ); + + char getUserdataPath( char *path, int pathlen ); + + void flush(); + + // char export( const char *filename, Type fileFormat ); + // char import( const char *filename ); + + class FL_EXPORT Name { + char *data_; + public: + Name( unsigned int n ); + Name( const char *format, ... ); + operator const char *() { return data_; } + ~Name(); + }; + + struct Entry + { + char *name, *value; + }; + +private: + + // make the following functions unavailable + Fl_Preferences(); + Fl_Preferences(const Fl_Preferences&); + Fl_Preferences &operator=(const Fl_Preferences&); + + static char nameBuffer[128]; + + class FL_EXPORT Node // a node contains a list to all its entries + { // and all means to manage the tree structure + Node *child_, *next_, *parent_; + char *path_; + char dirty_; + public: + Node( const char *path ); + ~Node(); + // node methods + int write( FILE *f ); + Node *find( const char *path ); + Node *search( const char *path, int offset=0 ); + Node *addChild( const char *path ); + void setParent( Node *parent ); + Node *parent() { return parent_; } + char remove(); + char dirty(); + // entry methods + int nChildren(); + const char *child( int ix ); + void set( const char *name, const char *value ); + void set( const char *line ); + void add( const char *line ); + const char *get( const char *name ); + int getEntry( const char *name ); + char deleteEntry( const char *name ); + // public values + Entry *entry; + int nEntry, NEntry; + static int lastEntrySet; + }; + friend class Node; + + class FL_EXPORT RootNode // the root node manages file paths and basic reading and writing + { + Fl_Preferences *prefs_; + char *filename_; + char *vendor_, *application_; + public: + RootNode( Fl_Preferences *, Root root, const char *vendor, const char *application ); + RootNode( Fl_Preferences *, const char *path, const char *vendor, const char *application ); + ~RootNode(); + int read(); + int write(); + char getPath( char *path, int pathlen ); + }; + friend class RootNode; + + Node *node; + RootNode *rootNode; + +}; + + +#endif // !Fl_Preferences_H + +// +// End of "$Id: Fl_Preferences.H 4458 2005-07-26 07:59:01Z matt $". +// diff --git a/Utilities/FLTK/FL/Fl_Progress.H b/Utilities/FLTK/FL/Fl_Progress.H new file mode 100644 index 0000000000..836d53ad77 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Progress.H @@ -0,0 +1,70 @@ +// +// "$Id: Fl_Progress.H 4288 2005-04-16 00:13:17Z mike $" +// +// Progress bar widget definitions. +// +// Copyright 2000-2005 by Michael Sweet. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef _Fl_Progress_H_ +# define _Fl_Progress_H_ + +// +// Include necessary headers. +// + +#include "Fl_Widget.H" + + +// +// Progress class... +// + +class FL_EXPORT Fl_Progress : public Fl_Widget +{ + float value_, + minimum_, + maximum_; + + protected: + + virtual void draw(); + + public: + + Fl_Progress(int x, int y, int w, int h, const char *l = 0); + + void maximum(float v) { maximum_ = v; redraw(); } + float maximum() const { return (maximum_); } + + void minimum(float v) { minimum_ = v; redraw(); } + float minimum() const { return (minimum_); } + + void value(float v) { value_ = v; redraw(); } + float value() const { return (value_); } +}; + +#endif // !_Fl_Progress_H_ + +// +// End of "$Id: Fl_Progress.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Radio_Button.H b/Utilities/FLTK/FL/Fl_Radio_Button.H new file mode 100644 index 0000000000..888a9ac7bd --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Radio_Button.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Radio_Button.H 4288 2005-04-16 00:13:17Z mike $" +// +// Radio button header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Radio_Button_H +#define Fl_Radio_Button_H + +#include "Fl_Button.H" + +class Fl_Radio_Button : public Fl_Button { +public: + Fl_Radio_Button(int x,int y,int w,int h,const char *l=0) + : Fl_Button(x,y,w,h,l) {type(FL_RADIO_BUTTON);} +}; + +#endif + +// +// End of "$Id: Fl_Radio_Button.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Radio_Light_Button.H b/Utilities/FLTK/FL/Fl_Radio_Light_Button.H new file mode 100644 index 0000000000..0d6a3ae7eb --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Radio_Light_Button.H @@ -0,0 +1,42 @@ +// +// "$Id: Fl_Radio_Light_Button.H 4288 2005-04-16 00:13:17Z mike $" +// +// Radio light button header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +#ifndef Fl_Radio_Light_Button_H +#define Fl_Radio_Light_Button_H + +#include "Fl_Light_Button.H" + +class Fl_Radio_Light_Button : public Fl_Light_Button { +public: + Fl_Radio_Light_Button(int X,int Y,int W,int H,const char *l=0) + : Fl_Light_Button(X,Y,W,H,l) {type(FL_RADIO_BUTTON);} +}; + +#endif + +// +// End of "$Id: Fl_Radio_Light_Button.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Radio_Round_Button.H b/Utilities/FLTK/FL/Fl_Radio_Round_Button.H new file mode 100644 index 0000000000..7e525c518a --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Radio_Round_Button.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Radio_Round_Button.H 4288 2005-04-16 00:13:17Z mike $" +// +// Radio round button header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Radio_Round_Button_H +#define Fl_Radio_Round_Button_H + +#include "Fl_Round_Button.H" + +class Fl_Radio_Round_Button : public Fl_Round_Button { +public: + Fl_Radio_Round_Button(int x,int y,int w,int h,const char *l=0) + : Fl_Round_Button(x,y,w,h,l) {type(FL_RADIO_BUTTON);} +}; + +#endif + +// +// End of "$Id: Fl_Radio_Round_Button.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Repeat_Button.H b/Utilities/FLTK/FL/Fl_Repeat_Button.H new file mode 100644 index 0000000000..5e0b650756 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Repeat_Button.H @@ -0,0 +1,49 @@ +// +// "$Id: Fl_Repeat_Button.H 4288 2005-04-16 00:13:17Z mike $" +// +// Repeat button header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Repeat_Button_H +#define Fl_Repeat_Button_H +#include "Fl.H" +#include "Fl_Button.H" + +class FL_EXPORT Fl_Repeat_Button : public Fl_Button { + static void repeat_callback(void *); +public: + int handle(int); + Fl_Repeat_Button(int X,int Y,int W,int H,const char *l=0) + : Fl_Button(X,Y,W,H,l) {} + void deactivate() { + Fl::remove_timeout(repeat_callback,this); + Fl_Button::deactivate(); + } +}; + +#endif + +// +// End of "$Id: Fl_Repeat_Button.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Return_Button.H b/Utilities/FLTK/FL/Fl_Return_Button.H new file mode 100644 index 0000000000..f9cb52a078 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Return_Button.H @@ -0,0 +1,45 @@ +// +// "$Id: Fl_Return_Button.H 4288 2005-04-16 00:13:17Z mike $" +// +// Return button header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Return_Button_H +#define Fl_Return_Button_H +#include "Fl_Button.H" + +class FL_EXPORT Fl_Return_Button : public Fl_Button { +protected: + void draw(); +public: + int handle(int); + Fl_Return_Button(int X, int Y, int W, int H,const char *l=0) + : Fl_Button(X,Y,W,H,l) {} +}; + +#endif + +// +// End of "$Id: Fl_Return_Button.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Roller.H b/Utilities/FLTK/FL/Fl_Roller.H new file mode 100644 index 0000000000..064b150680 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Roller.H @@ -0,0 +1,47 @@ +// +// "$Id: Fl_Roller.H 4288 2005-04-16 00:13:17Z mike $" +// +// Roller header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Roller_H +#define Fl_Roller_H + +#ifndef Fl_Valuator_H +#include "Fl_Valuator.H" +#endif + +class FL_EXPORT Fl_Roller : public Fl_Valuator { +protected: + void draw(); +public: + int handle(int); + Fl_Roller(int X,int Y,int W,int H,const char* L=0); +}; + +#endif + +// +// End of "$Id: Fl_Roller.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Round_Button.H b/Utilities/FLTK/FL/Fl_Round_Button.H new file mode 100644 index 0000000000..c47e92cd12 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Round_Button.H @@ -0,0 +1,42 @@ +// +// "$Id: Fl_Round_Button.H 4288 2005-04-16 00:13:17Z mike $" +// +// Round button header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Round_Button_H +#define Fl_Round_Button_H + +#include "Fl_Light_Button.H" + +class FL_EXPORT Fl_Round_Button : public Fl_Light_Button { +public: + Fl_Round_Button(int x,int y,int w,int h,const char *l = 0); +}; + +#endif + +// +// End of "$Id: Fl_Round_Button.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Round_Clock.H b/Utilities/FLTK/FL/Fl_Round_Clock.H new file mode 100644 index 0000000000..d3b9fb0913 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Round_Clock.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Round_Clock.H 4288 2005-04-16 00:13:17Z mike $" +// +// Round clock header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Round_Clock_H +#define Fl_Round_Clock_H + +#include "Fl_Clock.H" + +class Fl_Round_Clock : public Fl_Clock { +public: + Fl_Round_Clock(int x,int y,int w,int h, const char *l = 0) + : Fl_Clock(x,y,w,h,l) {type(FL_ROUND_CLOCK); box(FL_NO_BOX);} +}; + +#endif + +// +// End of "$Id: Fl_Round_Clock.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Scroll.H b/Utilities/FLTK/FL/Fl_Scroll.H new file mode 100644 index 0000000000..0bc3a5bb15 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Scroll.H @@ -0,0 +1,79 @@ +// +// "$Id: Fl_Scroll.H 4288 2005-04-16 00:13:17Z mike $" +// +// Scroll header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Scroll_H +#define Fl_Scroll_H + +#include "Fl_Group.H" +#include "Fl_Scrollbar.H" + +class FL_EXPORT Fl_Scroll : public Fl_Group { + + int xposition_, yposition_; + int width_, height_; + int oldx, oldy; + static void hscrollbar_cb(Fl_Widget*, void*); + static void scrollbar_cb(Fl_Widget*, void*); + void fix_scrollbar_order(); + static void draw_clip(void*,int,int,int,int); + void bbox(int&,int&,int&,int&); + +protected: + + void draw(); + +public: + + Fl_Scrollbar scrollbar; + Fl_Scrollbar hscrollbar; + + void resize(int,int,int,int); + int handle(int); + + Fl_Scroll(int X,int Y,int W,int H,const char*l=0); + + enum { // values for type() + HORIZONTAL = 1, + VERTICAL = 2, + BOTH = 3, + ALWAYS_ON = 4, + HORIZONTAL_ALWAYS = 5, + VERTICAL_ALWAYS = 6, + BOTH_ALWAYS = 7 + }; + + int xposition() const {return xposition_;} + int yposition() const {return yposition_;} + void position(int, int); + void clear(); +}; + +#endif + +// +// End of "$Id: Fl_Scroll.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Scrollbar.H b/Utilities/FLTK/FL/Fl_Scrollbar.H new file mode 100644 index 0000000000..93c75b8503 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Scrollbar.H @@ -0,0 +1,60 @@ +// +// "$Id: Fl_Scrollbar.H 4288 2005-04-16 00:13:17Z mike $" +// +// Scroll bar header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Scrollbar_H +#define Fl_Scrollbar_H + +#include "Fl_Slider.H" + +class FL_EXPORT Fl_Scrollbar : public Fl_Slider { + + int linesize_; + int pushed_; + static void timeout_cb(void*); + void increment_cb(); +protected: + void draw(); + +public: + + Fl_Scrollbar(int x,int y,int w,int h, const char *l = 0); + int handle(int); + + int value() {return int(Fl_Slider::value());} + int value(int p, int s, int top, int total) { + return scrollvalue(p, s, top, total); + } + int linesize() const {return linesize_;} + void linesize(int i) {linesize_ = i;} + +}; + +#endif + +// +// End of "$Id: Fl_Scrollbar.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Secret_Input.H b/Utilities/FLTK/FL/Fl_Secret_Input.H new file mode 100644 index 0000000000..a87bef59db --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Secret_Input.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Secret_Input.H 4288 2005-04-16 00:13:17Z mike $" +// +// Secret input header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Secret_Input_H +#define Fl_Secret_Input_H + +#include "Fl_Input.H" + +class Fl_Secret_Input : public Fl_Input { +public: + Fl_Secret_Input(int X,int Y,int W,int H,const char *l = 0) + : Fl_Input(X,Y,W,H,l) {type(FL_SECRET_INPUT);} +}; + +#endif + +// +// End of "$Id: Fl_Secret_Input.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Select_Browser.H b/Utilities/FLTK/FL/Fl_Select_Browser.H new file mode 100644 index 0000000000..4a8ef92105 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Select_Browser.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Select_Browser.H 4288 2005-04-16 00:13:17Z mike $" +// +// Select browser header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Select_Browser_H +#define Fl_Select_Browser_H + +#include "Fl_Browser.H" + +class Fl_Select_Browser : public Fl_Browser { +public: + Fl_Select_Browser(int X,int Y,int W,int H,const char *l=0) + : Fl_Browser(X,Y,W,H,l) {type(FL_SELECT_BROWSER);} +}; + +#endif + +// +// End of "$Id: Fl_Select_Browser.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Shared_Image.H b/Utilities/FLTK/FL/Fl_Shared_Image.H new file mode 100644 index 0000000000..042b7827d1 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Shared_Image.H @@ -0,0 +1,99 @@ +// +// "$Id: Fl_Shared_Image.H 4288 2005-04-16 00:13:17Z mike $" +// +// Shared image header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Shared_Image_H +# define Fl_Shared_Image_H + +# include "Fl_Image.H" + + +// Test function for adding new formats +typedef Fl_Image *(*Fl_Shared_Handler)(const char *name, uchar *header, + int headerlen); + +// Shared images class. +class FL_EXPORT Fl_Shared_Image : public Fl_Image { + protected: + + static Fl_Shared_Image **images_; // Shared images + static int num_images_; // Number of shared images + static int alloc_images_; // Allocated shared images + static Fl_Shared_Handler *handlers_; // Additional format handlers + static int num_handlers_; // Number of format handlers + static int alloc_handlers_; // Allocated format handlers + + const char *name_; // Name of image file + int original_; // Original image? + int refcount_; // Number of times this image has been used + Fl_Image *image_; // The image that is shared + int alloc_image_; // Was the image allocated? + + static int compare(Fl_Shared_Image **i0, Fl_Shared_Image **i1); + + // Use get() and release() to load/delete images in memory... + Fl_Shared_Image(); + Fl_Shared_Image(const char *n, Fl_Image *img = 0); + virtual ~Fl_Shared_Image(); + void add(); + void update(); + + public: + + const char *name() { return name_; } + int refcount() { return refcount_; } + void release(); + void reload(); + + virtual Fl_Image *copy(int W, int H); + Fl_Image *copy() { return copy(w(), h()); } + virtual void color_average(Fl_Color c, float i); + virtual void desaturate(); + virtual void draw(int X, int Y, int W, int H, int cx, int cy); + void draw(int X, int Y) { draw(X, Y, w(), h(), 0, 0); } + virtual void uncache(); + + static Fl_Shared_Image *find(const char *n, int W = 0, int H = 0); + static Fl_Shared_Image *get(const char *n, int W = 0, int H = 0); + static Fl_Shared_Image **images(); + static int num_images(); + static void add_handler(Fl_Shared_Handler f); + static void remove_handler(Fl_Shared_Handler f); +}; + +// +// The following function is provided in the fltk_images library and +// registers all of the "extra" image file formats that are not part +// of the core FLTK library... +// + +FL_EXPORT extern void fl_register_images(); + +#endif // !Fl_Shared_Image_H + +// +// End of "$Id: Fl_Shared_Image.H 4288 2005-04-16 00:13:17Z mike $" +// diff --git a/Utilities/FLTK/FL/Fl_Simple_Counter.H b/Utilities/FLTK/FL/Fl_Simple_Counter.H new file mode 100644 index 0000000000..84e07c9b5a --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Simple_Counter.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Simple_Counter.H 4288 2005-04-16 00:13:17Z mike $" +// +// Simple counter header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Simple_Counter_H +#define Fl_Simple_Counter_H + +#include "Fl_Counter.H" + +class Fl_Simple_Counter : public Fl_Counter { +public: + Fl_Simple_Counter(int x,int y,int w,int h, const char *l = 0) + : Fl_Counter(x,y,w,h,l) {type(FL_SIMPLE_COUNTER);} +}; + +#endif + +// +// End of "$Id: Fl_Simple_Counter.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Single_Window.H b/Utilities/FLTK/FL/Fl_Single_Window.H new file mode 100644 index 0000000000..c68e66e32c --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Single_Window.H @@ -0,0 +1,49 @@ +// +// "$Id: Fl_Single_Window.H 4288 2005-04-16 00:13:17Z mike $" +// +// Single-buffered window header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Single_Window_H +#define Fl_Single_Window_H + +#include "Fl_Window.H" + +class FL_EXPORT Fl_Single_Window : public Fl_Window { +public: + void show(); + void show(int a, char **b) {Fl_Window::show(a,b);} + void flush(); + Fl_Single_Window(int W, int H, const char *l=0) + : Fl_Window(W,H,l) {} + Fl_Single_Window(int X, int Y, int W, int H, const char *l=0) + : Fl_Window(X,Y,W,H,l) {} + int make_current(); +}; + +#endif + +// +// End of "$Id: Fl_Single_Window.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Slider.H b/Utilities/FLTK/FL/Fl_Slider.H new file mode 100644 index 0000000000..8a6b93d602 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Slider.H @@ -0,0 +1,75 @@ +// +// "$Id: Fl_Slider.H 4288 2005-04-16 00:13:17Z mike $" +// +// Slider header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Slider_H +#define Fl_Slider_H + +#ifndef Fl_Valuator_H +#include "Fl_Valuator.H" +#endif + +// values for type(), lowest bit indicate horizontal: +#define FL_VERT_SLIDER 0 +#define FL_HOR_SLIDER 1 +#define FL_VERT_FILL_SLIDER 2 +#define FL_HOR_FILL_SLIDER 3 +#define FL_VERT_NICE_SLIDER 4 +#define FL_HOR_NICE_SLIDER 5 + +class FL_EXPORT Fl_Slider : public Fl_Valuator { + + float slider_size_; + uchar slider_; + void _Fl_Slider(); + void draw_bg(int, int, int, int); + +protected: + + // these allow subclasses to put the slider in a smaller area: + void draw(int, int, int, int); + int handle(int, int, int, int, int); + +public: + + void draw(); + int handle(int); + Fl_Slider(int x,int y,int w,int h, const char *l = 0); + Fl_Slider(uchar t,int x,int y,int w,int h, const char *l); + + int scrollvalue(int windowtop,int windowsize,int first,int totalsize); + void bounds(double a, double b); + float slider_size() const {return slider_size_;} + void slider_size(double v); + Fl_Boxtype slider() const {return (Fl_Boxtype)slider_;} + void slider(Fl_Boxtype c) {slider_ = c;} +}; + +#endif + +// +// End of "$Id: Fl_Slider.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Spinner.H b/Utilities/FLTK/FL/Fl_Spinner.H new file mode 100644 index 0000000000..35a9badfbf --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Spinner.H @@ -0,0 +1,171 @@ +// +// "$Id$" +// +// Spinner widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Spinner_H +# define Fl_Spinner_H + +// +// Include necessary headers... +// + +# include <FL/Fl_Group.H> +# include <FL/Fl_Input.H> +# include <FL/Fl_Repeat_Button.H> +# include <stdio.h> +# include <stdlib.h> + + +// +// Fl_Spinner widget class... +// + +class Fl_Spinner : public Fl_Group +{ + double value_; // Current value + double minimum_; // Minimum value + double maximum_; // Maximum value + double step_; // Amount to add/subtract for up/down + const char *format_; // Format string + + Fl_Input input_; // Input field for the value + Fl_Repeat_Button + up_button_, // Up button + down_button_; // Down button + + static void sb_cb(Fl_Widget *w, Fl_Spinner *sb) { + double v; // New value + + if (w == &(sb->input_)) { + // Something changed in the input field... + v = atof(sb->input_.value()); + + if (v < sb->minimum_) { + sb->value_ = sb->minimum_; + sb->update(); + } else if (v > sb->maximum_) { + sb->value_ = sb->maximum_; + sb->update(); + } else sb->value_ = v; + } else if (w == &(sb->up_button_)) { + // Up button pressed... + v = sb->value_ + sb->step_; + + if (v > sb->maximum_) sb->value_ = sb->minimum_; + else sb->value_ = v; + + sb->update(); + } else if (w == &(sb->down_button_)) { + // Down button pressed... + v = sb->value_ - sb->step_; + + if (v < sb->minimum_) sb->value_ = sb->maximum_; + else sb->value_ = v; + + sb->update(); + } + + sb->do_callback(); + } + void update() { + char s[255]; // Value string + + sprintf(s, format_, value_); + input_.value(s); + } + + public: + + Fl_Spinner(int X, int Y, int W, int H, const char *L = 0) + : Fl_Group(X, Y, W, H, L), + input_(X, Y, W - H / 2 - 2, H), + up_button_(X + W - H / 2 - 2, Y, H / 2 + 2, H / 2, "@-22<"), + down_button_(X + W - H / 2 - 2, Y + H - H / 2, + H / 2 + 2, H / 2, "@-22>") { + end(); + + value_ = 1.0; + minimum_ = 1.0; + maximum_ = 100.0; + step_ = 1.0; + format_ = "%.0f"; + + align(FL_ALIGN_LEFT); + + input_.value("1"); + input_.type(FL_INT_INPUT); + input_.when(FL_WHEN_CHANGED); + input_.callback((Fl_Callback *)sb_cb, this); + + up_button_.callback((Fl_Callback *)sb_cb, this); + + down_button_.callback((Fl_Callback *)sb_cb, this); + } + + const char *format() { return (format_); } + void format(const char *f) { format_ = f; update(); } + double maxinum() const { return (maximum_); } + void maximum(double m) { maximum_ = m; } + double mininum() const { return (minimum_); } + void minimum(double m) { minimum_ = m; } + void range(double a, double b) { minimum_ = a; maximum_ = b; } + void resize(int X, int Y, int W, int H) { + Fl_Group::resize(X,Y,W,H); + + input_.resize(X, Y, W - H / 2 - 2, H); + up_button_.resize(X + W - H / 2 - 2, Y, H / 2 + 2, H / 2); + down_button_.resize(X + W - H / 2 - 2, Y + H - H / 2, + H / 2 + 2, H / 2); + } + double step() const { return (step_); } + void step(double s) { step_ = s; } + Fl_Color textcolor() const { + return (input_.textcolor()); + } + void textcolor(Fl_Color c) { + input_.textcolor(c); + } + uchar textfont() const { + return (input_.textfont()); + } + void textfont(uchar f) { + input_.textfont(f); + } + uchar textsize() const { + return (input_.textsize()); + } + void textsize(uchar s) { + input_.textsize(s); + } + double value() const { return (value_); } + void value(double v) { value_ = v; update(); } +}; + +#endif // !Fl_Spinner_H + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/FL/Fl_Sys_Menu_Bar.H b/Utilities/FLTK/FL/Fl_Sys_Menu_Bar.H new file mode 100644 index 0000000000..01f4b60c99 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Sys_Menu_Bar.H @@ -0,0 +1,56 @@ +// +// "$Id: Fl_Sys_Menu_Bar.H 4546 2005-08-29 20:05:38Z matt $" +// +// MacOS system menu bar header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Sys_Menu_Bar_H +#define Fl_Sys_Menu_Bar_H + +#include "Fl_Menu_Bar.H" + +#ifdef __APPLE__ + +class FL_EXPORT Fl_Sys_Menu_Bar : public Fl_Menu_Bar { +protected: + void draw(); +public: + Fl_Sys_Menu_Bar(int x,int y,int w,int h,const char *l=0) + : Fl_Menu_Bar(x,y,w,h,l) { + deactivate(); // don't let the old area take events + } + void menu(const Fl_Menu_Item *m); +}; + +#else + +typedef Fl_Menu_Bar Fl_Sys_Menu_Bar; + +#endif + +#endif + +// +// End of "$Id: Fl_Sys_Menu_Bar.H 4546 2005-08-29 20:05:38Z matt $". +// diff --git a/Utilities/FLTK/FL/Fl_Tabs.H b/Utilities/FLTK/FL/Fl_Tabs.H new file mode 100644 index 0000000000..3145f20c00 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Tabs.H @@ -0,0 +1,56 @@ +// +// "$Id: Fl_Tabs.H 4288 2005-04-16 00:13:17Z mike $" +// +// Tab header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Tabs_H +#define Fl_Tabs_H + +#include "Fl_Group.H" + +class FL_EXPORT Fl_Tabs : public Fl_Group { + Fl_Widget *value_; + Fl_Widget *push_; + int tab_positions(int*, int*); + int tab_height(); + void draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int sel=0); +protected: + void draw(); + +public: + int handle(int); + Fl_Widget *value(); + int value(Fl_Widget *); + Fl_Widget *push() const {return push_;} + int push(Fl_Widget *); + Fl_Tabs(int,int,int,int,const char * = 0); + Fl_Widget *which(int event_x, int event_y); +}; + +#endif + +// +// End of "$Id: Fl_Tabs.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Text_Buffer.H b/Utilities/FLTK/FL/Fl_Text_Buffer.H new file mode 100644 index 0000000000..d2b91f39d8 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Text_Buffer.H @@ -0,0 +1,259 @@ +// +// "$Id: Fl_Text_Buffer.H 4288 2005-04-16 00:13:17Z mike $" +// +// Header file for Fl_Text_Buffer class. +// +// Copyright 2001-2005 by Bill Spitzak and others. +// Original code Copyright Mark Edel. Permission to distribute under +// the LGPL for the FLTK library granted by Mark Edel. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef FL_TEXT_BUFFER_H +#define FL_TEXT_BUFFER_H + +/* Maximum length in characters of a tab or control character expansion + of a single buffer character */ +#define FL_TEXT_MAX_EXP_CHAR_LEN 20 + +#include "Fl_Export.H" + +class FL_EXPORT Fl_Text_Selection { + friend class Fl_Text_Buffer; + + public: + void set(int start, int end); + void set_rectangular(int start, int end, int rectStart, int rectEnd); + void update(int pos, int nDeleted, int nInserted); + char rectangular() { return mRectangular; } + int start() { return mStart; } + int end() { return mEnd; } + int rect_start() { return mRectStart; } + int rect_end() { return mRectEnd; } + char selected() { return mSelected; } + void selected(char b) { mSelected = b; } + int includes(int pos, int lineStartPos, int dispIndex); + int position(int* start, int* end); + int position(int* start, int* end, int* isRect, int* rectStart, int* rectEnd); + + + protected: + char mSelected; + char mRectangular; + int mStart; + int mEnd; + int mRectStart; + int mRectEnd; +}; + +typedef void (*Fl_Text_Modify_Cb)(int pos, int nInserted, int nDeleted, + int nRestyled, const char* deletedText, + void* cbArg); +typedef void (*Fl_Text_Predelete_Cb)(int pos, int nDeleted, void* cbArg); + +class FL_EXPORT Fl_Text_Buffer { + public: + Fl_Text_Buffer(int requestedSize = 0); + ~Fl_Text_Buffer(); + + int length() { return mLength; } + char* text(); + void text(const char* text); + char* text_range(int start, int end); + char character(int pos); + char* text_in_rectangle(int start, int end, int rectStart, int rectEnd); + void insert(int pos, const char* text); + void append(const char* t) { insert(length(), t); } + void remove(int start, int end); + void replace(int start, int end, const char *text); + void copy(Fl_Text_Buffer* fromBuf, int fromStart, int fromEnd, int toPos); + int undo(int *cp=0); + void canUndo(char flag=1); + int insertfile(const char *file, int pos, int buflen = 128*1024); + int appendfile(const char *file, int buflen = 128*1024) + { return insertfile(file, length(), buflen); } + int loadfile(const char *file, int buflen = 128*1024) + { select(0, length()); remove_selection(); return appendfile(file, buflen); } + int outputfile(const char *file, int start, int end, int buflen = 128*1024); + int savefile(const char *file, int buflen = 128*1024) + { return outputfile(file, 0, length(), buflen); } + + void insert_column(int column, int startPos, const char* text, + int* charsInserted, int* charsDeleted); + + void replace_rectangular(int start, int end, int rectStart, int rectEnd, + const char* text); + + void overlay_rectangular(int startPos, int rectStart, int rectEnd, + const char* text, int* charsInserted, + int* charsDeleted); + + void remove_rectangular(int start, int end, int rectStart, int rectEnd); + void clear_rectangular(int start, int end, int rectStart, int rectEnd); + int tab_distance() { return mTabDist; } + void tab_distance(int tabDist); + void select(int start, int end); + int selected() { return mPrimary.selected(); } + void unselect(); + void select_rectangular(int start, int end, int rectStart, int rectEnd); + int selection_position(int* start, int* end); + + int selection_position(int* start, int* end, int* isRect, int* rectStart, + int* rectEnd); + + char* selection_text(); + void remove_selection(); + void replace_selection(const char* text); + void secondary_select(int start, int end); + void secondary_unselect(); + + void secondary_select_rectangular(int start, int end, int rectStart, + int rectEnd); + + int secondary_selection_position(int* start, int* end, int* isRect, + int* rectStart, int* rectEnd); + + char* secondary_selection_text(); + void remove_secondary_selection(); + void replace_secondary_selection(const char* text); + void highlight(int start, int end); + void unhighlight(); + void highlight_rectangular(int start, int end, int rectStart, int rectEnd); + + int highlight_position(int* start, int* end, int* isRect, int* rectStart, + int* rectEnd); + + char* highlight_text(); + void add_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void* cbArg); + void remove_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void* cbArg); + + void call_modify_callbacks() { call_modify_callbacks(0, 0, 0, 0, 0); } + + void add_predelete_callback(Fl_Text_Predelete_Cb bufPredelCB, void* cbArg); + void remove_predelete_callback(Fl_Text_Predelete_Cb predelCB, void* cbArg); + + void call_predelete_callbacks() { call_predelete_callbacks(0, 0); } + + char* line_text(int pos); + int line_start(int pos); + int line_end(int pos); + int word_start(int pos); + int word_end(int pos); + int expand_character(int pos, int indent, char *outStr); + + static int expand_character(char c, int indent, char* outStr, int tabDist, + char nullSubsChar); + + static int character_width(char c, int indent, int tabDist, char nullSubsChar); + int count_displayed_characters(int lineStartPos, int targetPos); + int skip_displayed_characters(int lineStartPos, int nChars); + int count_lines(int startPos, int endPos); + int skip_lines(int startPos, int nLines); + int rewind_lines(int startPos, int nLines); + int findchar_forward(int startPos, char searchChar, int* foundPos); + int findchar_backward(int startPos, char searchChar, int* foundPos); + int findchars_forward(int startPos, const char* searchChars, int* foundPos); + int findchars_backward(int startPos, const char* searchChars, int* foundPos); + + int search_forward(int startPos, const char* searchString, int* foundPos, + int matchCase = 0); + + int search_backward(int startPos, const char* searchString, int* foundPos, + int matchCase = 0); + + int substitute_null_characters(char* string, int length); + void unsubstitute_null_characters(char* string); + char null_substitution_character() { return mNullSubsChar; } + Fl_Text_Selection* primary_selection() { return &mPrimary; } + Fl_Text_Selection* secondary_selection() { return &mSecondary; } + Fl_Text_Selection* highlight_selection() { return &mHighlight; } + + protected: + void call_modify_callbacks(int pos, int nDeleted, int nInserted, + int nRestyled, const char* deletedText); + void call_predelete_callbacks(int pos, int nDeleted); + + int insert_(int pos, const char* text); + void remove_(int start, int end); + + void remove_rectangular_(int start, int end, int rectStart, int rectEnd, + int* replaceLen, int* endPos); + + void insert_column_(int column, int startPos, const char* insText, + int* nDeleted, int* nInserted, int* endPos); + + void overlay_rectangular_(int startPos, int rectStart, int rectEnd, + const char* insText, int* nDeleted, + int* nInserted, int* endPos); + + void redisplay_selection(Fl_Text_Selection* oldSelection, + Fl_Text_Selection* newSelection); + + void move_gap(int pos); + void reallocate_with_gap(int newGapStart, int newGapLen); + char* selection_text_(Fl_Text_Selection* sel); + void remove_selection_(Fl_Text_Selection* sel); + void replace_selection_(Fl_Text_Selection* sel, const char* text); + + void rectangular_selection_boundaries(int lineStartPos, int rectStart, + int rectEnd, int* selStart, + int* selEnd); + + void update_selections(int pos, int nDeleted, int nInserted); + + Fl_Text_Selection mPrimary; /* highlighted areas */ + Fl_Text_Selection mSecondary; + Fl_Text_Selection mHighlight; + int mLength; /* length of the text in the buffer (the length + of the buffer itself must be calculated: + gapEnd - gapStart + length) */ + char* mBuf; /* allocated memory where the text is stored */ + int mGapStart; /* points to the first character of the gap */ + int mGapEnd; /* points to the first char after the gap */ + // The hardware tab distance used by all displays for this buffer, + // and used in computing offsets for rectangular selection operations. + int mTabDist; /* equiv. number of characters in a tab */ + int mUseTabs; /* True if buffer routines are allowed to use + tabs for padding in rectangular operations */ + int mNModifyProcs; /* number of modify-redisplay procs attached */ + Fl_Text_Modify_Cb* /* procedures to call when buffer is */ + mNodifyProcs; /* modified to redisplay contents */ + void** mCbArgs; /* caller arguments for modifyProcs above */ + int mNPredeleteProcs; /* number of pre-delete procs attached */ + Fl_Text_Predelete_Cb* /* procedure to call before text is deleted */ + mPredeleteProcs; /* from the buffer; at most one is supported. */ + void **mPredeleteCbArgs; /* caller argument for pre-delete proc above */ + int mCursorPosHint; /* hint for reasonable cursor position after + a buffer modification operation */ + char mNullSubsChar; /* NEdit is based on C null-terminated strings, + so ascii-nul characters must be substituted + with something else. This is the else, but + of course, things get quite messy when you + use it */ + char mCanUndo; /* if this buffer is used for attributes, it must + not do any undo calls */ +}; + +#endif + +// +// End of "$Id: Fl_Text_Buffer.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Text_Display.H b/Utilities/FLTK/FL/Fl_Text_Display.H new file mode 100644 index 0000000000..e7ef14d3f3 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Text_Display.H @@ -0,0 +1,298 @@ +// +// "$Id: Fl_Text_Display.H 4502 2005-08-10 23:11:51Z matt $" +// +// Header file for Fl_Text_Display class. +// +// Copyright 2001-2005 by Bill Spitzak and others. +// Original code Copyright Mark Edel. Permission to distribute under +// the LGPL for the FLTK library granted by Mark Edel. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef FL_TEXT_DISPLAY_H +#define FL_TEXT_DISPLAY_H + +#include "fl_draw.H" +#include "Fl_Group.H" +#include "Fl_Widget.H" +#include "Fl_Scrollbar.H" +#include "Fl_Text_Buffer.H" + +class FL_EXPORT Fl_Text_Display: public Fl_Group { + public: + enum { + NORMAL_CURSOR, CARET_CURSOR, DIM_CURSOR, + BLOCK_CURSOR, HEAVY_CURSOR + }; + + enum { + CURSOR_POS, CHARACTER_POS + }; + + // drag types- they match Fl::event_clicks() so that single clicking to + // start a collection selects by character, double clicking selects by + // word and triple clicking selects by line. + enum { + DRAG_CHAR = 0, DRAG_WORD = 1, DRAG_LINE = 2 + }; + friend void fl_text_drag_me(int pos, Fl_Text_Display* d); + + typedef void (*Unfinished_Style_Cb)(int, void *); + + // style attributes - currently not implemented! + enum { + ATTR_NONE = 0, + ATTR_UNDERLINE = 1, + ATTR_HIDDEN = 2 + }; + + struct Style_Table_Entry { + Fl_Color color; + Fl_Font font; + int size; + unsigned attr; + }; + + Fl_Text_Display(int X, int Y, int W, int H, const char *l = 0); + ~Fl_Text_Display(); + + virtual int handle(int e); + void buffer(Fl_Text_Buffer* buf); + void buffer(Fl_Text_Buffer& buf) { buffer(&buf); } + Fl_Text_Buffer* buffer() { return mBuffer; } + void redisplay_range(int start, int end); + void scroll(int topLineNum, int horizOffset); + void insert(const char* text); + void overstrike(const char* text); + void insert_position(int newPos); + int insert_position() { return mCursorPos; } + int in_selection(int x, int y); + void show_insert_position(); + int move_right(); + int move_left(); + int move_up(); + int move_down(); + int count_lines(int start, int end, bool start_pos_is_line_start); + int line_start(int pos); + int line_end(int pos, bool start_pos_is_line_start); + int skip_lines(int startPos, int nLines, bool startPosIsLineStart); + int rewind_lines(int startPos, int nLines); + void next_word(void); + void previous_word(void); + void show_cursor(int b = 1); + void hide_cursor() { show_cursor(0); } + void cursor_style(int style); + Fl_Color cursor_color() const {return mCursor_color;} + void cursor_color(Fl_Color n) {mCursor_color = n;} + int scrollbar_width() { return scrollbar_width_; } + Fl_Align scrollbar_align() { return scrollbar_align_; } + void scrollbar_width(int W) { scrollbar_width_ = W; } + void scrollbar_align(Fl_Align a) { scrollbar_align_ = a; } + int word_start(int pos) { return buffer()->word_start(pos); } + int word_end(int pos) { return buffer()->word_end(pos); } + + + void highlight_data(Fl_Text_Buffer *styleBuffer, + const Style_Table_Entry *styleTable, + int nStyles, char unfinishedStyle, + Unfinished_Style_Cb unfinishedHighlightCB, + void *cbArg); + + int position_style(int lineStartPos, int lineLen, int lineIndex, + int dispIndex); + + Fl_Font textfont() const {return (Fl_Font)textfont_;} + void textfont(uchar s) {textfont_ = s;} + uchar textsize() const {return textsize_;} + void textsize(uchar s) {textsize_ = s;} + Fl_Color textcolor() const {return (Fl_Color)textcolor_;} + void textcolor(unsigned n) {textcolor_ = n;} + + int wrapped_column(int row, int column); + int wrapped_row(int row); + void wrap_mode(int wrap, int wrap_margin); + + virtual void resize(int X, int Y, int W, int H); + + protected: + // Most (all?) of this stuff should only be called from resize() or + // draw(). + // Anything with "vline" indicates thats it deals with currently + // visible lines. + + virtual void draw(); + void draw_text(int X, int Y, int W, int H); + void draw_range(int start, int end); + void draw_cursor(int, int); + + void draw_string(int style, int x, int y, int toX, const char *string, + int nChars); + + void draw_vline(int visLineNum, int leftClip, int rightClip, + int leftCharIndex, int rightCharIndex); + + void draw_line_numbers(bool clearAll); + + void clear_rect(int style, int x, int y, int width, int height); + void display_insert(); + + void offset_line_starts(int newTopLineNum); + + void calc_line_starts(int startLine, int endLine); + + void update_line_starts(int pos, int charsInserted, int charsDeleted, + int linesInserted, int linesDeleted, int *scrolled); + + void calc_last_char(); + + int position_to_line( int pos, int* lineNum ); + int string_width(const char* string, int length, int style); + + static void scroll_timer_cb(void*); + + static void buffer_predelete_cb(int pos, int nDeleted, void* cbArg); + static void buffer_modified_cb(int pos, int nInserted, int nDeleted, + int nRestyled, const char* deletedText, + void* cbArg); + + static void h_scrollbar_cb(Fl_Scrollbar* w, Fl_Text_Display* d); + static void v_scrollbar_cb( Fl_Scrollbar* w, Fl_Text_Display* d); + void update_v_scrollbar(); + void update_h_scrollbar(); + int measure_vline(int visLineNum); + int longest_vline(); + int empty_vlines(); + int vline_length(int visLineNum); + int xy_to_position(int x, int y, int PosType = CHARACTER_POS); + + void xy_to_rowcol(int x, int y, int* row, int* column, + int PosType = CHARACTER_POS); + + int position_to_xy(int pos, int* x, int* y); + void maintain_absolute_top_line_number(int state); + int get_absolute_top_line_number(); + void absolute_top_line_number(int oldFirstChar); + int maintaining_absolute_top_line_number(); + void reset_absolute_top_line_number(); + int position_to_linecol(int pos, int* lineNum, int* column); + void scroll_(int topLineNum, int horizOffset); + + void extend_range_for_styles(int* start, int* end); + + void find_wrap_range(const char *deletedText, int pos, int nInserted, + int nDeleted, int *modRangeStart, int *modRangeEnd, + int *linesInserted, int *linesDeleted); + void measure_deleted_lines(int pos, int nDeleted); + void wrapped_line_counter(Fl_Text_Buffer *buf, int startPos, int maxPos, + int maxLines, bool startPosIsLineStart, + int styleBufOffset, int *retPos, int *retLines, + int *retLineStart, int *retLineEnd, + bool countLastLineMissingNewLine = true); + void find_line_end(int pos, bool start_pos_is_line_start, int *lineEnd, + int *nextLineStart); + int measure_proportional_character(char c, int colNum, int pos); + int wrap_uses_character(int lineEndPos); + int range_touches_selection(Fl_Text_Selection *sel, int rangeStart, + int rangeEnd); + + int damage_range1_start, damage_range1_end; + int damage_range2_start, damage_range2_end; + int mCursorPos; + int mCursorOn; + int mCursorOldY; /* Y pos. of cursor for blanking */ + int mCursorToHint; /* Tells the buffer modified callback + where to move the cursor, to reduce + the number of redraw calls */ + int mCursorStyle; /* One of enum cursorStyles above */ + int mCursorPreferredCol; /* Column for vert. cursor movement */ + int mNVisibleLines; /* # of visible (displayed) lines */ + int mNBufferLines; /* # of newlines in the buffer */ + Fl_Text_Buffer* mBuffer; /* Contains text to be displayed */ + Fl_Text_Buffer* mStyleBuffer; /* Optional parallel buffer containing + color and font information */ + int mFirstChar, mLastChar; /* Buffer positions of first and last + displayed character (lastChar points + either to a newline or one character + beyond the end of the buffer) */ + int mContinuousWrap; /* Wrap long lines when displaying */ + int mWrapMargin; /* Margin in # of char positions for + wrapping in continuousWrap mode */ + int* mLineStarts; + int mTopLineNum; /* Line number of top displayed line + of file (first line of file is 1) */ + int mAbsTopLineNum; /* In continuous wrap mode, the line + number of the top line if the text + were not wrapped (note that this is + only maintained as needed). */ + int mNeedAbsTopLineNum; /* Externally settable flag to continue + maintaining absTopLineNum even if + it isn't needed for line # display */ + int mHorizOffset; /* Horizontal scroll pos. in pixels */ + int mTopLineNumHint; /* Line number of top displayed line + of file (first line of file is 1) */ + int mHorizOffsetHint; /* Horizontal scroll pos. in pixels */ + int mNStyles; /* Number of entries in styleTable */ + const Style_Table_Entry *mStyleTable; /* Table of fonts and colors for + coloring/syntax-highlighting */ + char mUnfinishedStyle; /* Style buffer entry which triggers + on-the-fly reparsing of region */ + Unfinished_Style_Cb mUnfinishedHighlightCB; /* Callback to parse "unfinished" */ + /* regions */ + void* mHighlightCBArg; /* Arg to unfinishedHighlightCB */ + + int mMaxsize; + + int mFixedFontWidth; /* Font width if all current fonts are + fixed and match in width, else -1 */ + int mSuppressResync; /* Suppress resynchronization of line + starts during buffer updates */ + int mNLinesDeleted; /* Number of lines deleted during + buffer modification (only used + when resynchronization is suppressed) */ + int mModifyingTabDistance; /* Whether tab distance is being + modified */ + + Fl_Color mCursor_color; + + Fl_Scrollbar* mHScrollBar; + Fl_Scrollbar* mVScrollBar; + int scrollbar_width_; + Fl_Align scrollbar_align_; + int dragPos, dragType, dragging; + int display_insert_position_hint; + struct { int x, y, w, h; } text_area; + + uchar textfont_; + uchar textsize_; + unsigned textcolor_; + + // The following are not presently used from the original NEdit code, + // but are being put here so that future versions of Fl_Text_Display + // can implement line numbers without breaking binary compatibility. + int mLineNumLeft, mLineNumWidth; + /* Line number margin and width */ +}; + +#endif + +// +// End of "$Id: Fl_Text_Display.H 4502 2005-08-10 23:11:51Z matt $". +// diff --git a/Utilities/FLTK/FL/Fl_Text_Editor.H b/Utilities/FLTK/FL/Fl_Text_Editor.H new file mode 100644 index 0000000000..81782f1208 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Text_Editor.H @@ -0,0 +1,110 @@ +// +// "$Id: Fl_Text_Editor.H 4288 2005-04-16 00:13:17Z mike $" +// +// Header file for Fl_Text_Editor class. +// +// Copyright 2001-2005 by Bill Spitzak and others. +// Original code Copyright Mark Edel. Permission to distribute under +// the LGPL for the FLTK library granted by Mark Edel. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + + +#ifndef FL_TEXT_EDITOR_H +#define FL_TEXT_EDITOR_H + +#include "Fl_Text_Display.H" + +// key will match in any state +#define FL_TEXT_EDITOR_ANY_STATE (-1L) + +class FL_EXPORT Fl_Text_Editor : public Fl_Text_Display { + public: + typedef int (*Key_Func)(int key, Fl_Text_Editor* editor); + + struct Key_Binding { + int key; + int state; + Key_Func function; + Key_Binding* next; + }; + + Fl_Text_Editor(int X, int Y, int W, int H, const char* l = 0); + ~Fl_Text_Editor() { remove_all_key_bindings(); } + virtual int handle(int e); + void insert_mode(int b) { insert_mode_ = b; } + int insert_mode() { return insert_mode_; } + + void add_key_binding(int key, int state, Key_Func f, Key_Binding** list); + void add_key_binding(int key, int state, Key_Func f) + { add_key_binding(key, state, f, &key_bindings); } + void remove_key_binding(int key, int state, Key_Binding** list); + void remove_key_binding(int key, int state) + { remove_key_binding(key, state, &key_bindings); } + void remove_all_key_bindings(Key_Binding** list); + void remove_all_key_bindings() { remove_all_key_bindings(&key_bindings); } + void add_default_key_bindings(Key_Binding** list); + Key_Func bound_key_function(int key, int state, Key_Binding* list); + Key_Func bound_key_function(int key, int state) + { return bound_key_function(key, state, key_bindings); } + void default_key_function(Key_Func f) { default_key_function_ = f; } + + // functions for the built in default bindings + static int kf_default(int c, Fl_Text_Editor* e); + static int kf_ignore(int c, Fl_Text_Editor* e); + static int kf_backspace(int c, Fl_Text_Editor* e); + static int kf_enter(int c, Fl_Text_Editor* e); + static int kf_move(int c, Fl_Text_Editor* e); + static int kf_shift_move(int c, Fl_Text_Editor* e); + static int kf_ctrl_move(int c, Fl_Text_Editor* e); + static int kf_c_s_move(int c, Fl_Text_Editor* e); + static int kf_home(int, Fl_Text_Editor* e); + static int kf_end(int c, Fl_Text_Editor* e); + static int kf_left(int c, Fl_Text_Editor* e); + static int kf_up(int c, Fl_Text_Editor* e); + static int kf_right(int c, Fl_Text_Editor* e); + static int kf_down(int c, Fl_Text_Editor* e); + static int kf_page_up(int c, Fl_Text_Editor* e); + static int kf_page_down(int c, Fl_Text_Editor* e); + static int kf_insert(int c, Fl_Text_Editor* e); + static int kf_delete(int c, Fl_Text_Editor* e); + static int kf_copy(int c, Fl_Text_Editor* e); + static int kf_cut(int c, Fl_Text_Editor* e); + static int kf_paste(int c, Fl_Text_Editor* e); + static int kf_select_all(int c, Fl_Text_Editor* e); + static int kf_undo(int c, Fl_Text_Editor* e); + + protected: + int handle_key(); + void maybe_do_callback(); + + int insert_mode_; + Key_Binding* key_bindings; + static Key_Binding* global_key_bindings; + Key_Func default_key_function_; +}; + +#endif + +// +// End of "$Id: Fl_Text_Editor.H 4288 2005-04-16 00:13:17Z mike $". +// + diff --git a/Utilities/FLTK/FL/Fl_Tile.H b/Utilities/FLTK/FL/Fl_Tile.H new file mode 100644 index 0000000000..69250f8b97 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Tile.H @@ -0,0 +1,45 @@ +// +// "$Id: Fl_Tile.H 4288 2005-04-16 00:13:17Z mike $" +// +// Tile header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Tile_H +#define Fl_Tile_H + +#include "Fl_Group.H" + +class FL_EXPORT Fl_Tile : public Fl_Group { +public: + int handle(int); + Fl_Tile(int X,int Y,int W,int H,const char*l=0) : Fl_Group(X,Y,W,H,l) {} + void resize(int, int, int, int); + void position(int, int, int, int); +}; + +#endif + +// +// End of "$Id: Fl_Tile.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Tiled_Image.H b/Utilities/FLTK/FL/Fl_Tiled_Image.H new file mode 100644 index 0000000000..4af8a9d859 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Tiled_Image.H @@ -0,0 +1,59 @@ +// +// "$Id: Fl_Tiled_Image.H 4288 2005-04-16 00:13:17Z mike $" +// +// Tiled image header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Tiled_Image_H +# define Fl_Tiled_Image_H + +# include "Fl_Image.H" + + +// Tiled image class. +class FL_EXPORT Fl_Tiled_Image : public Fl_Image { + protected: + + Fl_Image *image_; // The image that is shared + int alloc_image_; // Did we allocate this image? + + public: + + Fl_Tiled_Image(Fl_Image *i, int W = 0, int H = 0); + virtual ~Fl_Tiled_Image(); + + virtual Fl_Image *copy(int W, int H); + Fl_Image *copy() { return copy(w(), h()); } + virtual void color_average(Fl_Color c, float i); + virtual void desaturate(); + virtual void draw(int X, int Y, int W, int H, int cx, int cy); + void draw(int X, int Y) { draw(X, Y, w(), h(), 0, 0); } + Fl_Image *image() { return image_; } +}; + +#endif // !Fl_Tiled_Image_H + +// +// End of "$Id: Fl_Tiled_Image.H 4288 2005-04-16 00:13:17Z mike $" +// diff --git a/Utilities/FLTK/FL/Fl_Timer.H b/Utilities/FLTK/FL/Fl_Timer.H new file mode 100644 index 0000000000..765afdbf80 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Timer.H @@ -0,0 +1,65 @@ +// +// "$Id: Fl_Timer.H 4288 2005-04-16 00:13:17Z mike $" +// +// Timer header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Timer_H +#define Fl_Timer_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +// values for type(): +#define FL_NORMAL_TIMER 0 +#define FL_VALUE_TIMER 1 +#define FL_HIDDEN_TIMER 2 + +class FL_EXPORT Fl_Timer : public Fl_Widget { + static void stepcb(void *); + void step(); + char on, direction_; + double delay, total; + long lastsec,lastusec; +protected: + void draw(); +public: + int handle(int); + Fl_Timer(uchar t,int x,int y,int w,int h, const char *l); + ~Fl_Timer(); + void value(double); + double value() const {return delay>0.0?delay:0.0;} + char direction() const {return direction_;} + void direction(char d) {direction_ = d;} + char suspended() const {return !on;} + void suspended(char d); +}; + +#endif + +// +// End of "$Id: Fl_Timer.H 4288 2005-04-16 00:13:17Z mike $". +// + diff --git a/Utilities/FLTK/FL/Fl_Toggle_Button.H b/Utilities/FLTK/FL/Fl_Toggle_Button.H new file mode 100644 index 0000000000..b7764c5c01 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Toggle_Button.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_Toggle_Button.H 4288 2005-04-16 00:13:17Z mike $" +// +// Toggle button header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Toggle_Button_H +#define Fl_Toggle_Button_H + +#include "Fl_Button.H" + +class Fl_Toggle_Button : public Fl_Button { +public: + Fl_Toggle_Button(int X,int Y,int W,int H,const char *l=0) + : Fl_Button(X,Y,W,H,l) {type(FL_TOGGLE_BUTTON);} +}; + +#endif + +// +// End of "$Id: Fl_Toggle_Button.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Toggle_Light_Button.H b/Utilities/FLTK/FL/Fl_Toggle_Light_Button.H new file mode 100644 index 0000000000..be9e8a6f27 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Toggle_Light_Button.H @@ -0,0 +1,37 @@ +// +// "$Id: Fl_Toggle_Light_Button.H 4288 2005-04-16 00:13:17Z mike $" +// +// Toggle light button header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// provided for back-compatability only + +#ifndef Fl_Toggle_Light_Button +#include "Fl_Light_Button.H" +#define Fl_Toggle_Light_Button Fl_Light_Button +#endif + +// +// End of "$Id: Fl_Toggle_Light_Button.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Toggle_Round_Button.H b/Utilities/FLTK/FL/Fl_Toggle_Round_Button.H new file mode 100644 index 0000000000..087ad8e5fb --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Toggle_Round_Button.H @@ -0,0 +1,37 @@ +// +// "$Id: Fl_Toggle_Round_Button.H 4288 2005-04-16 00:13:17Z mike $" +// +// Toggle round button header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// provided for back-compatability only + +#ifndef Fl_Toggle_Round_Button +#include "Fl_Round_Button.H" +#define Fl_Toggle_Round_Button Fl_Round_Button +#endif + +// +// End of "$Id: Fl_Toggle_Round_Button.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Tooltip.H b/Utilities/FLTK/FL/Fl_Tooltip.H new file mode 100644 index 0000000000..28fb69a238 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Tooltip.H @@ -0,0 +1,77 @@ +// +// "$Id: Fl_Tooltip.H 4288 2005-04-16 00:13:17Z mike $" +// +// Tooltip header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Tooltip_H +#define Fl_Tooltip_H + +#include <FL/Fl.H> +#include <FL/Fl_Widget.H> + +class FL_EXPORT Fl_Tooltip { +public: + static float delay() { return delay_; } + static void delay(float f) { delay_ = f; } + static float hoverdelay() { return hoverdelay_; } + static void hoverdelay(float f) { hoverdelay_ = f; } + static int enabled() { return enabled_; } + static void enable(int b = 1) { enabled_ = b;} + static void disable() { enabled_ = 0; } + static void (*enter)(Fl_Widget* w); + static void enter_area(Fl_Widget* w, int X, int Y, int W, int H, const char* tip); + static void (*exit)(Fl_Widget *w); + static Fl_Widget* current() {return widget_;} + static void current(Fl_Widget*); + + static int font() { return font_; } + static int size() { return size_; } + static void font(int i) { font_ = i; } + static void size(int s) { size_ = s; } + static void color(unsigned c) { color_ = c; } + static Fl_Color color() { return (Fl_Color)color_; } + static void textcolor(unsigned c) { textcolor_ = c; } + static Fl_Color textcolor() { return (Fl_Color)textcolor_; } + + // These should not be public, but Fl_Widget::tooltip() needs them... + static void enter_(Fl_Widget* w); + static void exit_(Fl_Widget *w); + +private: + static float delay_; + static float hoverdelay_; + static int enabled_; + static unsigned color_; + static unsigned textcolor_; + static int font_; + static int size_; + static Fl_Widget* widget_; +}; + +#endif + +// +// End of "$Id: Fl_Tooltip.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Valuator.H b/Utilities/FLTK/FL/Fl_Valuator.H new file mode 100644 index 0000000000..b2cd601494 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Valuator.H @@ -0,0 +1,86 @@ +// +// "$Id: Fl_Valuator.H 4288 2005-04-16 00:13:17Z mike $" +// +// Valuator header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Valuator_H +#define Fl_Valuator_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +// shared type() values for classes that work in both directions: +#define FL_VERTICAL 0 +#define FL_HORIZONTAL 1 + +class FL_EXPORT Fl_Valuator : public Fl_Widget { + + double value_; + double previous_value_; + double min, max; // truncates to this range *after* rounding + double A; int B; // rounds to multiples of A/B, or no rounding if A is zero + +protected: + + int horizontal() const {return type()&1;} + Fl_Valuator(int X, int Y, int W, int H, const char* L); + + double previous_value() const {return previous_value_;} + void handle_push() {previous_value_ = value_;} + double softclamp(double); + void handle_drag(double newvalue); + void handle_release(); // use drag() value + virtual void value_damage(); // cause damage() due to value() changing + void set_value(double v) {value_ = v;} + +public: + + void bounds(double a, double b) {min=a; max=b;} + double minimum() const {return min;} + void minimum(double a) {min = a;} + double maximum() const {return max;} + void maximum(double a) {max = a;} + void range(double a, double b) {min = a; max = b;} + void step(int a) {A = a; B = 1;} + void step(double a, int b) {A = a; B = b;} + void step(double s); + double step() const {return A/B;} + void precision(int); + + double value() const {return value_;} + int value(double); + + virtual int format(char*); + double round(double); // round to nearest multiple of step + double clamp(double); // keep in range + double increment(double, int); // add n*step to value +}; + +#endif + +// +// End of "$Id: Fl_Valuator.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Value_Input.H b/Utilities/FLTK/FL/Fl_Value_Input.H new file mode 100644 index 0000000000..78dc211156 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Value_Input.H @@ -0,0 +1,65 @@ +// +// "$Id: Fl_Value_Input.H 4288 2005-04-16 00:13:17Z mike $" +// +// Value input header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Value_Input_H +#define Fl_Value_Input_H + +#include "Fl_Valuator.H" +#include "Fl_Input.H" + +class FL_EXPORT Fl_Value_Input : public Fl_Valuator { +public: + Fl_Input input; +private: + char soft_; + static void input_cb(Fl_Widget*,void*); + virtual void value_damage(); // cause damage() due to value() changing +public: + int handle(int); + void draw(); + void resize(int,int,int,int); + Fl_Value_Input(int x,int y,int w,int h,const char *l=0); + + void soft(char s) {soft_ = s;} + char soft() const {return soft_;} + + Fl_Font textfont() const {return input.textfont();} + void textfont(uchar s) {input.textfont(s);} + uchar textsize() const {return input.textsize();} + void textsize(uchar s) {input.textsize(s);} + Fl_Color textcolor() const {return input.textcolor();} + void textcolor(unsigned n) {input.textcolor(n);} + Fl_Color cursor_color() const {return input.cursor_color();} + void cursor_color(unsigned n) {input.cursor_color(n);} + +}; + +#endif + +// +// End of "$Id: Fl_Value_Input.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Value_Output.H b/Utilities/FLTK/FL/Fl_Value_Output.H new file mode 100644 index 0000000000..3353e885c4 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Value_Output.H @@ -0,0 +1,58 @@ +// +// "$Id: Fl_Value_Output.H 4288 2005-04-16 00:13:17Z mike $" +// +// Value output header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Value_Output_H +#define Fl_Value_Output_H + +#ifndef Fl_Valuator_H +#include "Fl_Valuator.H" +#endif + +class FL_EXPORT Fl_Value_Output : public Fl_Valuator { + uchar textfont_, textsize_, soft_; + unsigned textcolor_; +public: + int handle(int); + void draw(); + Fl_Value_Output(int x,int y,int w,int h,const char *l=0); + + void soft(uchar s) {soft_ = s;} + uchar soft() const {return soft_;} + + Fl_Font textfont() const {return (Fl_Font)textfont_;} + void textfont(uchar s) {textfont_ = s;} + uchar textsize() const {return textsize_;} + void textsize(uchar s) {textsize_ = s;} + Fl_Color textcolor() const {return (Fl_Color)textcolor_;} + void textcolor(unsigned s) {textcolor_ = s;} +}; + +#endif + +// +// End of "$Id: Fl_Value_Output.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Value_Slider.H b/Utilities/FLTK/FL/Fl_Value_Slider.H new file mode 100644 index 0000000000..5162e8a3fa --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Value_Slider.H @@ -0,0 +1,52 @@ +// +// "$Id: Fl_Value_Slider.H 4288 2005-04-16 00:13:17Z mike $" +// +// Value slider header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Value_Slider_H +#define Fl_Value_Slider_H + +#include "Fl_Slider.H" + +class FL_EXPORT Fl_Value_Slider : public Fl_Slider { + uchar textfont_, textsize_; + unsigned textcolor_; +public: + void draw(); + int handle(int); + Fl_Value_Slider(int x,int y,int w,int h, const char *l = 0); + Fl_Font textfont() const {return (Fl_Font)textfont_;} + void textfont(uchar s) {textfont_ = s;} + uchar textsize() const {return textsize_;} + void textsize(uchar s) {textsize_ = s;} + Fl_Color textcolor() const {return (Fl_Color)textcolor_;} + void textcolor(unsigned s) {textcolor_ = s;} +}; + +#endif + +// +// End of "$Id: Fl_Value_Slider.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_Widget.H b/Utilities/FLTK/FL/Fl_Widget.H new file mode 100644 index 0000000000..a86556ca94 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Widget.H @@ -0,0 +1,220 @@ +// +// "$Id: Fl_Widget.H 4421 2005-07-15 09:34:53Z matt $" +// +// Widget header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Widget_H +#define Fl_Widget_H + +#include "Enumerations.H" + +class Fl_Widget; +class Fl_Window; +class Fl_Group; +class Fl_Image; + +typedef void (Fl_Callback )(Fl_Widget*, void*); +typedef Fl_Callback* Fl_Callback_p; // needed for BORLAND +typedef void (Fl_Callback0)(Fl_Widget*); +typedef void (Fl_Callback1)(Fl_Widget*, long); + +struct FL_EXPORT Fl_Label { + const char* value; + Fl_Image* image; + Fl_Image* deimage; + uchar type; + uchar font; + uchar size; + unsigned color; + void draw(int,int,int,int, Fl_Align) const ; + void measure(int&, int&) const ; +}; + +class FL_EXPORT Fl_Widget { + friend class Fl_Group; + + Fl_Group* parent_; + Fl_Callback* callback_; + void* user_data_; + short x_,y_,w_,h_; + Fl_Label label_; + int flags_; + unsigned color_; + unsigned color2_; + uchar type_; + uchar damage_; + uchar box_; + uchar align_; + uchar when_; + + const char *tooltip_; + + // unimplemented copy ctor and assignment operator + Fl_Widget(const Fl_Widget &); + Fl_Widget& operator=(const Fl_Widget &); + +protected: + + Fl_Widget(int,int,int,int,const char* =0); + + void x(int v) {x_ = (short)v;} + void y(int v) {y_ = (short)v;} + void w(int v) {w_ = (short)v;} + void h(int v) {h_ = (short)v;} + + int flags() const {return flags_;} + void set_flag(int c) {flags_ |= c;} + void clear_flag(int c) {flags_ &= ~c;} + enum {INACTIVE=1, INVISIBLE=2, OUTPUT=4, SHORTCUT_LABEL=64, + CHANGED=128, VISIBLE_FOCUS=512, COPIED_LABEL = 1024}; + + void draw_box() const; + void draw_box(Fl_Boxtype, Fl_Color) const; + void draw_box(Fl_Boxtype, int,int,int,int, Fl_Color) const; + void draw_focus() {draw_focus(box(),x(),y(),w(),h());} + void draw_focus(Fl_Boxtype, int,int,int,int) const; + void draw_label() const; + void draw_label(int, int, int, int) const; + +public: + + virtual ~Fl_Widget(); + + virtual void draw() = 0; + virtual int handle(int); + Fl_Group* parent() const {return parent_;} + void parent(Fl_Group* p) {parent_ = p;} // for hacks only, Fl_Group::add() + + uchar type() const {return type_;} + void type(uchar t) {type_ = t;} + + int x() const {return x_;} + int y() const {return y_;} + int w() const {return w_;} + int h() const {return h_;} + virtual void resize(int,int,int,int); + int damage_resize(int,int,int,int); + void position(int X,int Y) {resize(X,Y,w_,h_);} + void size(int W,int H) {resize(x_,y_,W,H);} + + Fl_Align align() const {return (Fl_Align)align_;} + void align(uchar a) {align_ = a;} + Fl_Boxtype box() const {return (Fl_Boxtype)box_;} + void box(Fl_Boxtype a) {box_ = a;} + Fl_Color color() const {return (Fl_Color)color_;} + void color(unsigned a) {color_ = a;} + Fl_Color selection_color() const {return (Fl_Color)color2_;} + void selection_color(unsigned a) {color2_ = a;} + void color(unsigned a, unsigned b) {color_=a; color2_=b;} + const char* label() const {return label_.value;} + void label(const char* a); + void copy_label(const char* a); + void label(Fl_Labeltype a,const char* b) {label_.type = a; label_.value = b;} + Fl_Labeltype labeltype() const {return (Fl_Labeltype)label_.type;} + void labeltype(Fl_Labeltype a) {label_.type = a;} + Fl_Color labelcolor() const {return (Fl_Color)label_.color;} + void labelcolor(unsigned a) {label_.color=a;} + Fl_Font labelfont() const {return (Fl_Font)label_.font;} + void labelfont(uchar a) {label_.font=a;} + uchar labelsize() const {return label_.size;} + void labelsize(uchar a) {label_.size=a;} + Fl_Image* image() {return label_.image;} + void image(Fl_Image* a) {label_.image=a;} + void image(Fl_Image& a) {label_.image=&a;} + Fl_Image* deimage() {return label_.deimage;} + void deimage(Fl_Image* a) {label_.deimage=a;} + void deimage(Fl_Image& a) {label_.deimage=&a;} + const char *tooltip() const {return tooltip_;} + void tooltip(const char *t); + Fl_Callback_p callback() const {return callback_;} + void callback(Fl_Callback* c, void* p) {callback_=c; user_data_=p;} + void callback(Fl_Callback* c) {callback_=c;} + void callback(Fl_Callback0*c) {callback_=(Fl_Callback*)c;} + void callback(Fl_Callback1*c, long p=0) {callback_=(Fl_Callback*)c; user_data_=(void*)p;} + void* user_data() const {return user_data_;} + void user_data(void* v) {user_data_ = v;} + long argument() const {return (long)user_data_;} + void argument(long v) {user_data_ = (void*)v;} + Fl_When when() const {return (Fl_When)when_;} + void when(uchar i) {when_ = i;} + + int visible() const {return !(flags_&INVISIBLE);} + int visible_r() const; + void show(); + void hide(); + void set_visible() {flags_ &= ~INVISIBLE;} + void clear_visible() {flags_ |= INVISIBLE;} + int active() const {return !(flags_&INACTIVE);} + int active_r() const; + void activate(); + void deactivate(); + int output() const {return (flags_&OUTPUT);} + void set_output() {flags_ |= OUTPUT;} + void clear_output() {flags_ &= ~OUTPUT;} + int takesevents() const {return !(flags_&(INACTIVE|INVISIBLE|OUTPUT));} + int changed() const {return flags_&CHANGED;} + void set_changed() {flags_ |= CHANGED;} + void clear_changed() {flags_ &= ~CHANGED;} + int take_focus(); + void set_visible_focus() { flags_ |= VISIBLE_FOCUS; } + void clear_visible_focus() { flags_ &= ~VISIBLE_FOCUS; } + void visible_focus(int v) { if (v) set_visible_focus(); else clear_visible_focus(); } + int visible_focus() { return flags_ & VISIBLE_FOCUS; } + + static void default_callback(Fl_Widget*, void*); + void do_callback() {callback_(this,user_data_); if (callback_ != default_callback) clear_changed();} + void do_callback(Fl_Widget* o,void* arg=0) {callback_(o,arg); if (callback_ != default_callback) clear_changed();} + void do_callback(Fl_Widget* o,long arg) {callback_(o,(void*)arg); if (callback_ != default_callback) clear_changed();} + int test_shortcut(); + static int test_shortcut(const char*); + int contains(const Fl_Widget*) const ; + int inside(const Fl_Widget* o) const {return o ? o->contains(this) : 0;} + + void redraw(); + void redraw_label(); + uchar damage() const {return damage_;} + void clear_damage(uchar c = 0) {damage_ = c;} + void damage(uchar c); + void damage(uchar c,int,int,int,int); + void draw_label(int, int, int, int, Fl_Align) const; + void measure_label(int& xx, int& yy) {label_.measure(xx,yy);} + + Fl_Window* window() const ; + + // back compatability only: + Fl_Color color2() const {return (Fl_Color)color2_;} + void color2(unsigned a) {color2_ = a;} +}; + +// reserved type numbers (necessary for my cheapo RTTI) start here. +// grep the header files for "RESERVED_TYPE" to find the next available +// number. +#define FL_RESERVED_TYPE 100 + +#endif + +// +// End of "$Id: Fl_Widget.H 4421 2005-07-15 09:34:53Z matt $". +// diff --git a/Utilities/FLTK/FL/Fl_Window.H b/Utilities/FLTK/FL/Fl_Window.H new file mode 100644 index 0000000000..16a02259e8 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Window.H @@ -0,0 +1,135 @@ +// +// "$Id: Fl_Window.H 4421 2005-07-15 09:34:53Z matt $" +// +// Window header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Window_H +#define Fl_Window_H + +#include "Fl_Group.H" + +#define FL_WINDOW 0xF0 // all subclasses have type() >= this +#define FL_DOUBLE_WINDOW 0xF1 + +class Fl_X; + +class FL_EXPORT Fl_Window : public Fl_Group { + + friend class Fl_X; + Fl_X *i; // points at the system-specific stuff + + const char* iconlabel_; + const char* xclass_; + const void* icon_; + // size_range stuff: + short minw, minh, maxw, maxh; + uchar dw, dh, aspect, size_range_set; + // cursor stuff + Fl_Cursor cursor_default; + Fl_Color cursor_fg, cursor_bg; + void size_range_(); + // values for flags(): + enum { + FL_MODAL = 64, + FL_NOBORDER = 8, + FL_FORCE_POSITION = 16, + FL_NON_MODAL = 32, + FL_OVERRIDE = 256 + }; + void _Fl_Window(); // constructor innards + + // unimplemented copy ctor and assignment operator + Fl_Window(const Fl_Window&); + Fl_Window& operator=(const Fl_Window&); + +protected: + + static Fl_Window *current_; + virtual void draw(); + virtual void flush(); + +public: + + Fl_Window(int,int,int,int, const char* = 0); + Fl_Window(int,int, const char* = 0); + virtual ~Fl_Window(); + + virtual int handle(int); + + virtual void resize(int,int,int,int); + void border(int b); + void clear_border() {set_flag(FL_NOBORDER);} + int border() const {return !(flags() & FL_NOBORDER);} + void set_override() {set_flag(FL_NOBORDER|FL_OVERRIDE);} + int override() const { return flags()&FL_OVERRIDE; } + void set_modal() {set_flag(FL_MODAL);} + int modal() const {return flags() & FL_MODAL;} + void set_non_modal() {set_flag(FL_NON_MODAL);} + int non_modal() const {return flags() & (FL_NON_MODAL|FL_MODAL);} + + void hotspot(int x, int y, int offscreen = 0); + void hotspot(const Fl_Widget*, int offscreen = 0); + void hotspot(const Fl_Widget& p, int offscreen = 0) {hotspot(&p,offscreen);} + void free_position() {clear_flag(FL_FORCE_POSITION);} + void size_range(int a, int b, int c=0, int d=0, int e=0, int f=0, int g=0) { + minw=(short)a; minh=(short)b; maxw=(short)c; maxh=(short)d; dw=(uchar)e; dh=(uchar)f; aspect=(uchar)g; size_range_();} + + const char* label() const {return Fl_Widget::label();} + const char* iconlabel() const {return iconlabel_;} + void label(const char*); + void iconlabel(const char*); + void label(const char* label, const char* iconlabel); + void copy_label(const char* a); + const char* xclass() const {return xclass_;} + void xclass(const char* c) {xclass_ = c;} + const void* icon() const {return icon_;} + void icon(const void * ic) {icon_ = ic;} + + int shown() {return i != 0;} + virtual void show(); + virtual void hide(); + void show(int, char**); + void fullscreen(); + void fullscreen_off(int,int,int,int); + void iconize(); + + int x_root() const ; + int y_root() const ; + + static Fl_Window *current(); + void make_current(); + + // for back-compatability only: + void cursor(Fl_Cursor, Fl_Color=FL_BLACK, Fl_Color=FL_WHITE); + void default_cursor(Fl_Cursor, Fl_Color=FL_BLACK, Fl_Color=FL_WHITE); + static void default_callback(Fl_Window*, void* v); + +}; + +#endif + +// +// End of "$Id: Fl_Window.H 4421 2005-07-15 09:34:53Z matt $". +// diff --git a/Utilities/FLTK/FL/Fl_Wizard.H b/Utilities/FLTK/FL/Fl_Wizard.H new file mode 100644 index 0000000000..4c39b7ec59 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_Wizard.H @@ -0,0 +1,62 @@ +// +// "$Id: Fl_Wizard.H 4288 2005-04-16 00:13:17Z mike $" +// +// Fl_Wizard widget definitions. +// +// Copyright 1999-2005 by Easy Software Products. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// +// Include necessary header files... +// + +#ifndef _Fl_Wizard_H_ +# define _Fl_Wizard_H_ + +# include <FL/Fl_Group.H> + + +// +// Fl_Wizard class... +// + +class FL_EXPORT Fl_Wizard : public Fl_Group +{ + Fl_Widget *value_; + + void draw(); + + public: + + Fl_Wizard(int, int, int, int, const char * = 0); + + void next(); + void prev(); + Fl_Widget *value(); + void value(Fl_Widget *); +}; + +#endif // !_Fl_Wizard_H_ + +// +// End of "$Id: Fl_Wizard.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_XBM_Image.H b/Utilities/FLTK/FL/Fl_XBM_Image.H new file mode 100644 index 0000000000..90f94ab9f8 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_XBM_Image.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_XBM_Image.H 4288 2005-04-16 00:13:17Z mike $" +// +// XBM image header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_XBM_Image_H +#define Fl_XBM_Image_H +# include "Fl_Bitmap.H" + +class FL_EXPORT Fl_XBM_Image : public Fl_Bitmap { + + public: + + Fl_XBM_Image(const char* filename); +}; + +#endif // !Fl_XBM_Image_H + +// +// End of "$Id: Fl_XBM_Image.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Fl_XPM_Image.H b/Utilities/FLTK/FL/Fl_XPM_Image.H new file mode 100644 index 0000000000..9ffb1c1085 --- /dev/null +++ b/Utilities/FLTK/FL/Fl_XPM_Image.H @@ -0,0 +1,43 @@ +// +// "$Id: Fl_XPM_Image.H 4288 2005-04-16 00:13:17Z mike $" +// +// XPM image header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_XPM_Image_H +#define Fl_XPM_Image_H +# include "Fl_Pixmap.H" + +class FL_EXPORT Fl_XPM_Image : public Fl_Pixmap { + + public: + + Fl_XPM_Image(const char* filename); +}; + +#endif // !Fl_XPM_Image + +// +// End of "$Id: Fl_XPM_Image.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/Makefile.in b/Utilities/FLTK/FL/Makefile.in new file mode 100644 index 0000000000..9fb8fde8d3 --- /dev/null +++ b/Utilities/FLTK/FL/Makefile.in @@ -0,0 +1,64 @@ +# +# "$Id: Makefile.in 4288 2005-04-16 00:13:17Z mike $" +# +# Header makefile for the Fast Light Tool Kit (FLTK). +# +# Copyright 1998-2005 by Bill Spitzak and others. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. +# +# Please report all bugs and problems on the following page: +# +# http://www.fltk.org/str.php +# + +include ../makeinclude + +all: + +clean: + +depend: + +install: + echo "Installing include files in $(DESTDIR)$(includedir)..." + -$(MKDIR) -p $(DESTDIR)$(includedir) + $(RMDIR) $(DESTDIR)$(includedir)/FL + $(MKDIR) $(DESTDIR)$(includedir)/FL + $(CHMOD) 755 $(DESTDIR)$(includedir)/FL + $(CP) ../FL/*.[hHr] $(DESTDIR)$(includedir)/FL + $(CHMOD) 644 $(DESTDIR)$(includedir)/FL/*.[hHr] +@HLINKS@ cd $(DESTDIR)$(includedir)/FL;\ +@HLINKS@ for file in *.H; do\ +@HLINKS@ $(RM) "`basename $$file H`h";\ +@HLINKS@ $(LN) $$file "`basename $$file H`h";\ +@HLINKS@ done +@HLINKS@ $(RM) $(DESTDIR)$(includedir)/FL/fl_file_chooser.H +@HLINKS@ $(LN) Fl_File_Chooser.H $(DESTDIR)$(includedir)/FL/fl_file_chooser.H +@HLINKS@ $(RM) $(DESTDIR)$(includedir)/FL/fl_file_chooser.h +@HLINKS@ $(LN) Fl_File_Chooser.H $(DESTDIR)$(includedir)/FL/fl_file_chooser.h +@HLINKS@ $(RM) $(DESTDIR)$(includedir)/Fl +@HLINKS@ $(LN) FL $(DESTDIR)$(includedir)/Fl + +uninstall: + echo "Uninstalling include files..." + $(RMDIR) $(DESTDIR)$(includedir)/FL +@HLINKS@ $(RM) $(DESTDIR)$(includedir)/Fl + + +# +# End of "$Id: Makefile.in 4288 2005-04-16 00:13:17Z mike $". +# diff --git a/Utilities/FLTK/FL/dirent.h b/Utilities/FLTK/FL/dirent.h new file mode 100644 index 0000000000..93db65619e --- /dev/null +++ b/Utilities/FLTK/FL/dirent.h @@ -0,0 +1,33 @@ +// +// "$Id$" +// +// Directory header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// this file is for back-compatability only +#include "filename.H" + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/FL/filename.H b/Utilities/FLTK/FL/filename.H new file mode 100644 index 0000000000..df7dd87d13 --- /dev/null +++ b/Utilities/FLTK/FL/filename.H @@ -0,0 +1,138 @@ +/* + * "$Id: filename.H 4548 2005-08-29 20:16:36Z matt $" + * + * Filename header file for the Fast Light Tool Kit (FLTK). + * + * Copyright 1998-2005 by Bill Spitzak and others. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems on the following page: + * + * http://www.fltk.org/str.php + */ + +#ifndef FL_FILENAME_H +# define FL_FILENAME_H + +# include "Fl_Export.H" + +# define FL_PATH_MAX 256 /* all buffers are this length */ + +FL_EXPORT const char *fl_filename_name(const char *); +FL_EXPORT const char *fl_filename_ext(const char *); +FL_EXPORT char *fl_filename_setext(char *to, int tolen, const char *ext); +FL_EXPORT int fl_filename_expand(char *to, int tolen, const char *from); +FL_EXPORT int fl_filename_absolute(char *to, int tolen, const char *from); +FL_EXPORT int fl_filename_relative(char *to, int tolen, const char *from); +FL_EXPORT int fl_filename_match(const char *name, const char *pattern); +FL_EXPORT int fl_filename_isdir(const char *name); + +# ifdef __cplusplus +/* + * Under WIN32, we include filename.H from numericsort.c; this should probably change... + */ + +inline char *fl_filename_setext(char *to, const char *ext) { return fl_filename_setext(to, FL_PATH_MAX, ext); } +inline int fl_filename_expand(char *to, const char *from) { return fl_filename_expand(to, FL_PATH_MAX, from); } +inline int fl_filename_absolute(char *to, const char *from) { return fl_filename_absolute(to, FL_PATH_MAX, from); } +inline int fl_filename_relative(char *to, const char *from) { return fl_filename_relative(to, FL_PATH_MAX, from); } +# endif /* __cplusplus */ + + +# if defined(WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) + +struct dirent {char d_name[1];}; + +# elif defined(__APPLE__) && defined(__PROJECTBUILDER__) + +/* Apple's ProjectBuilder has the nasty habit of including recursively + * down the file tree. To avoid re-including <FL/dirent.h> we must + * directly include the systems math file. (Plus, I could not find a + * predefined macro for ProjectBuilder builds, so we have to define it + * in the project) + */ +# include <sys/types.h> +# include "/usr/include/dirent.h" + +# elif defined(__WATCOMC__) +# include <sys/types.h> +# include <direct.h> + +# else +/* + * WARNING: on some systems (very few nowadays?) <dirent.h> may not exist. + * The correct information is in one of these files: + * + * #include <sys/ndir.h> + * #include <sys/dir.h> + * #include <ndir.h> + * + * plus you must do the following #define: + * + * #define dirent direct + * + * It would be best to create a <dirent.h> file that does this... + */ +# include <sys/types.h> +# include <dirent.h> +# endif + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + +FL_EXPORT int fl_alphasort(struct dirent **, struct dirent **); +FL_EXPORT int fl_casealphasort(struct dirent **, struct dirent **); +FL_EXPORT int fl_casenumericsort(struct dirent **, struct dirent **); +FL_EXPORT int fl_numericsort(struct dirent **, struct dirent **); + +typedef int (Fl_File_Sort_F)(struct dirent **, struct dirent **); + +# ifdef __cplusplus +} + +/* + * Portable "scandir" function. Ugly but necessary... + */ + +FL_EXPORT int fl_filename_list(const char *d, struct dirent ***l, + Fl_File_Sort_F *s = fl_numericsort); +# endif /* __cplusplus */ + +/* + * FLTK 1.0.x compatibility definitions... + */ + +# ifdef FLTK_1_0_COMPAT +# define filename_absolute fl_filename_absolute +# define filename_expand fl_filename_expand +# define filename_ext fl_filename_ext +# define filename_isdir fl_filename_isdir +# define filename_list fl_filename_list +# define filename_match fl_filename_match +# define filename_name fl_filename_name +# define filename_relative fl_filename_relative +# define filename_setext fl_filename_setext +# define numericsort fl_numericsort +# endif /* FLTK_1_0_COMPAT */ + + +#endif /* FL_FILENAME_H */ + +/* + * End of "$Id: filename.H 4548 2005-08-29 20:16:36Z matt $". + */ diff --git a/Utilities/FLTK/FL/fl_ask.H b/Utilities/FLTK/FL/fl_ask.H new file mode 100644 index 0000000000..f237af11d6 --- /dev/null +++ b/Utilities/FLTK/FL/fl_ask.H @@ -0,0 +1,81 @@ +// +// "$Id: fl_ask.H 4279 2005-04-13 19:35:28Z mike $" +// +// Standard dialog header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef fl_ask_H +# define fl_ask_H + +# include "Enumerations.H" + +class Fl_Widget; + +enum { + FL_BEEP_DEFAULT = 0, + FL_BEEP_MESSAGE, + FL_BEEP_ERROR, + FL_BEEP_QUESTION, + FL_BEEP_PASSWORD, + FL_BEEP_NOTIFICATION +}; + +# ifdef __GNUC__ +# define __fl_attr(x) __attribute__ (x) +# if __GNUC__ < 3 +# define __deprecated__ +# endif // __GNUC__ < 3 +# else +# define __fl_attr(x) +# endif // __GNUC__ + +FL_EXPORT void fl_beep(int type = FL_BEEP_DEFAULT); +FL_EXPORT void fl_message(const char *,...) __fl_attr((__format__ (__printf__, 1, 2))); +FL_EXPORT void fl_alert(const char *,...) __fl_attr((__format__ (__printf__, 1, 2))); +// fl_ask() is deprecated since it uses "Yes" and "No" for the buttons, +// which does not conform to the current FLTK Human Interface Guidelines. +// Use fl_choice() instead with the appropriate verbs instead. +FL_EXPORT int fl_ask(const char *,...) __fl_attr((__format__ (__printf__, 1, 2), __deprecated__)); +FL_EXPORT int fl_choice(const char *q,const char *b0,const char *b1,const char *b2,...) __fl_attr((__format__ (__printf__, 1, 5))); +FL_EXPORT const char *fl_input(const char *label, const char *deflt = 0, ...) __fl_attr((__format__ (__printf__, 1, 3))); +FL_EXPORT const char *fl_password(const char *label, const char *deflt = 0, ...) __fl_attr((__format__ (__printf__, 1, 3))); + +FL_EXPORT Fl_Widget *fl_message_icon(); +extern FL_EXPORT Fl_Font fl_message_font_; +extern FL_EXPORT unsigned char fl_message_size_; +inline void fl_message_font(unsigned char f,unsigned char s) { + fl_message_font_ = (Fl_Font)f; fl_message_size_ = s;} + +// pointers you can use to change FLTK to a foreign language: +extern FL_EXPORT const char* fl_no; +extern FL_EXPORT const char* fl_yes; +extern FL_EXPORT const char* fl_ok; +extern FL_EXPORT const char* fl_cancel; +extern FL_EXPORT const char* fl_close; + +#endif // !fl_ask_H + +// +// End of "$Id: fl_ask.H 4279 2005-04-13 19:35:28Z mike $". +// diff --git a/Utilities/FLTK/FL/fl_draw.H b/Utilities/FLTK/FL/fl_draw.H new file mode 100644 index 0000000000..ba5d71054a --- /dev/null +++ b/Utilities/FLTK/FL/fl_draw.H @@ -0,0 +1,200 @@ +// +// "$Id: fl_draw.H 4288 2005-04-16 00:13:17Z mike $" +// +// Portable drawing function header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef fl_draw_H +#define fl_draw_H + +#include "Enumerations.H" // for the color names + +// Image class... +class Fl_Image; + +// Label flags... +FL_EXPORT extern char fl_draw_shortcut; + +// Colors: +FL_EXPORT void fl_color(Fl_Color); // select indexed color +inline void fl_color(int c) {fl_color((Fl_Color)c);} // for back compatability +FL_EXPORT void fl_color(uchar, uchar, uchar); // select actual color +extern FL_EXPORT Fl_Color fl_color_; +inline Fl_Color fl_color() {return fl_color_;} + +// clip: +FL_EXPORT void fl_push_clip(int x, int y, int w, int h); +#define fl_clip fl_push_clip +FL_EXPORT void fl_push_no_clip(); +FL_EXPORT void fl_pop_clip(); +FL_EXPORT int fl_not_clipped(int x, int y, int w, int h); +FL_EXPORT int fl_clip_box(int, int, int, int, int& x, int& y, int& w, int& h); + +// points: +FL_EXPORT void fl_point(int x, int y); + +// line type: +FL_EXPORT void fl_line_style(int style, int width=0, char* dashes=0); +enum { + FL_SOLID = 0, + FL_DASH = 1, + FL_DOT = 2, + FL_DASHDOT = 3, + FL_DASHDOTDOT = 4, + + FL_CAP_FLAT = 0x100, + FL_CAP_ROUND = 0x200, + FL_CAP_SQUARE = 0x300, + + FL_JOIN_MITER = 0x1000, + FL_JOIN_ROUND = 0x2000, + FL_JOIN_BEVEL = 0x3000 +}; + +// rectangles tweaked to exactly fill the pixel rectangle: +FL_EXPORT void fl_rect(int x, int y, int w, int h); +inline void fl_rect(int x, int y, int w, int h, Fl_Color c) {fl_color(c); fl_rect(x,y,w,h);} +FL_EXPORT void fl_rectf(int x, int y, int w, int h); +inline void fl_rectf(int x, int y, int w, int h, Fl_Color c) {fl_color(c); fl_rectf(x,y,w,h);} + +// line segments: +FL_EXPORT void fl_line(int,int, int,int); +FL_EXPORT void fl_line(int,int, int,int, int,int); + +// closed line segments: +FL_EXPORT void fl_loop(int,int, int,int, int,int); +FL_EXPORT void fl_loop(int,int, int,int, int,int, int,int); + +// filled polygons +FL_EXPORT void fl_polygon(int,int, int,int, int,int); +FL_EXPORT void fl_polygon(int,int, int,int, int,int, int,int); + +// draw rectilinear lines, horizontal segment first: +FL_EXPORT void fl_xyline(int x, int y, int x1); +FL_EXPORT void fl_xyline(int x, int y, int x1, int y2); +FL_EXPORT void fl_xyline(int x, int y, int x1, int y2, int x3); + +// draw rectilinear lines, vertical segment first: +FL_EXPORT void fl_yxline(int x, int y, int y1); +FL_EXPORT void fl_yxline(int x, int y, int y1, int x2); +FL_EXPORT void fl_yxline(int x, int y, int y1, int x2, int y3); + +// circular lines and pie slices (code in fl_arci.C): +FL_EXPORT void fl_arc(int x, int y, int w, int h, double a1, double a2); +FL_EXPORT void fl_pie(int x, int y, int w, int h, double a1, double a2); +FL_EXPORT void fl_chord(int x, int y, int w, int h, double a1, double a2); // nyi + +// scalable drawing code (code in fl_vertex.C and fl_arc.C): +FL_EXPORT void fl_push_matrix(); +FL_EXPORT void fl_pop_matrix(); +FL_EXPORT void fl_scale(double x, double y); +FL_EXPORT void fl_scale(double x); +FL_EXPORT void fl_translate(double x, double y); +FL_EXPORT void fl_rotate(double d); +FL_EXPORT void fl_mult_matrix(double a, double b, double c, double d, double x,double y); +FL_EXPORT void fl_begin_points(); +FL_EXPORT void fl_begin_line(); +FL_EXPORT void fl_begin_loop(); +FL_EXPORT void fl_begin_polygon(); +FL_EXPORT void fl_vertex(double x, double y); +FL_EXPORT void fl_curve(double, double, double, double, double, double, double, double); +FL_EXPORT void fl_arc(double x, double y, double r, double start, double a); +FL_EXPORT void fl_circle(double x, double y, double r); +FL_EXPORT void fl_end_points(); +FL_EXPORT void fl_end_line(); +FL_EXPORT void fl_end_loop(); +FL_EXPORT void fl_end_polygon(); +FL_EXPORT void fl_begin_complex_polygon(); +FL_EXPORT void fl_gap(); +FL_EXPORT void fl_end_complex_polygon(); +// get and use transformed positions: +FL_EXPORT double fl_transform_x(double x, double y); +FL_EXPORT double fl_transform_y(double x, double y); +FL_EXPORT double fl_transform_dx(double x, double y); +FL_EXPORT double fl_transform_dy(double x, double y); +FL_EXPORT void fl_transformed_vertex(double x, double y); + +// current font: +FL_EXPORT void fl_font(int face, int size); +extern FL_EXPORT int fl_font_; +inline int fl_font() {return fl_font_;} +extern FL_EXPORT int fl_size_; +inline int fl_size() {return fl_size_;} + +// information you can get about the current font: +FL_EXPORT int fl_height(); // using "size" should work ok +inline int fl_height(int, int size) {return size;} +FL_EXPORT int fl_descent(); +FL_EXPORT double fl_width(const char*); +FL_EXPORT double fl_width(const char*, int n); +FL_EXPORT double fl_width(uchar); + +// draw using current font: +FL_EXPORT void fl_draw(const char*, int x, int y); +FL_EXPORT void fl_draw(const char*, int n, int x, int y); +FL_EXPORT void fl_measure(const char*, int& x, int& y, int draw_symbols = 1); +FL_EXPORT void fl_draw(const char*, int,int,int,int, Fl_Align, Fl_Image* img=0, + int draw_symbols = 1); +FL_EXPORT void fl_draw(const char*, int,int,int,int, Fl_Align, + void (*callthis)(const char *, int n, int x, int y), + Fl_Image* img=0, int draw_symbols = 1); + +// boxtypes: +FL_EXPORT void fl_frame(const char* s, int x, int y, int w, int h); +FL_EXPORT void fl_frame2(const char* s, int x, int y, int w, int h); +FL_EXPORT void fl_draw_box(Fl_Boxtype, int x, int y, int w, int h, Fl_Color); + +// images: +FL_EXPORT void fl_draw_image(const uchar*, int,int,int,int, int delta=3, int ldelta=0); +FL_EXPORT void fl_draw_image_mono(const uchar*, int,int,int,int, int delta=1, int ld=0); +typedef void (*Fl_Draw_Image_Cb)(void*,int,int,int,uchar*); +FL_EXPORT void fl_draw_image(Fl_Draw_Image_Cb, void*, int,int,int,int, int delta=3); +FL_EXPORT void fl_draw_image_mono(Fl_Draw_Image_Cb, void*, int,int,int,int, int delta=1); +FL_EXPORT void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b); + +FL_EXPORT uchar *fl_read_image(uchar *p, int x,int y, int w, int h, int alpha=0); + +// pixmaps: +FL_EXPORT int fl_draw_pixmap(/*const*/ char* const* data, int x,int y,Fl_Color=FL_GRAY); +FL_EXPORT int fl_measure_pixmap(/*const*/ char* const* data, int &w, int &h); +FL_EXPORT int fl_draw_pixmap(const char* const* data, int x,int y,Fl_Color=FL_GRAY); +FL_EXPORT int fl_measure_pixmap(const char* const* data, int &w, int &h); + +// other: +FL_EXPORT void fl_scroll(int X, int Y, int W, int H, int dx, int dy, + void (*draw_area)(void*, int,int,int,int), void* data); +FL_EXPORT const char* fl_shortcut_label(int); +FL_EXPORT void fl_overlay_rect(int,int,int,int); +FL_EXPORT void fl_overlay_clear(); +FL_EXPORT void fl_cursor(Fl_Cursor, Fl_Color=FL_BLACK, Fl_Color=FL_WHITE); + +// XForms symbols: +FL_EXPORT int fl_draw_symbol(const char* label,int x,int y,int w,int h, Fl_Color); +FL_EXPORT int fl_add_symbol(const char* name, void (*drawit)(Fl_Color), int scalable); + +#endif + +// +// End of "$Id: fl_draw.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/fl_message.H b/Utilities/FLTK/FL/fl_message.H new file mode 100644 index 0000000000..dd66272ee4 --- /dev/null +++ b/Utilities/FLTK/FL/fl_message.H @@ -0,0 +1,32 @@ +// +// "$Id: fl_message.H 4288 2005-04-16 00:13:17Z mike $" +// +// Standard message header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include "fl_ask.H" + +// +// End of "$Id: fl_message.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/fl_show_colormap.H b/Utilities/FLTK/FL/fl_show_colormap.H new file mode 100644 index 0000000000..baaa2b708b --- /dev/null +++ b/Utilities/FLTK/FL/fl_show_colormap.H @@ -0,0 +1,37 @@ +// +// "$Id: fl_show_colormap.H 4288 2005-04-16 00:13:17Z mike $" +// +// Colormap picker header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef fl_show_colormap_H +#define fl_show_colormap_H + +FL_EXPORT Fl_Color fl_show_colormap(Fl_Color oldcol); + +#endif + +// +// End of "$Id: fl_show_colormap.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/fl_show_input.H b/Utilities/FLTK/FL/fl_show_input.H new file mode 100644 index 0000000000..3773f99aca --- /dev/null +++ b/Utilities/FLTK/FL/fl_show_input.H @@ -0,0 +1,32 @@ +// +// "$Id: fl_show_input.H 4288 2005-04-16 00:13:17Z mike $" +// +// Standard input dialog header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include "fl_ask.H" + +// +// End of "$Id: fl_show_input.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/forms.H b/Utilities/FLTK/FL/forms.H new file mode 100644 index 0000000000..dabbea3677 --- /dev/null +++ b/Utilities/FLTK/FL/forms.H @@ -0,0 +1,844 @@ +// +// "$Id: forms.H 4288 2005-04-16 00:13:17Z mike $" +// +// Forms emulation header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef __FORMS_H__ +#define __FORMS_H__ + +#include "Fl.H" +#include "Fl_Group.H" +#include "Fl_Window.H" +#include "fl_draw.H" + +typedef Fl_Widget FL_OBJECT; +typedef Fl_Window FL_FORM; + +//////////////////////////////////////////////////////////////// +// Random constants & symbols defined by forms.h file: + +#ifndef NULL +#define NULL 0 +#endif +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif + +#define FL_ON 1 +#define FL_OK 1 +#define FL_VALID 1 +#define FL_PREEMPT 1 +#define FL_AUTO 2 +#define FL_WHEN_NEEDED FL_AUTO +#define FL_OFF 0 +#define FL_NONE 0 +#define FL_CANCEL 0 +#define FL_INVALID 0 +#define FL_IGNORE -1 +#define FL_CLOSE -2 + +#define FL_LCOL FL_BLACK +#define FL_COL1 FL_GRAY +#define FL_MCOL FL_LIGHT1 +#define FL_LEFT_BCOL FL_LIGHT3 // 53 is better match +#define FL_TOP_BCOL FL_LIGHT2 // 51 +#define FL_BOTTOM_BCOL FL_DARK2 // 40 +#define FL_RIGHT_BCOL FL_DARK3 // 36 +#define FL_INACTIVE FL_INACTIVE_COLOR +#define FL_INACTIVE_COL FL_INACTIVE_COLOR +#define FL_FREE_COL1 FL_FREE_COLOR +#define FL_FREE_COL2 ((Fl_Color)(FL_FREE_COLOR+1)) +#define FL_FREE_COL3 ((Fl_Color)(FL_FREE_COLOR+2)) +#define FL_FREE_COL4 ((Fl_Color)(FL_FREE_COLOR+3)) +#define FL_FREE_COL5 ((Fl_Color)(FL_FREE_COLOR+4)) +#define FL_FREE_COL6 ((Fl_Color)(FL_FREE_COLOR+5)) +#define FL_FREE_COL7 ((Fl_Color)(FL_FREE_COLOR+6)) +#define FL_FREE_COL8 ((Fl_Color)(FL_FREE_COLOR+7)) +#define FL_FREE_COL9 ((Fl_Color)(FL_FREE_COLOR+8)) +#define FL_FREE_COL10 ((Fl_Color)(FL_FREE_COLOR+9)) +#define FL_FREE_COL11 ((Fl_Color)(FL_FREE_COLOR+10)) +#define FL_FREE_COL12 ((Fl_Color)(FL_FREE_COLOR+11)) +#define FL_FREE_COL13 ((Fl_Color)(FL_FREE_COLOR+12)) +#define FL_FREE_COL14 ((Fl_Color)(FL_FREE_COLOR+13)) +#define FL_FREE_COL15 ((Fl_Color)(FL_FREE_COLOR+14)) +#define FL_FREE_COL16 ((Fl_Color)(FL_FREE_COLOR+15)) +#define FL_TOMATO ((Fl_Color)(131)) +#define FL_INDIANRED ((Fl_Color)(164)) +#define FL_SLATEBLUE ((Fl_Color)(195)) +#define FL_DARKGOLD ((Fl_Color)(84)) +#define FL_PALEGREEN ((Fl_Color)(157)) +#define FL_ORCHID ((Fl_Color)(203)) +#define FL_DARKCYAN ((Fl_Color)(189)) +#define FL_DARKTOMATO ((Fl_Color)(113)) +#define FL_WHEAT ((Fl_Color)(174)) + +#define FL_ALIGN_BESIDE FL_ALIGN_INSIDE + +#define FL_PUP_TOGGLE 2 // FL_MENU_TOGGLE +#define FL_PUP_INACTIVE 1 // FL_MENU_INACTIVE +#define FL_NO_FRAME FL_NO_BOX +#define FL_ROUNDED3D_UPBOX FL_ROUND_UP_BOX +#define FL_ROUNDED3D_DOWNBOX FL_ROUND_DOWN_BOX +#define FL_OVAL3D_UPBOX FL_ROUND_UP_BOX +#define FL_OVAL3D_DOWNBOX FL_ROUND_DOWN_BOX + +#define FL_MBUTTON1 1 +#define FL_LEFTMOUSE 1 +#define FL_MBUTTON2 2 +#define FL_MIDDLEMOUSE 2 +#define FL_MBUTTON3 3 +#define FL_RIGHTMOUSE 3 +#define FL_MBUTTON4 4 +#define FL_MBUTTON5 5 + +#define FL_INVALID_STYLE 255 +#define FL_NORMAL_STYLE FL_HELVETICA +#define FL_BOLD_STYLE FL_HELVETICA_BOLD +#define FL_ITALIC_STYLE FL_HELVETICA_ITALIC +#define FL_BOLDITALIC_STYLE FL_HELVETICA_BOLD_ITALIC +#define FL_FIXED_STYLE FL_COURIER +#define FL_FIXEDBOLD_STYLE FL_COURIER_BOLD +#define FL_FIXEDITALIC_STYLE FL_COURIER_ITALIC +#define FL_FIXEDBOLDITALIC_STYLE FL_COURIER_BOLD_ITALIC +#define FL_TIMES_STYLE FL_TIMES +#define FL_TIMESBOLD_STYLE FL_TIMES_BOLD +#define FL_TIMESITALIC_STYLE FL_TIMES_ITALIC +#define FL_TIMESBOLDITALIC_STYLE FL_TIMES_BOLD_ITALIC + +// hacks to change the labeltype() when passed to fl_set_object_lstyle(): +#define FL_SHADOW_STYLE (FL_SHADOW_LABEL<<8) +#define FL_ENGRAVED_STYLE (FL_ENGRAVED_LABEL<<8) +#define FL_EMBOSSED_STYLE (FL_EMBOSSED_LABEL<<0) + +// size values are different from XForms, match older Forms: +#define FL_TINY_SIZE 8 +#define FL_SMALL_SIZE 11 // 10 +//#define FL_NORMAL_SIZE 14 // 12 +#define FL_MEDIUM_SIZE 18 // 14 +#define FL_LARGE_SIZE 24 // 18 +#define FL_HUGE_SIZE 32 // 24 +#define FL_DEFAULT_SIZE FL_SMALL_SIZE +#define FL_TINY_FONT FL_TINY_SIZE +#define FL_SMALL_FONT FL_SMALL_SIZE +#define FL_NORMAL_FONT FL_NORMAL_SIZE +#define FL_MEDIUM_FONT FL_MEDIUM_SIZE +#define FL_LARGE_FONT FL_LARGE_SIZE +#define FL_HUGE_FONT FL_HUGE_SIZE +#define FL_NORMAL_FONT1 FL_SMALL_FONT +#define FL_NORMAL_FONT2 FL_NORMAL_FONT +#define FL_DEFAULT_FONT FL_SMALL_FONT + +#define FL_RETURN_END_CHANGED FL_WHEN_RELEASE +#define FL_RETURN_CHANGED FL_WHEN_CHANGED +#define FL_RETURN_END FL_WHEN_RELEASE_ALWAYS +#define FL_RETURN_ALWAYS (FL_WHEN_CHANGED|FL_WHEN_NOT_CHANGED) + +#define FL_BOUND_WIDTH 3 + +typedef int FL_Coord; +typedef int FL_COLOR; + +//////////////////////////////////////////////////////////////// +// fltk interaction: + +#define FL_CMD_OPT void +extern FL_EXPORT void fl_initialize(int*, char*[], const char*, FL_CMD_OPT*, int); +inline void fl_finish() {} + +typedef void (*FL_IO_CALLBACK) (int, void*); +inline void fl_add_io_callback(int fd, short w, FL_IO_CALLBACK cb, void* v) { + Fl::add_fd(fd,w,cb,v);} +inline void fl_remove_io_callback(int fd, short, FL_IO_CALLBACK) { + Fl::remove_fd(fd);} // removes all the callbacks! + +// type of callback is different and no "id" number is returned: +inline void fl_add_timeout(long msec, void (*cb)(void*), void* v) { + Fl::add_timeout(msec*.001, cb, v);} +inline void fl_remove_timeout(int) {} + +// type of callback is different! +inline void fl_set_idle_callback(void (*cb)()) {Fl::set_idle(cb);} + +FL_EXPORT Fl_Widget* fl_do_forms(void); +FL_EXPORT Fl_Widget* fl_check_forms(); +inline Fl_Widget* fl_do_only_forms(void) {return fl_do_forms();} +inline Fl_Widget* fl_check_only_forms(void) {return fl_check_forms();} + +// because of new redraw behavior, these are no-ops: +inline void fl_freeze_object(Fl_Widget*) {} +inline void fl_unfreeze_object(Fl_Widget*) {} +inline void fl_freeze_form(Fl_Window*) {} +inline void fl_unfreeze_form(Fl_Window*) {} +inline void fl_freeze_all_forms() {} +inline void fl_unfreeze_all_forms() {} + +inline void fl_set_focus_object(Fl_Window*, Fl_Widget* o) {Fl::focus(o);} +inline void fl_reset_focus_object(Fl_Widget* o) {Fl::focus(o);} +#define fl_set_object_focus fl_set_focus_object + +// void fl_set_form_atclose(Fl_Window*w,int (*cb)(Fl_Window*,void*),void* v) +// void fl_set_atclose(int (*cb)(Fl_Window*,void*),void*) +// fl_set_form_atactivate/atdeactivate not implemented! + +//////////////////////////////////////////////////////////////// +// Fl_Widget: + +inline void fl_set_object_boxtype(Fl_Widget* o, Fl_Boxtype a) {o->box(a);} +inline void fl_set_object_lsize(Fl_Widget* o,int s) {o->labelsize(s);} +inline void fl_set_object_lstyle(Fl_Widget* o,int a) { + o->labelfont((uchar)a); o->labeltype((Fl_Labeltype)(a>>8));} +inline void fl_set_object_lcol(Fl_Widget* o, unsigned a) {o->labelcolor(a);} +#define fl_set_object_lcolor fl_set_object_lcol +inline void fl_set_object_lalign(Fl_Widget* o, Fl_Align a) {o->align(a);} +#define fl_set_object_align fl_set_object_lalign +inline void fl_set_object_color(Fl_Widget* o,unsigned a,unsigned b) {o->color(a,b);} +inline void fl_set_object_label(Fl_Widget* o, const char* a) {o->label(a); o->redraw();} +inline void fl_set_object_position(Fl_Widget*o,int x,int y) {o->position(x,y);} +inline void fl_set_object_size(Fl_Widget* o, int w, int h) {o->size(w,h);} +inline void fl_set_object_geometry(Fl_Widget* o,int x,int y,int w,int h) {o->resize(x,y,w,h);} + +inline void fl_get_object_geometry(Fl_Widget* o,int*x,int*y,int*w,int*h) { + *x = o->x(); *y = o->y(); *w = o->w(); *h = o->h();} +inline void fl_get_object_position(Fl_Widget* o,int*x,int*y) { + *x = o->x(); *y = o->y();} + +typedef void (*Forms_CB)(Fl_Widget*, long); +inline void fl_set_object_callback(Fl_Widget*o,Forms_CB c,long a) {o->callback(c,a);} +#define fl_set_call_back fl_set_object_callback +inline void fl_call_object_callback(Fl_Widget* o) {o->do_callback();} +inline void fl_trigger_object(Fl_Widget* o) {o->do_callback();} +inline void fl_set_object_return(Fl_Widget* o, int v) { + o->when((Fl_When)(v|FL_WHEN_RELEASE));} + +inline void fl_redraw_object(Fl_Widget* o) {o->redraw();} +inline void fl_show_object(Fl_Widget* o) {o->show();} +inline void fl_hide_object(Fl_Widget* o) {o->hide();} +inline void fl_free_object(Fl_Widget* x) {delete x;} +inline void fl_delete_object(Fl_Widget* o) {((Fl_Group*)(o->parent()))->remove(*o);} +inline void fl_activate_object(Fl_Widget* o) {o->activate();} +inline void fl_deactivate_object(Fl_Widget* o) {o->deactivate();} + +inline void fl_add_object(Fl_Window* f, Fl_Widget* x) {f->add(x);} +inline void fl_insert_object(Fl_Widget* o, Fl_Widget* b) { + ((Fl_Group*)(b->parent()))->insert(*o,b);} + +inline Fl_Window* FL_ObjWin(Fl_Widget* o) {return o->window();} + +//////////////////////////////////////////////////////////////// +// things that appered in the demos a lot that I don't emulate, but +// I did not want to edit out of all the demos... + +inline int fl_get_border_width() {return 3;} +inline void fl_set_border_width(int) {} +inline void fl_set_object_dblbuffer(Fl_Widget*, int) {} +inline void fl_set_form_dblbuffer(Fl_Window*, int) {} + +//////////////////////////////////////////////////////////////// +// Fl_Window: + +inline void fl_free_form(Fl_Window* x) {delete x;} +inline void fl_redraw_form(Fl_Window* f) {f->redraw();} + +inline Fl_Window* fl_bgn_form(Fl_Boxtype b,int w,int h) { + Fl_Window* g = new Fl_Window(w,h,0); + g->box(b); + return g; +} +FL_EXPORT void fl_end_form(); +inline void fl_addto_form(Fl_Window* f) {f->begin();} +inline Fl_Group* fl_bgn_group() {return new Fl_Group(0,0,0,0,0);} +inline void fl_end_group() {Fl_Group::current()->forms_end();} +inline void fl_addto_group(Fl_Widget* o) {((Fl_Group* )o)->begin();} +#define resizebox _ddfdesign_kludge() + +inline void fl_scale_form(Fl_Window* f, double x, double y) { + f->resizable(f); f->size(int(f->w()*x),int(f->h()*y));} +inline void fl_set_form_position(Fl_Window* f,int x,int y) {f->position(x,y);} +inline void fl_set_form_size(Fl_Window* f, int w, int h) {f->size(w,h);} +inline void fl_set_form_geometry(Fl_Window* f,int x,int y,int w,int h) { + f->resize(x,y,w,h);} +#define fl_set_initial_placement fl_set_form_geometry +inline void fl_adjust_form_size(Fl_Window*) {} + +FL_EXPORT void fl_show_form(Fl_Window* f,int p,int b,const char* n); +enum { // "p" argument values: + FL_PLACE_FREE = 0, // make resizable + FL_PLACE_MOUSE = 1, // mouse centered on form + FL_PLACE_CENTER = 2, // center of the screen + FL_PLACE_POSITION = 4,// fixed position, resizable + FL_PLACE_SIZE = 8, // fixed size, normal fltk behavior + FL_PLACE_GEOMETRY =16,// fixed size and position + FL_PLACE_ASPECT = 32, // keep aspect ratio (ignored) + FL_PLACE_FULLSCREEN=64,// fill screen + FL_PLACE_HOTSPOT = 128,// enables hotspot + FL_PLACE_ICONIC = 256,// iconic (ignored) + FL_FREE_SIZE=(1<<14), // force resizable + FL_FIX_SIZE =(1<<15) // force off resizable +}; +#define FL_PLACE_FREE_CENTER (FL_PLACE_CENTER|FL_FREE_SIZE) +#define FL_PLACE_CENTERFREE (FL_PLACE_CENTER|FL_FREE_SIZE) +enum { // "b" arguement values: + FL_NOBORDER = 0, + FL_FULLBORDER, + FL_TRANSIENT +//FL_MODAL = (1<<8) // not implemented yet in Forms +}; +inline void fl_set_form_hotspot(Fl_Window* w,int x,int y) {w->hotspot(x,y);} +inline void fl_set_form_hotobject(Fl_Window* w, Fl_Widget* o) {w->hotspot(o);} +extern FL_EXPORT char fl_flip; // in forms.C +inline void fl_flip_yorigin() {fl_flip = 1;} + +#define fl_prepare_form_window fl_show_form +inline void fl_show_form_window(Fl_Window*) {} + +inline void fl_raise_form(Fl_Window* f) {f->show();} + +inline void fl_hide_form(Fl_Window* f) {f->hide();} +inline void fl_pop_form(Fl_Window* f) {f->show();} + +extern FL_EXPORT char fl_modal_next; // in forms.C +inline void fl_activate_all_forms() {} +inline void fl_deactivate_all_forms() {fl_modal_next = 1;} +inline void fl_deactivate_form(Fl_Window*w) {w->deactivate();} +inline void fl_activate_form(Fl_Window*w) {w->activate();} + +inline void fl_set_form_title(Fl_Window* f, const char* s) {f->label(s);} +inline void fl_title_form(Fl_Window* f, const char* s) {f->label(s);} + +typedef void (*Forms_FormCB)(Fl_Widget*); +inline void fl_set_form_callback(Fl_Window* f,Forms_FormCB c) {f->callback(c);} +#define fl_set_form_call_back fl_set_form_callback + +inline void fl_init() {} +FL_EXPORT void fl_set_graphics_mode(int,int); + +inline int fl_form_is_visible(Fl_Window* f) {return f->visible();} + +inline int fl_mouse_button() {return Fl::event_button();} +#define fl_mousebutton fl_mouse_button + +#define fl_free free +#define fl_malloc malloc +#define fl_calloc calloc +#define fl_realloc realloc + +//////////////////////////////////////////////////////////////// +// Drawing functions. Only usable inside an Fl_Free object? + +inline void fl_drw_box(Fl_Boxtype b,int x,int y,int w,int h,Fl_Color bgc,int=3) { + fl_draw_box(b,x,y,w,h,bgc);} +inline void fl_drw_frame(Fl_Boxtype b,int x,int y,int w,int h,Fl_Color bgc,int=3) { + fl_draw_box(b,x,y,w,h,bgc);} + +inline void fl_drw_text(Fl_Align align, int x, int y, int w, int h, + Fl_Color fgcolor, int size, Fl_Font style, + const char* s) { + fl_font(style,size); + fl_color(fgcolor); + fl_draw(s,x,y,w,h,align); +} + +// this does not work except for CENTER... +inline void fl_drw_text_beside(Fl_Align align, int x, int y, int w, int h, + Fl_Color fgcolor, int size, Fl_Font style, + const char* s) { + fl_font(style,size); + fl_color(fgcolor); + fl_draw(s,x,y,w,h,align); +} + +inline void fl_set_font_name(Fl_Font n,const char* s) {Fl::set_font(n,s);} + +inline void fl_mapcolor(Fl_Color c, uchar r, uchar g, uchar b) {Fl::set_color(c,r,g,b);} + +#define fl_set_clipping(x,y,w,h) fl_clip(x,y,w,h) +#define fl_unset_clipping() fl_pop_clip() + +//////////////////////////////////////////////////////////////// +// Forms classes: + +inline Fl_Widget* fl_add_new(Fl_Widget* p) {return p;} +inline Fl_Widget* fl_add_new(uchar t,Fl_Widget* p) {p->type(t); return p;} + +#define forms_constructor(type,name) \ +inline type* name(uchar t,int x,int y,int w,int h,const char* l) { \ + return (type*)(fl_add_new(t, new type(x,y,w,h,l)));} +#define forms_constructort(type,name) \ +inline type* name(uchar t,int x,int y,int w,int h,const char* l) { \ + return (type*)(fl_add_new(new type(t,x,y,w,h,l)));} +#define forms_constructorb(type,name) \ +inline type* name(Fl_Boxtype t,int x,int y,int w,int h,const char* l) { \ + return (type*)(fl_add_new(new type(t,x,y,w,h,l)));} + +#include "Fl_FormsBitmap.H" +#define FL_NORMAL_BITMAP FL_NO_BOX +forms_constructorb(Fl_FormsBitmap, fl_add_bitmap) +inline void fl_set_bitmap_data(Fl_Widget* o, int w, int h, const uchar* b) { + ((Fl_FormsBitmap*)o)->set(w,h,b); +} + +#include "Fl_FormsPixmap.H" +#define FL_NORMAL_PIXMAP FL_NO_BOX +forms_constructorb(Fl_FormsPixmap, fl_add_pixmap) +inline void fl_set_pixmap_data(Fl_Widget* o, char*const* b) { + ((Fl_FormsPixmap*)o)->set(b); +} +//inline void fl_set_pixmap_file(Fl_Widget*, const char*); +inline void fl_set_pixmap_align(Fl_Widget* o,Fl_Align a,int,int) {o->align(a);} +//inline void fl_set_pixmap_colorcloseness(int, int, int); + +#include "Fl_Box.H" +forms_constructorb(Fl_Box, fl_add_box) + +#include "Fl_Browser.H" +forms_constructor(Fl_Browser, fl_add_browser) + +inline void fl_clear_browser(Fl_Widget* o) { + ((Fl_Browser*)o)->clear();} +inline void fl_add_browser_line(Fl_Widget* o, const char* s) { + ((Fl_Browser*)o)->add(s);} +inline void fl_addto_browser(Fl_Widget* o, const char* s) { + ((Fl_Browser*)o)->add(s);} /* should also scroll to bottom */ +//inline void fl_addto_browser_chars(Fl_Widget*, const char*) +//#define fl_append_browser fl_addto_browser_chars +inline void fl_insert_browser_line(Fl_Widget* o, int n, const char* s) { + ((Fl_Browser*)o)->insert(n,s);} +inline void fl_delete_browser_line(Fl_Widget* o, int n) { + ((Fl_Browser*)o)->remove(n);} +inline void fl_replace_browser_line(Fl_Widget* o, int n, const char* s) { + ((Fl_Browser*)o)->replace(n,s);} +inline char* fl_get_browser_line(Fl_Widget* o, int n) { + return (char*)(((Fl_Browser*)o)->text(n));} +inline int fl_load_browser(Fl_Widget* o, const char* f) { + return ((Fl_Browser*)o)->load(f);} +inline void fl_select_browser_line(Fl_Widget* o, int n) { + ((Fl_Browser*)o)->select(n,1);} +inline void fl_deselect_browser_line(Fl_Widget* o, int n) { + ((Fl_Browser*)o)->select(n,0);} +inline void fl_deselect_browser(Fl_Widget* o) { + ((Fl_Browser*)o)->deselect();} +inline int fl_isselected_browser_line(Fl_Widget* o, int n) { + return ((Fl_Browser*)o)->selected(n);} +inline int fl_get_browser_topline(Fl_Widget* o) { + return ((Fl_Browser*)o)->topline();} +inline int fl_get_browser(Fl_Widget* o) { + return ((Fl_Browser*)o)->value();} +inline int fl_get_browser_maxline(Fl_Widget* o) { + return ((Fl_Browser*)o)->size();} +//linline int fl_get_browser_screenlines(Fl_Widget*); +inline void fl_set_browser_topline(Fl_Widget* o, int n) { + ((Fl_Browser*)o)->topline(n);} +inline void fl_set_browser_fontsize(Fl_Widget* o, int s) { + ((Fl_Browser*)o)->textsize(s);} +inline void fl_set_browser_fontstyle(Fl_Widget* o, Fl_Font s) { + ((Fl_Browser*)o)->textfont(s);} +inline void fl_set_browser_specialkey(Fl_Widget* o, char c) { + ((Fl_Browser*)o)->format_char(c);} +//inline void fl_set_browser_vscrollbar(Fl_Widget*, int); +//inline void fl_set_browser_hscrollbar(Fl_Widget*, int); +//inline void fl_set_browser_leftslider(Fl_Widget*, int); +//#define fl_set_browser_leftscrollbar fl_set_browser_leftslider +//inline void fl_set_browser_line_selectable(Fl_Widget*, int, int); +//inline void fl_get_browser_dimension(Fl_Widget*,int*,int*,int*,int*); +//inline void fl_set_browser_dblclick_callback(Fl_Widget*,FL_CALLBACKPTR,long); +//inline void fl_set_browser_xoffset(Fl_Widget*, FL_Coord); +//inline void fl_set_browser_scrollbarsize(Fl_Widget*, int, int); +inline void fl_setdisplayed_browser_line(Fl_Widget* o, int n, int i) { + ((Fl_Browser*)o)->display(n,i);} +inline int fl_isdisplayed_browser_line(Fl_Widget* o, int n) { + return ((Fl_Browser*)o)->displayed(n);} + +#include "Fl_Button.H" + +#define FL_NORMAL_BUTTON 0 +#define FL_TOUCH_BUTTON 4 +#define FL_INOUT_BUTTON 5 +#define FL_RETURN_BUTTON 6 +#define FL_HIDDEN_RET_BUTTON 7 +#define FL_PUSH_BUTTON FL_TOGGLE_BUTTON +#define FL_MENU_BUTTON 9 + +FL_EXPORT Fl_Button* fl_add_button(uchar t,int x,int y,int w,int h,const char* l); +inline int fl_get_button(Fl_Widget* b) {return ((Fl_Button*)b)->value();} +inline void fl_set_button(Fl_Widget* b, int v) {((Fl_Button*)b)->value(v);} +inline int fl_get_button_numb(Fl_Widget*) {return Fl::event_button();} +inline void fl_set_button_shortcut(Fl_Widget* b, const char* s,int=0) { + ((Fl_Button*)b)->shortcut(s);} +//#define fl_set_object_shortcut(b,s) fl_set_button_shortcut(b,s) + +#include "Fl_Light_Button.H" +forms_constructor(Fl_Light_Button, fl_add_lightbutton) + +#include "Fl_Round_Button.H" +forms_constructor(Fl_Round_Button, fl_add_roundbutton) +forms_constructor(Fl_Round_Button, fl_add_round3dbutton) + +#include "Fl_Check_Button.H" +forms_constructor(Fl_Check_Button, fl_add_checkbutton) + +inline Fl_Widget* fl_add_bitmapbutton(int t,int x,int y,int w,int h,const char* l) {Fl_Widget* o = fl_add_button(t,x,y,w,h,l); return o;} +inline void fl_set_bitmapbutton_data(Fl_Widget* o,int a,int b,uchar* c) { + (new Fl_Bitmap(c,a,b))->label(o);} // does not delete old Fl_Bitmap! + +inline Fl_Widget* fl_add_pixmapbutton(int t,int x,int y,int w,int h,const char* l) {Fl_Widget* o = fl_add_button(t,x,y,w,h,l); return o;} +inline void fl_set_pixmapbutton_data(Fl_Widget* o, const char*const* c) { + (new Fl_Pixmap(c))->label(o);} // does not delete old Fl_Pixmap! + +// Fl_Canvas object not yet implemented! + +#include "Fl_Chart.H" + +forms_constructor(Fl_Chart, fl_add_chart) +inline void fl_clear_chart(Fl_Widget* o) { + ((Fl_Chart*)o)->clear();} +inline void fl_add_chart_value(Fl_Widget* o,double v,const char* s,uchar c){ + ((Fl_Chart*)o)->add(v,s,c);} +inline void fl_insert_chart_value(Fl_Widget* o, int i, double v, const char* s, uchar c) { + ((Fl_Chart*)o)->insert(i,v,s,c);} +inline void fl_replace_chart_value(Fl_Widget* o, int i, double v, const char* s, uchar c) { + ((Fl_Chart*)o)->replace(i,v,s,c);} +inline void fl_set_chart_bounds(Fl_Widget* o, double a, double b) { + ((Fl_Chart*)o)->bounds(a,b);} +inline void fl_set_chart_maxnumb(Fl_Widget* o, int v) { + ((Fl_Chart*)o)->maxsize(v);} +inline void fl_set_chart_autosize(Fl_Widget* o, int v) { + ((Fl_Chart*)o)->autosize(v);} +inline void fl_set_chart_lstyle(Fl_Widget* o, Fl_Font v) { + ((Fl_Chart*)o)->textfont(v);} +inline void fl_set_chart_lsize(Fl_Widget* o, int v) { + ((Fl_Chart*)o)->textsize(v);} +inline void fl_set_chart_lcolor(Fl_Widget* o, unsigned v) { + ((Fl_Chart*)o)->textcolor(v);} +#define fl_set_chart_lcol fl_set_chart_lcolor + +#include "Fl_Choice.H" + +#define FL_NORMAL_CHOICE 0 +#define FL_NORMAL_CHOICE2 0 +#define FL_DROPLIST_CHOICE 0 + +forms_constructor(Fl_Choice, fl_add_choice) +inline void fl_clear_choice(Fl_Widget* o) { + ((Fl_Choice*)o)->clear();} +inline void fl_addto_choice(Fl_Widget* o, const char* s) { + ((Fl_Choice*)o)->add(s);} +inline void fl_replace_choice(Fl_Widget* o, int i, const char* s) { + ((Fl_Choice*)o)->replace(i-1,s);} +inline void fl_delete_choice(Fl_Widget* o, int i) { + ((Fl_Choice*)o)->remove(i-1);} +inline void fl_set_choice(Fl_Widget* o, int i) { + ((Fl_Choice*)o)->value(i-1);} +// inline void fl_set_choice_text(Fl_Widget*, const char*); +inline int fl_get_choice(Fl_Widget* o) { + return ((Fl_Choice*)o)->value()+1;} +// inline const char* fl_get_choice_item_text(Fl_Widget*, int); +// inline int fl_get_choice_maxitems(Fl_Widget*); +inline const char* fl_get_choice_text(Fl_Widget* o) { + return ((Fl_Choice*)o)->text();} +inline void fl_set_choice_fontsize(Fl_Widget* o, int x) { + ((Fl_Choice*)o)->textsize(x);} +inline void fl_set_choice_fontstyle(Fl_Widget* o, Fl_Font x) { + ((Fl_Choice*)o)->textfont(x);} +// inline void fl_set_choice_item_mode(Fl_Widget*, int, unsigned); +// inline void fl_set_choice_item_shortcut(Fl_Widget*, int, const char*); + +#include "Fl_Clock.H" +forms_constructort(Fl_Clock, fl_add_clock) +inline void fl_get_clock(Fl_Widget* o, int* h, int* m, int* s) { + *h = ((Fl_Clock*)o)->hour(); + *m = ((Fl_Clock*)o)->minute(); + *s = ((Fl_Clock*)o)->second(); +} + +#include "Fl_Counter.H" +forms_constructor(Fl_Counter, fl_add_counter) +inline void fl_set_counter_value(Fl_Widget* o, double v) { + ((Fl_Counter*)o)->value(v);} +inline void fl_set_counter_bounds(Fl_Widget* o, double a, double b) { + ((Fl_Counter*)o)->bounds(a,b);} +inline void fl_set_counter_step(Fl_Widget* o, double a, double b) { + ((Fl_Counter*)o)->step(a,b);} +inline void fl_set_counter_precision(Fl_Widget* o, int v) { + ((Fl_Counter*)o)->precision(v);} +inline void fl_set_counter_return(Fl_Widget* o, int v) { + ((Fl_Counter*)o)->when((Fl_When)(v|FL_WHEN_RELEASE));} +inline double fl_get_counter_value(Fl_Widget* o) { + return ((Fl_Counter*)o)->value();} +inline void fl_get_counter_bounds(Fl_Widget* o, float* a, float* b) { + *a = float(((Fl_Counter*)o)->minimum()); + *b = float(((Fl_Counter*)o)->maximum()); +} +//inline void fl_set_counter_filter(Fl_Widget*,const char* (*)(Fl_Widget*,double,int)); + +// Cursor stuff cannot be emulated because it uses X stuff +inline void fl_set_cursor(Fl_Window* w, Fl_Cursor c) {w->cursor(c);} +#define FL_INVISIBLE_CURSOR FL_CURSOR_NONE +#define FL_DEFAULT_CURSOR FL_CURSOR_DEFAULT + +#include "Fl_Dial.H" + +#define FL_DIAL_COL1 FL_GRAY +#define FL_DIAL_COL2 37 + +forms_constructor(Fl_Dial, fl_add_dial) +inline void fl_set_dial_value(Fl_Widget* o, double v) { + ((Fl_Dial*)o)->value(v);} +inline double fl_get_dial_value(Fl_Widget* o) { + return ((Fl_Dial*)o)->value();} +inline void fl_set_dial_bounds(Fl_Widget* o, double a, double b) { + ((Fl_Dial*)o)->bounds(a, b);} +inline void fl_get_dial_bounds(Fl_Widget* o, float* a, float* b) { + *a = float(((Fl_Dial*)o)->minimum()); + *b = float(((Fl_Dial*)o)->maximum()); +} +inline void fl_set_dial_return(Fl_Widget* o, int i) { + ((Fl_Dial*)o)->when((Fl_When)(i|FL_WHEN_RELEASE));} +inline void fl_set_dial_angles(Fl_Widget* o, int a, int b) { + ((Fl_Dial*)o)->angles((short)a, (short)b);} +//inline void fl_set_dial_cross(Fl_Widget* o, int); +// inline void fl_set_dial_direction(Fl_Widget* o, uchar d) { +// ((Fl_Dial*)o)->direction(d);} +inline void fl_set_dial_step(Fl_Widget* o, double v) { + ((Fl_Dial*)o)->step(v);} + +// Frames: + +inline Fl_Widget* fl_add_frame(Fl_Boxtype i,int x,int y,int w,int h,const char* l) { + return fl_add_box(i,x-3,y-3,w+6,h+6,l);} + +// labelframe nyi +inline Fl_Widget* fl_add_labelframe(Fl_Boxtype i,int x,int y,int w,int h,const char* l) { + Fl_Widget* o = fl_add_box(i,x-3,y-3,w+6,h+6,l); + o->align(FL_ALIGN_TOP_LEFT); + return o; +} + +#include "Fl_Free.H" +inline Fl_Free* +fl_add_free(int t,double x,double y,double w,double h,const char* l, + FL_HANDLEPTR hdl) { + return (Fl_Free*)(fl_add_new( + new Fl_Free(t,int(x),int(y),int(w),int(h),l,hdl))); +} + +#include "fl_ask.H" +#include "fl_show_colormap.H" + +inline int fl_show_question(const char* c, int = 0) {return fl_choice("%s",fl_no,fl_yes,0L,c);} +FL_EXPORT void fl_show_message(const char *,const char *,const char *); +FL_EXPORT void fl_show_alert(const char *,const char *,const char *,int=0); +FL_EXPORT int fl_show_question(const char *,const char *,const char *); +inline const char *fl_show_input(const char *l,const char*d=0) {return fl_input(l,d);} +FL_EXPORT /*const*/ char *fl_show_simple_input(const char *label, const char *deflt = 0); +FL_EXPORT int fl_show_choice( + const char *m1, + const char *m2, + const char *m3, + int numb, + const char *b0, + const char *b1, + const char *b2); + +inline void fl_set_goodies_font(uchar a, uchar b) {fl_message_font(a,b);} +#define fl_show_messages fl_message +inline int fl_show_choices(const char* c,int n,const char* b1,const char* b2, + const char* b3, int) { + return fl_show_choice(0,c,0,n,b1,b2,b3); +} + +#include "filename.H" +#include "Fl_File_Chooser.H" +inline int do_matching(char* a, const char* b) {return fl_filename_match(a,b);} + +// Forms-compatable file chooser (implementation in fselect.C): +FL_EXPORT char* fl_show_file_selector(const char* message,const char* dir, + const char* pat,const char* fname); +FL_EXPORT char* fl_get_directory(); +FL_EXPORT char* fl_get_pattern(); +FL_EXPORT char* fl_get_filename(); + +#include "Fl_Input.H" +forms_constructor(Fl_Input, fl_add_input) +inline void fl_set_input(Fl_Widget* o, const char* v) { + ((Fl_Input*)o)->value(v);} +inline void fl_set_input_return(Fl_Widget* o, int x) { + ((Fl_Input*)o)->when((Fl_When)(x | FL_WHEN_RELEASE));} +inline void fl_set_input_color(Fl_Widget* o, unsigned a, unsigned b) { + ((Fl_Input*)o)->textcolor(a); + ((Fl_Input*)o)->cursor_color(b); +} +// inline void fl_set_input_scroll(Fl_Widget*, int); +inline void fl_set_input_cursorpos(Fl_Widget* o, int x, int /*y*/) { + ((Fl_Input*)o)->position(x);} +// inline void fl_set_input_selected(Fl_Widget*, int); +// inline void fl_set_input_selected_range(Fl_Widget*, int, int); +// inline void fl_set_input_maxchars(Fl_Widget*, int); +// inline void fl_set_input_format(Fl_Widget*, int, int); +// inline void fl_set_input_hscrollbar(Fl_Widget*, int); +// inline void fl_set_input_vscrollbar(Fl_Widget*, int); +// inline void fl_set_input_xoffset(Fl_Widget*, int); +// inline void fl_set_input_topline(Fl_Widget*, int); +// inline void fl_set_input_scrollbarsize(Fl_Widget*, int, int); +// inline int fl_get_input_topline(Fl_Widget*); +// inline int fl_get_input_screenlines(Fl_Widget*); +inline int fl_get_input_cursorpos(Fl_Widget* o, int*x, int*y) { + *x = ((Fl_Input*)o)->position(); *y = 0; return *x;} +// inline int fl_get_input_numberoflines(Fl_Widget*); +// inline void fl_get_input_format(Fl_Widget*, int*, int*); +inline const char* fl_get_input(Fl_Widget* o) {return ((Fl_Input*)o)->value();} + +#include "Fl_Menu_Button.H" + +// types are not implemented, they all act like FL_PUSH_MENU: +#define FL_TOUCH_MENU 0 +#define FL_PUSH_MENU 1 +#define FL_PULLDOWN_MENU 2 +forms_constructor(Fl_Menu_Button, fl_add_menu) + +inline void fl_clear_menu(Fl_Widget* o) { + ((Fl_Menu_Button*)o)->clear();} +inline void fl_set_menu(Fl_Widget* o, const char* s) { + ((Fl_Menu_Button*)o)->clear(); ((Fl_Menu_Button*)o)->add(s);} +inline void fl_addto_menu(Fl_Widget* o, const char* s) { + ((Fl_Menu_Button*)o)->add(s);} +inline void fl_replace_menu_item(Fl_Widget* o, int i, const char* s) { + ((Fl_Menu_Button*)o)->replace(i-1,s);} +inline void fl_delete_menu_item(Fl_Widget* o, int i) { + ((Fl_Menu_Button*)o)->remove(i-1);} +inline void fl_set_menu_item_shortcut(Fl_Widget* o, int i, const char* s) { + ((Fl_Menu_Button*)o)->shortcut(i-1,fl_old_shortcut(s));} +inline void fl_set_menu_item_mode(Fl_Widget* o, int i, long x) { + ((Fl_Menu_Button*)o)->mode(i-1,x);} +inline void fl_show_menu_symbol(Fl_Widget*, int ) { +/* ((Fl_Menu_Button*)o)->show_menu_symbol(i); */} +// inline void fl_set_menu_popup(Fl_Widget*, int); +inline int fl_get_menu(Fl_Widget* o) { + return ((Fl_Menu_Button*)o)->value()+1;} +inline const char* fl_get_menu_item_text(Fl_Widget* o, int i) { + return ((Fl_Menu_Button*)o)->text(i);} +inline int fl_get_menu_maxitems(Fl_Widget* o) { + return ((Fl_Menu_Button*)o)->size();} +inline int fl_get_menu_item_mode(Fl_Widget* o, int i) { + return ((Fl_Menu_Button*)o)->mode(i);} +inline const char* fl_get_menu_text(Fl_Widget* o) { + return ((Fl_Menu_Button*)o)->text();} + +#include "Fl_Positioner.H" +#define FL_NORMAL_POSITIONER 0 +forms_constructor(Fl_Positioner, fl_add_positioner) +inline void fl_set_positioner_xvalue(Fl_Widget* o, double v) { + ((Fl_Positioner*)o)->xvalue(v);} +inline double fl_get_positioner_xvalue(Fl_Widget* o) { + return ((Fl_Positioner*)o)->xvalue();} +inline void fl_set_positioner_xbounds(Fl_Widget* o, double a, double b) { + ((Fl_Positioner*)o)->xbounds(a,b);} +inline void fl_get_positioner_xbounds(Fl_Widget* o, float* a, float* b) { + *a = float(((Fl_Positioner*)o)->xminimum()); + *b = float(((Fl_Positioner*)o)->xmaximum()); +} +inline void fl_set_positioner_yvalue(Fl_Widget* o, double v) { + ((Fl_Positioner*)o)->yvalue(v);} +inline double fl_get_positioner_yvalue(Fl_Widget* o) { + return ((Fl_Positioner*)o)->yvalue();} +inline void fl_set_positioner_ybounds(Fl_Widget* o, double a, double b) { + ((Fl_Positioner*)o)->ybounds(a,b);} +inline void fl_get_positioner_ybounds(Fl_Widget* o, float* a, float* b) { + *a = float(((Fl_Positioner*)o)->yminimum()); + *b = float(((Fl_Positioner*)o)->ymaximum()); +} +inline void fl_set_positioner_xstep(Fl_Widget* o, double v) { + ((Fl_Positioner*)o)->xstep(v);} +inline void fl_set_positioner_ystep(Fl_Widget* o, double v) { + ((Fl_Positioner*)o)->ystep(v);} +inline void fl_set_positioner_return(Fl_Widget* o, int v) { + ((Fl_Positioner*)o)->when((Fl_When)(v|FL_WHEN_RELEASE));} + +#include "Fl_Slider.H" + +#define FL_HOR_BROWSER_SLIDER FL_HOR_SLIDER +#define FL_VERT_BROWSER_SLIDER FL_VERT_SLIDER + +forms_constructort(Fl_Slider, fl_add_slider) +#define FL_SLIDER_COL1 FL_GRAY +inline void fl_set_slider_value(Fl_Widget* o, double v) { + ((Fl_Slider*)o)->value(v);} +inline double fl_get_slider_value(Fl_Widget* o) { + return ((Fl_Slider*)o)->value();} +inline void fl_set_slider_bounds(Fl_Widget* o, double a, double b) { + ((Fl_Slider*)o)->bounds(a, b);} +inline void fl_get_slider_bounds(Fl_Widget* o, float* a, float* b) { + *a = float(((Fl_Slider*)o)->minimum()); + *b = float(((Fl_Slider*)o)->maximum()); +} +inline void fl_set_slider_return(Fl_Widget* o, int i) { + ((Fl_Slider*)o)->when((Fl_When)(i|FL_WHEN_RELEASE));} +inline void fl_set_slider_step(Fl_Widget* o, double v) { + ((Fl_Slider*)o)->step(v);} +// inline void fl_set_slider_increment(Fl_Widget* o, double v, double); +inline void fl_set_slider_size(Fl_Widget* o, double v) { + ((Fl_Slider*)o)->slider_size(v);} + +#include "Fl_Value_Slider.H" +forms_constructor(Fl_Value_Slider, fl_add_valslider) + +inline void fl_set_slider_precision(Fl_Widget* o, int i) { + ((Fl_Value_Slider*)o)->precision(i);} +// filter function! + +// The forms text object was the same as an Fl_Box except it inverted the +// meaning of FL_ALIGN_INSIDE. Implementation in forms.cxx +class FL_EXPORT Fl_FormsText : public Fl_Widget { +protected: + void draw(); +public: + Fl_FormsText(Fl_Boxtype b, int X, int Y, int W, int H, const char* l=0) + : Fl_Widget(X,Y,W,H,l) {box(b); align(FL_ALIGN_LEFT);} +}; +#define FL_NORMAL_TEXT FL_NO_BOX +forms_constructorb(Fl_FormsText, fl_add_text) + +#include "Fl_Timer.H" +forms_constructort(Fl_Timer, fl_add_timer) +inline void fl_set_timer(Fl_Widget* o, double v) {((Fl_Timer*)o)->value(v);} +inline double fl_get_timer(Fl_Widget* o) {return ((Fl_Timer*)o)->value();} +inline void fl_suspend_timer(Fl_Widget* o) {((Fl_Timer*)o)->suspended(1);} +inline void fl_resume_timer(Fl_Widget* o) {((Fl_Timer*)o)->suspended(0);} +inline void fl_set_timer_countup(Fl_Widget* o,char d) {((Fl_Timer*)o)->direction(d);} +void fl_gettime(long* sec, long* usec); + +// Fl_XYPlot nyi + + +// stuff from DDForms: + +inline int fl_double_click() {return Fl::event_clicks();} +inline void fl_draw() {Fl::flush();} + +#endif /* define __FORMS_H__ */ + +// +// End of "$Id: forms.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/gl.h b/Utilities/FLTK/FL/gl.h new file mode 100644 index 0000000000..4bd40cd071 --- /dev/null +++ b/Utilities/FLTK/FL/gl.h @@ -0,0 +1,87 @@ +// +// "$Id$" +// +// OpenGL header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// You must include this instead of GL/gl.h to get the Microsoft +// APIENTRY stuff included (from <windows.h>) prior to the OpenGL +// header files. +// +// This file also provides "missing" OpenGL functions, and +// gl_start() and gl_finish() to allow OpenGL to be used in any window +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef FL_gl_H +# define FL_gl_H + +# include "Enumerations.H" // for color names +# ifdef WIN32 +# include <windows.h> +# endif +# ifndef APIENTRY +# if defined(__CYGWIN__) +# define APIENTRY __attribute__ ((__stdcall__)) +# else +# define APIENTRY +# endif +# endif + +# ifdef __APPLE__ +# include <OpenGL/gl.h> +# else +# include <GL/gl.h> +# endif + +FL_EXPORT void gl_start(); +FL_EXPORT void gl_finish(); + +FL_EXPORT void gl_color(Fl_Color); +inline void gl_color(int c) {gl_color((Fl_Color)c);} // back compatability + +FL_EXPORT void gl_rect(int x,int y,int w,int h); +inline void gl_rectf(int x,int y,int w,int h) {glRecti(x,y,x+w,y+h);} + +FL_EXPORT void gl_font(int fontid, int size); +FL_EXPORT int gl_height(); +FL_EXPORT int gl_descent(); +FL_EXPORT double gl_width(const char *); +FL_EXPORT double gl_width(const char *, int n); +FL_EXPORT double gl_width(uchar); + +FL_EXPORT void gl_draw(const char*); +FL_EXPORT void gl_draw(const char*, int n); +FL_EXPORT void gl_draw(const char*, int x, int y); +FL_EXPORT void gl_draw(const char*, float x, float y); +FL_EXPORT void gl_draw(const char*, int n, int x, int y); +FL_EXPORT void gl_draw(const char*, int n, float x, float y); +FL_EXPORT void gl_draw(const char*, int x, int y, int w, int h, Fl_Align); +FL_EXPORT void gl_measure(const char*, int& x, int& y); + +FL_EXPORT void gl_draw_image(const uchar *, int x,int y,int w,int h, int d=3, int ld=0); + +#endif // !FL_gl_H + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/FL/gl2opengl.h b/Utilities/FLTK/FL/gl2opengl.h new file mode 100644 index 0000000000..b89614e0fb --- /dev/null +++ b/Utilities/FLTK/FL/gl2opengl.h @@ -0,0 +1,35 @@ +/* gl.h + + GL to OpenGL translator. + If you include this, you might be able to port old GL programs. + There are also much better emulators available on the net. + +*/ + +#include <FL/gl.h> +#include "gl_draw.H" + +inline void clear() {glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);} +#define RGBcolor(r,g,b) glColor3ub(r,g,b) +#define bgnline() glBegin(GL_LINE_STRIP) +#define bgnpolygon() glBegin(GL_POLYGON) +#define bgnclosedline() glBegin(GL_LINE_LOOP) +#define endline() glEnd() +#define endpolygon() glEnd() +#define endclosedline() glEnd() +#define v2f(v) glVertex2fv(v) +#define v2s(v) glVertex2sv(v) +#define cmov(x,y,z) glRasterPos3f(x,y,z) +#define charstr(s) gl_draw(s) +#define fmprstr(s) gl_draw(s) +typedef float Matrix[4][4]; +inline void pushmatrix() {glPushMatrix();} +inline void popmatrix() {glPopMatrix();} +inline void multmatrix(Matrix m) {glMultMatrixf((float *)m);} +inline void color(int n) {glIndexi(n);} +inline void rect(int x,int y,int r,int t) {gl_rect(x,y,r-x,t-y);} +inline void rectf(int x,int y,int r,int t) {glRectf(x,y,r+1,t+1);} +inline void recti(int x,int y,int r,int t) {gl_rect(x,y,r-x,t-y);} +inline void rectfi(int x,int y,int r,int t) {glRecti(x,y,r+1,t+1);} +inline void rects(int x,int y,int r,int t) {gl_rect(x,y,r-x,t-y);} +inline void rectfs(int x,int y,int r,int t) {glRects(x,y,r+1,t+1);} diff --git a/Utilities/FLTK/FL/gl_draw.H b/Utilities/FLTK/FL/gl_draw.H new file mode 100644 index 0000000000..09c99d053a --- /dev/null +++ b/Utilities/FLTK/FL/gl_draw.H @@ -0,0 +1,35 @@ +// +// "$Id: gl_draw.H 4288 2005-04-16 00:13:17Z mike $" +// +// OpenGL header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include "gl.h" + +extern FL_EXPORT void gl_remove_displaylist_fonts(); + + +// +// End of "$Id: gl_draw.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/glut.H b/Utilities/FLTK/FL/glut.H new file mode 100644 index 0000000000..f05169585d --- /dev/null +++ b/Utilities/FLTK/FL/glut.H @@ -0,0 +1,476 @@ +// +// "$Id: glut.H 4288 2005-04-16 00:13:17Z mike $" +// +// GLUT emulation header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Emulation of GLUT using fltk. + +// GLUT is Copyright (c) Mark J. Kilgard, 1994, 1995, 1996: +// "This program is freely distributable without licensing fees and is +// provided without guarantee or warrantee expressed or implied. This +// program is -not- in the public domain." + +// Although I have copied the GLUT API, none of my code is based on +// any GLUT implementation details and is therefore covered by the LGPL. + +// FLTK does not include the GLUT drawing functions (such as +// glutWireTeapot()) or the stroke fonts but the declarations for the +// drawing functions are included here because otherwise there is no +// way to get them along with this. To use them you will have to +// link in the original GLUT library, put -lglut *after* -lfltk. + +// Commented out lines indicate parts of GLUT that are not emulated. + +#ifndef __glut_h__ +# define __glut_h__ + +# include "gl.h" +//# include <GL/glu.h> + +//////////////////////////////////////////////////////////////// +// GLUT is emulated using this window class and these static variables +// (plus several more static variables hidden in glut.C): + +# include "Fl.H" +# include "Fl_Gl_Window.H" + +class FL_EXPORT Fl_Glut_Window : public Fl_Gl_Window { + void _init(); + int mouse_down; +protected: + void draw(); + void draw_overlay(); + int handle(int); +public: // so the inline functions work + int number; + int menu[3]; + void make_current(); + void (*display)(); + void (*overlaydisplay)(); + void (*reshape)(int w, int h); + void (*keyboard)(uchar, int x, int y); + void (*mouse)(int b, int state, int x, int y); + void (*motion)(int x, int y); + void (*passivemotion)(int x, int y); + void (*entry)(int); + void (*visibility)(int); + void (*special)(int, int x, int y); + Fl_Glut_Window(int w, int h, const char *); + Fl_Glut_Window(int x, int y, int w, int h, const char *); + ~Fl_Glut_Window(); +}; + +extern FL_EXPORT Fl_Glut_Window *glut_window; // the current window +extern FL_EXPORT int glut_menu; // the current menu + +// function pointers that are not per-window: +extern FL_EXPORT void (*glut_idle_function)(); +extern FL_EXPORT void (*glut_menustate_function)(int); +extern FL_EXPORT void (*glut_menustatus_function)(int,int,int); + +//////////////////////////////////////////////////////////////// + +//# define GLUT_API_VERSION This does not match any version of GLUT exactly... + +FL_EXPORT void glutInit(int *argcp, char **argv); // creates first window + +FL_EXPORT void glutInitDisplayMode(unsigned int mode); +// the FL_ symbols have the same value as the GLUT ones: +# define GLUT_RGB FL_RGB +# define GLUT_RGBA FL_RGB +# define GLUT_INDEX FL_INDEX +# define GLUT_SINGLE FL_SINGLE +# define GLUT_DOUBLE FL_DOUBLE +# define GLUT_ACCUM FL_ACCUM +# define GLUT_ALPHA FL_ALPHA +# define GLUT_DEPTH FL_DEPTH +# define GLUT_STENCIL FL_STENCIL +# define GLUT_MULTISAMPLE FL_MULTISAMPLE +# define GLUT_STEREO FL_STEREO +// # define GLUT_LUMINANCE 512 + +FL_EXPORT void glutInitWindowPosition(int x, int y); + +FL_EXPORT void glutInitWindowSize(int w, int h); + +FL_EXPORT void glutMainLoop(); + +FL_EXPORT int glutCreateWindow(char *title); + +FL_EXPORT int glutCreateSubWindow(int win, int x, int y, int width, int height); + +FL_EXPORT void glutDestroyWindow(int win); + +inline void glutPostRedisplay() {glut_window->redraw();} + +FL_EXPORT void glutSwapBuffers(); + +inline int glutGetWindow() {return glut_window->number;} + +FL_EXPORT void glutSetWindow(int win); + +inline void glutSetWindowTitle(char *t) {glut_window->label(t);} + +inline void glutSetIconTitle(char *t) {glut_window->iconlabel(t);} + +inline void glutPositionWindow(int x, int y) {glut_window->position(x,y);} + +inline void glutReshapeWindow(int w, int h) {glut_window->size(w,h);} + +inline void glutPopWindow() {glut_window->show();} + +//inline void glutPushWindow(); + +inline void glutIconifyWindow() {glut_window->iconize();} + +inline void glutShowWindow() {glut_window->show();} + +inline void glutHideWindow() {glut_window->hide();} + +inline void glutFullScreen() {glut_window->fullscreen();} + +inline void glutSetCursor(Fl_Cursor cursor) {glut_window->cursor(cursor);} +// notice that the numeric values are different than glut: +# define GLUT_CURSOR_RIGHT_ARROW ((Fl_Cursor)2) +# define GLUT_CURSOR_LEFT_ARROW ((Fl_Cursor)67) +# define GLUT_CURSOR_INFO FL_CURSOR_HAND +# define GLUT_CURSOR_DESTROY ((Fl_Cursor)45) +# define GLUT_CURSOR_HELP FL_CURSOR_HELP +# define GLUT_CURSOR_CYCLE ((Fl_Cursor)26) +# define GLUT_CURSOR_SPRAY ((Fl_Cursor)63) +# define GLUT_CURSOR_WAIT FL_CURSOR_WAIT +# define GLUT_CURSOR_TEXT FL_CURSOR_INSERT +# define GLUT_CURSOR_CROSSHAIR FL_CURSOR_CROSS +# define GLUT_CURSOR_UP_DOWN FL_CURSOR_NS +# define GLUT_CURSOR_LEFT_RIGHT FL_CURSOR_WE +# define GLUT_CURSOR_TOP_SIDE FL_CURSOR_N +# define GLUT_CURSOR_BOTTOM_SIDE FL_CURSOR_S +# define GLUT_CURSOR_LEFT_SIDE FL_CURSOR_W +# define GLUT_CURSOR_RIGHT_SIDE FL_CURSOR_E +# define GLUT_CURSOR_TOP_LEFT_CORNER FL_CURSOR_NW +# define GLUT_CURSOR_TOP_RIGHT_CORNER FL_CURSOR_NE +# define GLUT_CURSOR_BOTTOM_RIGHT_CORNER FL_CURSOR_SE +# define GLUT_CURSOR_BOTTOM_LEFT_CORNER FL_CURSOR_SW +# define GLUT_CURSOR_INHERIT FL_CURSOR_DEFAULT +# define GLUT_CURSOR_NONE FL_CURSOR_NONE +# define GLUT_CURSOR_FULL_CROSSHAIR FL_CURSOR_CROSS + +//inline void glutWarpPointer(int x, int y); + +inline void glutEstablishOverlay() {glut_window->make_overlay_current();} + +inline void glutRemoveOverlay() {glut_window->hide_overlay();} + +inline void glutUseLayer(GLenum layer) { + layer ? glut_window->make_overlay_current() : glut_window->make_current();} +enum {GLUT_NORMAL, GLUT_OVERLAY}; + +inline void glutPostOverlayRedisplay() {glut_window->redraw_overlay();} + +inline void glutShowOverlay() {glut_window->redraw_overlay();} + +inline void glutHideOverlay() {glut_window->hide_overlay();} + +FL_EXPORT int glutCreateMenu(void (*)(int)); + +FL_EXPORT void glutDestroyMenu(int menu); + +inline int glutGetMenu() {return glut_menu;} + +inline void glutSetMenu(int m) {glut_menu = m;} + +FL_EXPORT void glutAddMenuEntry(char *label, int value); + +FL_EXPORT void glutAddSubMenu(char *label, int submenu); + +FL_EXPORT void glutChangeToMenuEntry(int item, char *label, int value); + +FL_EXPORT void glutChangeToSubMenu(int item, char *label, int submenu); + +FL_EXPORT void glutRemoveMenuItem(int item); + +inline void glutAttachMenu(int b) {glut_window->menu[b] = glut_menu;} + +inline void glutDetachMenu(int b) {glut_window->menu[b] = 0;} + +inline void glutDisplayFunc(void (*f)()) {glut_window->display = f;} + +inline void glutReshapeFunc(void (*f)(int w, int h)) {glut_window->reshape=f;} + +inline void glutKeyboardFunc(void (*f)(uchar key, int x, int y)) { + glut_window->keyboard = f;} + +inline void glutMouseFunc(void (*f)(int b, int state, int x, int y)) { + glut_window->mouse = f;} +# define GLUT_LEFT_BUTTON 0 +# define GLUT_MIDDLE_BUTTON 1 +# define GLUT_RIGHT_BUTTON 2 +# define GLUT_DOWN 0 +# define GLUT_UP 1 + +inline void glutMotionFunc(void (*f)(int x, int y)) {glut_window->motion= f;} + +inline void glutPassiveMotionFunc(void (*f)(int x, int y)) { + glut_window->passivemotion= f;} + +inline void glutEntryFunc(void (*f)(int s)) {glut_window->entry = f;} +enum {GLUT_LEFT, GLUT_ENTERED}; + +inline void glutVisibilityFunc(void (*f)(int s)) {glut_window->visibility=f;} +enum {GLUT_NOT_VISIBLE, GLUT_VISIBLE}; + +inline void glutIdleFunc(void (*f)()) {Fl::set_idle(f);} + +// Warning: this cast may not work on all machines: +inline void glutTimerFunc(unsigned int msec, void (*f)(int), int value) { + Fl::add_timeout(msec*.001, (void (*)(void *))f, (void *)value); +} + +inline void glutMenuStateFunc(void (*f)(int state)) { + glut_menustate_function = f;} + +inline void glutMenuStatusFunc(void (*f)(int status, int x, int y)) { + glut_menustatus_function = f;} +enum {GLUT_MENU_NOT_IN_USE, GLUT_MENU_IN_USE}; + +inline void glutSpecialFunc(void (*f)(int key, int x, int y)) { + glut_window->special = f;} +# define GLUT_KEY_F1 1 +# define GLUT_KEY_F2 2 +# define GLUT_KEY_F3 3 +# define GLUT_KEY_F4 4 +# define GLUT_KEY_F5 5 +# define GLUT_KEY_F6 6 +# define GLUT_KEY_F7 7 +# define GLUT_KEY_F8 8 +# define GLUT_KEY_F9 9 +# define GLUT_KEY_F10 10 +# define GLUT_KEY_F11 11 +# define GLUT_KEY_F12 12 +// WARNING: Different values than GLUT uses: +# define GLUT_KEY_LEFT FL_Left +# define GLUT_KEY_UP FL_Up +# define GLUT_KEY_RIGHT FL_Right +# define GLUT_KEY_DOWN FL_Down +# define GLUT_KEY_PAGE_UP FL_Page_Up +# define GLUT_KEY_PAGE_DOWN FL_Page_Down +# define GLUT_KEY_HOME FL_Home +# define GLUT_KEY_END FL_End +# define GLUT_KEY_INSERT FL_Insert + +//inline void glutSpaceballMotionFunc(void (*)(int x, int y, int z)); + +//inline void glutSpaceballRotateFunc(void (*)(int x, int y, int z)); + +//inline void glutSpaceballButtonFunc(void (*)(int button, int state)); + +//inline void glutButtonBoxFunc(void (*)(int button, int state)); + +//inline void glutDialsFunc(void (*)(int dial, int value)); + +//inline void glutTabletMotionFunc(void (*)(int x, int y)); + +//inline void glutTabletButtonFunc(void (*)(int button, int state, int x, int y)); + +inline void glutOverlayDisplayFunc(void (*f)()) { + glut_window->overlaydisplay = f;} + +//inline void glutWindowStatusFunc(void (*)(int state)); +//enum {GLUT_HIDDEN, GLUT_FULLY_RETAINED, GLUT_PARTIALLY_RETAINED, +// GLUT_FULLY_COVERED}; + +//inline void glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue); + +//inline GLfloat glutGetColor(int ndx, int component); +//#define GLUT_RED 0 +//#define GLUT_GREEN 1 +//#define GLUT_BLUE 2 + +//inline void glutCopyColormap(int win); + +// Warning: values are changed from GLUT! +// Also relies on the GL_ symbols having values greater than 100 +int glutGet(GLenum type); +enum { + GLUT_RETURN_ZERO = 0, + GLUT_WINDOW_X, + GLUT_WINDOW_Y, + GLUT_WINDOW_WIDTH, + GLUT_WINDOW_HEIGHT, + GLUT_WINDOW_PARENT, +//GLUT_WINDOW_NUM_CHILDREN, +//GLUT_WINDOW_CURSOR, + GLUT_SCREEN_WIDTH, + GLUT_SCREEN_HEIGHT, +//GLUT_SCREEN_WIDTH_MM, +//GLUT_SCREEN_HEIGHT_MM, + GLUT_MENU_NUM_ITEMS, + GLUT_DISPLAY_MODE_POSSIBLE, + GLUT_INIT_WINDOW_X, + GLUT_INIT_WINDOW_Y, + GLUT_INIT_WINDOW_WIDTH, + GLUT_INIT_WINDOW_HEIGHT, + GLUT_INIT_DISPLAY_MODE, +//GLUT_ELAPSED_TIME, + GLUT_WINDOW_BUFFER_SIZE +}; + +# define GLUT_WINDOW_STENCIL_SIZE GL_STENCIL_BITS +# define GLUT_WINDOW_DEPTH_SIZE GL_DEPTH_BITS +# define GLUT_WINDOW_RED_SIZE GL_RED_BITS +# define GLUT_WINDOW_GREEN_SIZE GL_GREEN_BITS +# define GLUT_WINDOW_BLUE_SIZE GL_BLUE_BITS +# define GLUT_WINDOW_ALPHA_SIZE GL_ALPHA_BITS +# define GLUT_WINDOW_ACCUM_RED_SIZE GL_ACCUM_RED_BITS +# define GLUT_WINDOW_ACCUM_GREEN_SIZE GL_ACCUM_GREEN_BITS +# define GLUT_WINDOW_ACCUM_BLUE_SIZE GL_ACCUM_BLUE_BITS +# define GLUT_WINDOW_ACCUM_ALPHA_SIZE GL_ACCUM_ALPHA_BITS +# define GLUT_WINDOW_DOUBLEBUFFER GL_DOUBLEBUFFER +# define GLUT_WINDOW_RGBA GL_RGBA +# define GLUT_WINDOW_COLORMAP_SIZE GL_INDEX_BITS +# ifdef GL_SAMPLES_SGIS +# define GLUT_WINDOW_NUM_SAMPLES GL_SAMPLES_SGIS +# else +# define GLUT_WINDOW_NUM_SAMPLES GLUT_RETURN_ZERO +# endif +# define GLUT_WINDOW_STEREO GL_STEREO + +//int glutDeviceGet(GLenum type); +//#define GLUT_HAS_KEYBOARD 600 +//#define GLUT_HAS_MOUSE 601 +//#define GLUT_HAS_SPACEBALL 602 +//#define GLUT_HAS_DIAL_AND_BUTTON_BOX 603 +//#define GLUT_HAS_TABLET 604 +//#define GLUT_NUM_MOUSE_BUTTONS 605 +//#define GLUT_NUM_SPACEBALL_BUTTONS 606 +//#define GLUT_NUM_BUTTON_BOX_BUTTONS 607 +//#define GLUT_NUM_DIALS 608 +//#define GLUT_NUM_TABLET_BUTTONS 609 + +// WARNING: these values are different than GLUT uses: +# define GLUT_ACTIVE_SHIFT FL_SHIFT +# define GLUT_ACTIVE_CTRL FL_CTRL +# define GLUT_ACTIVE_ALT FL_ALT +inline int glutGetModifiers() {return Fl::event_state() & (GLUT_ACTIVE_SHIFT | GLUT_ACTIVE_CTRL | GLUT_ACTIVE_ALT);} + +int glutLayerGet(GLenum); +# define GLUT_OVERLAY_POSSIBLE 800 +//#define GLUT_LAYER_IN_USE 801 +//#define GLUT_HAS_OVERLAY 802 +# define GLUT_TRANSPARENT_INDEX 803 +# define GLUT_NORMAL_DAMAGED 804 +# define GLUT_OVERLAY_DAMAGED 805 + +//inline int glutVideoResizeGet(GLenum param); +//#define GLUT_VIDEO_RESIZE_POSSIBLE 900 +//#define GLUT_VIDEO_RESIZE_IN_USE 901 +//#define GLUT_VIDEO_RESIZE_X_DELTA 902 +//#define GLUT_VIDEO_RESIZE_Y_DELTA 903 +//#define GLUT_VIDEO_RESIZE_WIDTH_DELTA 904 +//#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 905 +//#define GLUT_VIDEO_RESIZE_X 906 +//#define GLUT_VIDEO_RESIZE_Y 907 +//#define GLUT_VIDEO_RESIZE_WIDTH 908 +//#define GLUT_VIDEO_RESIZE_HEIGHT 909 + +//inline void glutSetupVideoResizing(); + +//inline void glutStopVideoResizing(); + +//inline void glutVideoResize(int x, int y, int width, int height); + +//inline void glutVideoPan(int x, int y, int width, int height); + +//////////////////////////////////////////////////////////////// +// Emulated GLUT drawing functions: + +// Font argument must be a void* for compatability, so... +extern FL_EXPORT struct Glut_Bitmap_Font {uchar font; int size;} + glutBitmap9By15, glutBitmap8By13, glutBitmapTimesRoman10, + glutBitmapTimesRoman24, glutBitmapHelvetica10, glutBitmapHelvetica12, + glutBitmapHelvetica18; +# define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15) +# define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13) +# define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10) +# define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24) +# define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10) +# define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12) +# define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18) + +FL_EXPORT void glutBitmapCharacter(void *font, int character); +FL_EXPORT int glutBitmapWidth(void *font, int character); + +//////////////////////////////////////////////////////////////// +// GLUT drawing functions. These are NOT emulated but you can +// link in the glut library to get them. This assumes the object +// files in GLUT remain as they currently are so that there are +// not symbol conflicts with the above. + +extern "C" { + +extern int APIENTRY glutExtensionSupported(char *name); + +/* Stroke font constants (use these in GLUT program). */ +# ifdef WIN32 +# define GLUT_STROKE_ROMAN ((void*)0) +# define GLUT_STROKE_MONO_ROMAN ((void*)1) +# else +extern void *glutStrokeRoman; +# define GLUT_STROKE_ROMAN (&glutStrokeRoman) +extern void *glutStrokeMonoRoman; +# define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman) +# endif + +/* GLUT font sub-API */ +extern void APIENTRY glutStrokeCharacter(void *font, int character); +extern int APIENTRY glutStrokeWidth(void *font, int character); + +/* GLUT pre-built models sub-API */ +extern void APIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks); +extern void APIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); +extern void APIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); +extern void APIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); +extern void APIENTRY glutWireCube(GLdouble size); +extern void APIENTRY glutSolidCube(GLdouble size); +extern void APIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); +extern void APIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); +extern void APIENTRY glutWireDodecahedron(); +extern void APIENTRY glutSolidDodecahedron(); +extern void APIENTRY glutWireTeapot(GLdouble size); +extern void APIENTRY glutSolidTeapot(GLdouble size); +extern void APIENTRY glutWireOctahedron(); +extern void APIENTRY glutSolidOctahedron(); +extern void APIENTRY glutWireTetrahedron(); +extern void APIENTRY glutSolidTetrahedron(); +extern void APIENTRY glutWireIcosahedron(); +extern void APIENTRY glutSolidIcosahedron(); + +} + +#endif /* !__glut_h__ */ + +// +// End of "$Id: glut.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/FL/mac.H b/Utilities/FLTK/FL/mac.H new file mode 100644 index 0000000000..11ee29a53d --- /dev/null +++ b/Utilities/FLTK/FL/mac.H @@ -0,0 +1,135 @@ +// +// "$Id: mac.H 4288 2005-04-16 00:13:17Z mike $" +// +// Mac header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Do not directly include this file, instead use <FL/x.H>. It will +// include this file if "__APPLE__" is defined. This is to encourage +// portability of even the system-specific code... + +#ifndef Fl_X_H +# error "Never use <FL/mac.H> directly; include <FL/x.H> instead." +#endif // !Fl_X_H + +// Standard MacOS Carbon API includes... +#include <Carbon/Carbon.h> + +// Now make some fixes to the headers... +#undef check // Dunno where this comes from... + +// Some random X equivalents +typedef WindowPtr Window; +struct XPoint { int x, y; }; +struct XRectangle {int x, y, width, height;}; +typedef RgnHandle Fl_Region; +void fl_clip_region(Fl_Region); +inline Fl_Region XRectangleRegion(int x, int y, int w, int h) { + Fl_Region R = NewRgn(); + SetRectRgn(R, x, y, x+w, y+h); + return R; +} +inline void XDestroyRegion(Fl_Region r) { + DisposeRgn(r); +} + +# define XDestroyWindow(a,b) DisposeWindow(b) +# define XMapWindow(a,b) ShowWindow(b) +# define XUnmapWindow(a,b) HideWindow(b) + +# include "Fl_Window.H" + +// This object contains all mac-specific stuff about a window: +// WARNING: this object is highly subject to change! +class Fl_X +{ +public: + Window xid; // Mac WindowPtr + GWorldPtr other_xid; // pointer for offscreen bitmaps (doublebuffer) + Fl_Window *w; // FLTK window for + Fl_Region region; + Fl_Region subRegion; // region for this specific subwindow + Fl_X *next; // linked tree to support subwindows + Fl_X *xidChildren, *xidNext; // more subwindow tree + int wait_for_expose; + CursHandle cursor; + static Fl_X* first; + static Fl_X* i(const Fl_Window* w) {return w->i;} + static int fake_X_wm(const Fl_Window*,int&,int&,int&,int&,int&); + static void make(Fl_Window*); + void flush(); + // Quartz additions: + CGContextRef gc; // graphics context (NULL when using QD) + static ATSUTextLayout atsu_layout; // windows share a global font + static ATSUStyle atsu_style; + static void q_fill_context(); // fill a Quartz context with current FLTK state + static void q_clear_clipping(); // remove all clipping from a Quartz context + static void q_release_context(Fl_X *x=0); // free all resources associated with fl_gc + static void q_begin_image(CGRect&, int x, int y, int w, int h); + static void q_end_image(); +}; + +inline Window fl_xid(const Fl_Window*w) +{ + return Fl_X::i(w)->xid; +} + +extern CursHandle fl_default_cursor; + +extern struct Fl_XMap { + RGBColor rgb; + ulong pen; +} *fl_current_xmap; + +extern FL_EXPORT void *fl_display; +extern FL_EXPORT Window fl_window; +extern FL_EXPORT CGContextRef fl_gc; +extern FL_EXPORT Handle fl_system_menu; +extern FL_EXPORT class Fl_Sys_Menu_Bar *fl_sys_menu_bar; + +typedef GWorldPtr Fl_Offscreen; + +extern Fl_Offscreen fl_create_offscreen(int w, int h); +extern void fl_copy_offscreen(int x,int y,int w,int h, Fl_Offscreen gWorld, int srcx,int srcy); +extern void fl_delete_offscreen(Fl_Offscreen gWorld); +extern void fl_begin_offscreen(Fl_Offscreen gWorld); +extern void fl_end_offscreen(); + +typedef GWorldPtr Fl_Bitmask; // Carbon requires a 1-bit GWorld instead of a BitMap + +extern FL_EXPORT Fl_Bitmask fl_create_bitmask(int w, int h, const uchar *data); +extern FL_EXPORT Fl_Bitmask fl_create_alphamask(int w, int h, int d, int ld, const uchar *data); +extern FL_EXPORT void fl_delete_bitmask(Fl_Bitmask bm); + +extern void fl_open_display(); + +// Register a function for opening files via the finder... +extern void fl_open_callback(void (*cb)(const char *)); + +extern FL_EXPORT int fl_parse_color(const char* p, uchar& r, uchar& g, uchar& b); + +// +// End of "$Id: mac.H 4288 2005-04-16 00:13:17Z mike $". +// + diff --git a/Utilities/FLTK/FL/mac.r b/Utilities/FLTK/FL/mac.r new file mode 100644 index 0000000000..3d71f2ebbf --- /dev/null +++ b/Utilities/FLTK/FL/mac.r @@ -0,0 +1,13 @@ +data 'MBAR' (128) { + $"0001 0080" /* ...� */ +}; + +data 'MENU' (128, "Apple") { + $"0080 0000 0000 0000 0000 FFFF FFFB 0114" /* .�........����.. */ + $"0A41 626F 7574 2046 4C54 4B00 0000 0001" /* �About FLTK..... */ + $"2D00 0000 0000" /* -..... */ +}; + +data 'carb' (0) { +}; + diff --git a/Utilities/FLTK/FL/math.h b/Utilities/FLTK/FL/math.h new file mode 100644 index 0000000000..891da4bf79 --- /dev/null +++ b/Utilities/FLTK/FL/math.h @@ -0,0 +1,72 @@ +// +// "$Id$" +// +// Math header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef fl_math_h +# define fl_math_h + +// Apple's ProjectBuilder has the nasty habit of including recursively +// down the file tree. To avoid re-including <FL/math.h> we must +// directly include the systems math file. (Plus, I could not find a +// predefined macro for ProjectBuilder builds, so we have to define it +// in the project) +# if defined(__APPLE__) && defined(__PROJECTBUILDER__) +# include "/usr/include/math.h" +# else +# include <math.h> +# endif + +# ifdef __EMX__ +# include <float.h> +# endif + + +# ifndef M_PI +# define M_PI 3.14159265358979323846 +# define M_PI_2 1.57079632679489661923 +# define M_PI_4 0.78539816339744830962 +# define M_1_PI 0.31830988618379067154 +# define M_2_PI 0.63661977236758134308 +# endif // !M_PI + +# ifndef M_SQRT2 +# define M_SQRT2 1.41421356237309504880 +# define M_SQRT1_2 0.70710678118654752440 +# endif // !M_SQRT2 + +# if (defined(WIN32) || defined(CRAY)) && !defined(__MINGW32__) && !defined(__MWERKS__) + +inline double rint(double v) {return floor(v+.5);} +inline double copysign(double a, double b) {return b<0 ? -a : a;} + +# endif // (WIN32 || CRAY) && !__MINGW32__ && !__MWERKS__ + +#endif // !fl_math_h + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/FL/win32.H b/Utilities/FLTK/FL/win32.H new file mode 100644 index 0000000000..439c181e4f --- /dev/null +++ b/Utilities/FLTK/FL/win32.H @@ -0,0 +1,151 @@ +// +// "$Id: win32.H 4569 2005-09-15 07:41:17Z matt $" +// +// WIN32 header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Do not directly include this file, instead use <FL/x.H>. It will +// include this file if WIN32 is defined. This is to encourage +// portability of even the system-specific code... + +#ifndef Fl_X_H +# error "Never use <FL/win32.H> directly; include <FL/x.H> instead." +#endif // !Fl_X_H + +#include <windows.h> +// In some of the distributions, the gcc header files are missing some stuff: +#ifndef LPMINMAXINFO +#define LPMINMAXINFO MINMAXINFO* +#endif +#ifndef VK_LWIN +#define VK_LWIN 0x5B +#define VK_RWIN 0x5C +#define VK_APPS 0x5D +#endif + +// some random X equivalents +typedef HWND Window; +typedef POINT XPoint; +struct XRectangle {int x, y, width, height;}; +typedef HRGN Fl_Region; +FL_EXPORT void fl_clip_region(Fl_Region); +inline Fl_Region XRectangleRegion(int x, int y, int w, int h) { + return CreateRectRgn(x,y,x+w,y+h); +} +inline void XDestroyRegion(Fl_Region r) {DeleteObject(r);} +inline void XClipBox(Fl_Region r,XRectangle* rect) { + RECT win_rect; GetRgnBox(r,&win_rect); + rect->x=win_rect.left; + rect->y=win_rect.top; + rect->width=win_rect.right-win_rect.left; + rect->height=win_rect.bottom-win_rect.top; +} +#define XDestroyWindow(a,b) DestroyWindow(b) +#define XMapWindow(a,b) ShowWindow(b, SW_RESTORE) +#define XUnmapWindow(a,b) ShowWindow(b, SW_HIDE) + +#include "Fl_Window.H" +// this object contains all win32-specific stuff about a window: +// Warning: this object is highly subject to change! +class FL_EXPORT Fl_X { +public: + // member variables - add new variables only at the end of this block + Window xid; + HBITMAP other_xid; // for double-buffered windows + Fl_Window* w; + Fl_Region region; + Fl_X *next; + int wait_for_expose; + HDC private_dc; // used for OpenGL + HCURSOR cursor; + HDC saved_hdc; // saves the handle of the DC currently loaded + // static variables, static functions and member functions + static Fl_X* first; + static Fl_X* i(const Fl_Window* w) {return w->i;} + static int fake_X_wm(const Fl_Window* w,int &X, int &Y, + int &bt,int &bx,int &by); + void setwindow(Fl_Window* wi) {w=wi; wi->i=this;} + void flush() {w->flush();} + void set_minmax(LPMINMAXINFO minmax); + void mapraise(); + static Fl_X* make(Fl_Window*); +}; +extern FL_EXPORT HCURSOR fl_default_cursor; +extern FL_EXPORT UINT fl_wake_msg; +inline Window fl_xid(const Fl_Window*w) {Fl_X *temp = Fl_X::i(w); return temp ? temp->xid : 0;} +FL_EXPORT Fl_Window* fl_find(Window xid); +extern FL_EXPORT char fl_override_redirect; // hack into Fl_Window::make_xid() +extern FL_EXPORT int fl_background_pixel; // hack into Fl_Window::make_xid() + +// most recent fl_color() or fl_rgbcolor() points at one of these: +extern FL_EXPORT struct Fl_XMap { + COLORREF rgb; // this should be the type the RGB() macro returns + HPEN pen; // pen, 0 if none created yet + int brush; // ref to solid brush, 0 if none created yet +} *fl_current_xmap; +inline COLORREF fl_RGB() {return fl_current_xmap->rgb;} +inline HPEN fl_pen() {return fl_current_xmap->pen;} +FL_EXPORT HBRUSH fl_brush(); // allocates a brush if necessary +FL_EXPORT HBRUSH fl_brush_action(int); // now does the real work + +extern FL_EXPORT HINSTANCE fl_display; +extern FL_EXPORT Window fl_window; +extern FL_EXPORT HDC fl_gc; +extern FL_EXPORT HPALETTE fl_palette; // non-zero only on 8-bit displays! +extern FL_EXPORT HDC fl_GetDC(Window); +extern FL_EXPORT MSG fl_msg; +extern FL_EXPORT void fl_release_dc(HWND w, HDC dc); +extern FL_EXPORT void fl_save_dc( HWND w, HDC dc); + +// off-screen pixmaps: create, destroy, draw into, copy to window +typedef HBITMAP Fl_Offscreen; +#define fl_create_offscreen(w, h) CreateCompatibleBitmap(fl_gc, w, h) + +extern FL_EXPORT HDC fl_makeDC(HBITMAP); + +#define fl_begin_offscreen(b) \ + HDC _sgc=fl_gc; Window _sw=fl_window; \ + fl_gc=fl_makeDC(b); int _savedc = SaveDC(fl_gc); fl_window=(HWND)b; fl_push_no_clip() + +#define fl_end_offscreen() \ + fl_pop_clip(); RestoreDC(fl_gc, _savedc); DeleteDC(fl_gc); fl_window=_sw; fl_gc = _sgc + +FL_EXPORT void fl_copy_offscreen(int x,int y,int w,int h,HBITMAP pixmap,int srcx,int srcy); +#define fl_delete_offscreen(bitmap) DeleteObject(bitmap); + +// Bitmap masks +typedef HBITMAP Fl_Bitmask; + +extern FL_EXPORT Fl_Bitmask fl_create_bitmask(int w, int h, const uchar *data); +extern FL_EXPORT Fl_Bitmask fl_create_alphamask(int w, int h, int d, int ld, const uchar *data); +extern FL_EXPORT void fl_delete_bitmask(Fl_Bitmask bm); + +// Dummy function to register a function for opening files via the window manager... +inline void fl_open_callback(void (*)(const char *)) {} + +extern FL_EXPORT int fl_parse_color(const char* p, uchar& r, uchar& g, uchar& b); + +// +// End of "$Id: win32.H 4569 2005-09-15 07:41:17Z matt $". +// diff --git a/Utilities/FLTK/FL/x.H b/Utilities/FLTK/FL/x.H new file mode 100644 index 0000000000..91642c2208 --- /dev/null +++ b/Utilities/FLTK/FL/x.H @@ -0,0 +1,147 @@ +// +// "$Id: x.H 4288 2005-04-16 00:13:17Z mike $" +// +// X11 header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// These are internal fltk symbols that are necessary or useful for +// calling Xlib. You should include this file if (and ONLY if) you +// need to call Xlib directly. These symbols may not exist on non-X +// systems. + +#ifndef Fl_X_H +# define Fl_X_H + +# include "Enumerations.H" + +# ifdef WIN32 +# include "win32.H" +# elif defined(__APPLE__) +# include "mac.H" +# else +# if defined(_ABIN32) || defined(_ABI64) // fix for broken SGI Irix X .h files +# pragma set woff 3322 +# endif +# include <X11/Xlib.h> +# include <X11/Xutil.h> +# if defined(_ABIN32) || defined(_ABI64) +# pragma reset woff 3322 +# endif +# include <X11/Xatom.h> +# include "Fl_Window.H" + +// Mirror X definition of Region to Fl_Region, for portability... +typedef Region Fl_Region; + +FL_EXPORT void fl_open_display(); +FL_EXPORT void fl_open_display(Display*); +FL_EXPORT void fl_close_display(); + +// constant info about the X server connection: +extern FL_EXPORT Display *fl_display; +extern FL_EXPORT Window fl_message_window; +extern FL_EXPORT int fl_screen; +extern FL_EXPORT XVisualInfo *fl_visual; +extern FL_EXPORT Colormap fl_colormap; + +// drawing functions: +extern FL_EXPORT GC fl_gc; +extern FL_EXPORT Window fl_window; +extern FL_EXPORT XFontStruct* fl_xfont; +FL_EXPORT ulong fl_xpixel(Fl_Color i); +FL_EXPORT ulong fl_xpixel(uchar r, uchar g, uchar b); +FL_EXPORT void fl_clip_region(Fl_Region); +FL_EXPORT Fl_Region fl_clip_region(); +FL_EXPORT Fl_Region XRectangleRegion(int x, int y, int w, int h); // in fl_rect.cxx + +// feed events into fltk: +FL_EXPORT int fl_handle(const XEvent&); + +// you can use these in Fl::add_handler() to look at events: +extern FL_EXPORT const XEvent* fl_xevent; +extern FL_EXPORT ulong fl_event_time; + +// off-screen pixmaps: create, destroy, draw into, copy to window: +typedef ulong Fl_Offscreen; +#define fl_create_offscreen(w,h) \ + XCreatePixmap(fl_display, fl_window, w, h, fl_visual->depth) +// begin/end are macros that save the old state in local variables: +# define fl_begin_offscreen(pixmap) \ + Window _sw=fl_window; fl_window=pixmap; fl_push_no_clip() +# define fl_end_offscreen() \ + fl_pop_clip(); fl_window = _sw + +# define fl_copy_offscreen(x,y,w,h,pixmap,srcx,srcy) \ + XCopyArea(fl_display, pixmap, fl_window, fl_gc, srcx, srcy, w, h, x, y) +# define fl_delete_offscreen(pixmap) XFreePixmap(fl_display, pixmap) + +// Bitmap masks +typedef ulong Fl_Bitmask; + +extern FL_EXPORT Fl_Bitmask fl_create_bitmask(int w, int h, const uchar *data); +extern FL_EXPORT Fl_Bitmask fl_create_alphamask(int w, int h, int d, int ld, const uchar *data); +extern FL_EXPORT void fl_delete_bitmask(Fl_Bitmask bm); + +// this object contains all X-specific stuff about a window: +// Warning: this object is highly subject to change! It's definition +// is only here so that fl_xid can be declared inline: +class FL_EXPORT Fl_X { +public: + Window xid; + Window other_xid; + Fl_Window *w; + Fl_Region region; + Fl_X *next; + char wait_for_expose; + char backbuffer_bad; // used for XDBE + static Fl_X* first; + static Fl_X* i(const Fl_Window* wi) {return wi->i;} + void setwindow(Fl_Window* wi) {w=wi; wi->i=this;} + void sendxjunk(); + static void make_xid(Fl_Window*,XVisualInfo* =fl_visual, Colormap=fl_colormap); + static Fl_X* set_xid(Fl_Window*, Window); + // kludges to get around protection: + void flush() {w->flush();} + static void x(Fl_Window* wi, int X) {wi->x(X);} + static void y(Fl_Window* wi, int Y) {wi->y(Y);} +}; + +// convert xid <-> Fl_Window: +inline Window fl_xid(const Fl_Window*w) {return Fl_X::i(w)->xid;} +FL_EXPORT Fl_Window* fl_find(Window xid); + +extern FL_EXPORT char fl_override_redirect; // hack into Fl_X::make_xid() +extern FL_EXPORT int fl_background_pixel; // hack into Fl_X::make_xid() + +// Dummy function to register a function for opening files via the window manager... +inline void fl_open_callback(void (*)(const char *)) {} + +extern FL_EXPORT int fl_parse_color(const char* p, uchar& r, uchar& g, uchar& b); + +# endif +#endif + +// +// End of "$Id: x.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/GL/glut.h b/Utilities/FLTK/GL/glut.h new file mode 100644 index 0000000000..0c57f0700e --- /dev/null +++ b/Utilities/FLTK/GL/glut.h @@ -0,0 +1,30 @@ +// +// "$Id$" +// +// GLUT compatibility header for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to "fltk-bugs@fltk.org". +// + +#include <FL/glut.H> + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/README b/Utilities/FLTK/README new file mode 100755 index 0000000000..1732a6bb8e --- /dev/null +++ b/Utilities/FLTK/README @@ -0,0 +1,29 @@ +FLTK modifications: +--------------------- + +Add following line: +#include <FL/Fl.H> +For: +Fl_Overlay_Window.cxx +Fl_grab.cxx +Fl_own_colormap.cxx +Fl_visual.cxx +fl_rect.cxx + +src/flstring.h + + +Add following line: +#include "fltk-config.h" +For: +Fl_get_system_colors.cxx +fl_draw_image.cxx +fl_draw_pixmap.cxx +filename_list.cxx +src/flstring.h + + +CMakeLists.txt: rename config.h file name as following: +config.h -> fltk-config.h +# In CMake/FLTKConfig.cmake.in add line +SET(FLTK_PLATFORM_DEPENDENT_LIBS "@FLTK_PLATFORM_DEPENDENT_LIBS@") diff --git a/Utilities/FLTK/configh.cmake.in b/Utilities/FLTK/configh.cmake.in new file mode 100644 index 0000000000..35aade4aae --- /dev/null +++ b/Utilities/FLTK/configh.cmake.in @@ -0,0 +1,265 @@ +/* + * "$Id: configh.cmake.in 4454 2005-07-24 18:41:30Z matt $" + * + * Configuration file for the Fast Light Tool Kit (FLTK). + * @configure_input@ + * + * Copyright 1998-2005 by Bill Spitzak and others. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "fltk-bugs@fltk.org". + */ + +/* + * Where to find files... + */ + +#define FLTK_DATADIR "@FLTK_DATADIR@" +#define FLTK_DOCDIR "@FLTK_DOCDIR@" + +/* + * BORDER_WIDTH: + * + * Thickness of FL_UP_BOX and FL_DOWN_BOX. Current 1,2, and 3 are + * supported. + * + * 3 is the historic FLTK look. + * 2 is the default and looks like Microsoft Windows, KDE, and Qt. + * 1 is a plausible future evolution... + * + * Note that this may be simulated at runtime by redefining the boxtypes + * using Fl::set_boxtype(). + */ + +#define BORDER_WIDTH 2 + +/* + * HAVE_GL: + * + * Do you have OpenGL? Set this to 0 if you don't have or plan to use + * OpenGL, and FLTK will be smaller. + */ + +#define HAVE_GL @HAVE_GL@ + +/* + * HAVE_GL_GLU_H: + * + * Do you have the OpenGL Utility Library header file? + * (many broken Mesa RPMs do not...) + */ + +#cmakedefine HAVE_GL_GLU_H @HAVE_GL_GLU_H@ + +/* + * USE_COLORMAP: + * + * Setting this to zero will save a good deal of code (especially for + * fl_draw_image), but FLTK will only work on TrueColor visuals. + */ + +#define USE_COLORMAP 1 + +/* + * USE_XFT + * + * Use the new Xft library to draw anti-aliased text. + */ + +#define USE_XFT 0 + +/* + * HAVE_XDBE: + * + * Do we have the X double-buffer extension? + */ + +#define HAVE_XDBE 0 + +/* + * USE_XDBE: + * + * Actually try to use the double-buffer extension? + */ + +#define USE_XDBE HAVE_XDBE + +/* + * USE_QUARTZ: + * + * Use Quartz instead of Quickdraw on Apple Mac OS X machines. + * FLTK was originally ported to Quickdraw which is no longer + * supported by Apple. If USE_QUARTZ is defined, FLTK will be + * compiled using Quartz instead. This flag has no meaning on + * other operating systems. + */ + +#cmakedefine FLTK_APPLE +#ifdef FLTK_APPLE + #cmakedefine FLTK_QUARTZ + #ifdef FLTK_QUARTZ + #define USE_QUARTZ 1 + #define __APPLE_QUARTZ__ + #undef __APPLE_QD__ + #else + #define USE_QUARTZ 0 + #undef __APPLE_QUARTZ__ + #define __APPLE_QD__ + #endif +#endif + +/* + * HAVE_OVERLAY: + * + * Use the X overlay extension? FLTK will try to use an overlay + * visual for Fl_Overlay_Window, the Gl_Window overlay, and for the + * menus. Setting this to zero will remove a substantial amount of + * code from FLTK. Overlays have only been tested on SGI servers! + */ + +#define HAVE_OVERLAY 0 + +/* + * HAVE_GL_OVERLAY: + * + * It is possible your GL has an overlay even if X does not. If so, + * set this to 1. + */ + +#define HAVE_GL_OVERLAY HAVE_OVERLAY + +/* + * WORDS_BIGENDIAN: + * + * Byte order of your machine: 1 = big-endian, 0 = little-endian. + */ + +#define WORDS_BIGENDIAN 0 + +/* + * U16, U32, U64: + * + * Types used by fl_draw_image. One of U32 or U64 must be defined. + * U16 is optional but FLTK will work better with it! + */ + +#cmakedefine U16 @U16@ +#cmakedefine U32 @U32@ +#cmakedefine U64 @U64@ + +/* + * HAVE_DIRENT_H, HAVE_SYS_NDIR_H, HAVE_SYS_DIR_H, HAVE_NDIR_H, HAVE_SCANDIR: + * + * Where is <dirent.h> (used only by fl_file_chooser and scandir). + */ + +#cmakedefine HAVE_DIRENT_H @HAVE_DIRENT_H@ +#cmakedefine HAVE_SYS_NDIR_H @HAVE_SYS_NDIR_H@ +#cmakedefine HAVE_SYS_DIR_H @HAVE_SYS_DIR_H@ +#cmakedefine HAVE_NDIR_H @HAVE_NDIR_H@ +#cmakedefine HAVE_SCANDIR @HAVE_SCANDIR@ + +/* + * Possibly missing sprintf-style functions: + */ + +#cmakedefine HAVE_VSNPRINTF @HAVE_VSNPRINTF@ +#cmakedefine HAVE_SNPRINTF @HAVE_SNPRINTF@ + +/* + * String functions and headers... + */ + +#cmakedefine HAVE_STRINGS_H @HAVE_STRINGS_H@ +#cmakedefine HAVE_STRCASECMP @HAVE_STRCASECMP@ +#cmakedefine HAVE_STRLCAT @HAVE_STRLCAT@ +#cmakedefine HAVE_STRLCPY @HAVE_STRLCPY@ + +/* + * 'locale' functions + */ + +#cmakedefine HAVE_LOCALE_H @HAVE_LOCALE_H@ +#cmakedefine HAVE_LOCALECONV @HAVE_LOCALECONV@ + +/* + * HAVE_SYS_SELECT_H: + * + * Whether or not select() call has its own header file. + */ + +#cmakedefine HAVE_SYS_SELECT_H @HAVE_SYS_SELECT_H@ + +/* + * HAVE_SYS_STDTYPES_H: + * + * Whether or not we have the <sys/stdtypes.h> header file. + */ + +#cmakedefine HAVE_SYS_STDTYPES_H @HAVE_SYS_STDTYPES_H@ + +/* + * USE_POLL: + * + * Use the poll() call provided on Linux and Irix instead of select() + */ + +#define USE_POLL 0 + +/* + * Do we have various image libraries? + */ + +#cmakedefine HAVE_LIBPNG @HAVE_LIBPNG@ +#cmakedefine HAVE_LIBZ @HAVE_LIBZ@ +#cmakedefine HAVE_LIBJPEG @HAVE_LIBJPEG@ + +/* + * Which header file do we include for libpng? + */ + +#cmakedefine HAVE_PNG_H @HAVE_PNG_H@ +#cmakedefine HAVE_LIBPNG_PNG_H @HAVE_LIBPNG_PNG_H@ + +/* + * Do we have the png_xyz() functions? + */ + +#cmakedefine HAVE_PNG_GET_VALID @HAVE_PNG_GET_VALID@ +#cmakedefine HAVE_PNG_SET_TRNS_TO_ALPHA @HAVE_PNG_SET_TRNS_TO_ALPHA@ + +/* + * Do we have POSIX threading? + */ + +#cmakedefine CMAKE_USE_PTHREADS +#ifdef CMAKE_USE_PTHREADS +#define HAVE_PTHREAD 1 +#else +#define HAVE_PTHREAD 0 +#endif + +#cmakedefine CMAKE_HAVE_PTHREAD_H +#ifdef CMAKE_HAVE_PTHREAD_H +#define HAVE_PTHREAD_H 1 +#else +#define HAVE_PTHREAD_H 0 +#endif + +/* + * End of "$Id: configh.cmake.in 4454 2005-07-24 18:41:30Z matt $". + */ diff --git a/Utilities/FLTK/configh.in b/Utilities/FLTK/configh.in new file mode 100644 index 0000000000..6211cb6a82 --- /dev/null +++ b/Utilities/FLTK/configh.in @@ -0,0 +1,284 @@ +/* + * "$Id: configh.in 4702 2005-12-14 00:39:55Z mike $" + * + * Configuration file for the Fast Light Tool Kit (FLTK). + * @configure_input@ + * + * Copyright 1998-2005 by Bill Spitzak and others. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems on the following page: + * + * http://www.fltk.org/str.php + */ + +/* + * Where to find files... + */ + +#define FLTK_DATADIR "" +#define FLTK_DOCDIR "" + +/* + * BORDER_WIDTH: + * + * Thickness of FL_UP_BOX and FL_DOWN_BOX. Current 1,2, and 3 are + * supported. + * + * 3 is the historic FLTK look. + * 2 is the default and looks like Microsoft Windows, KDE, and Qt. + * 1 is a plausible future evolution... + * + * Note that this may be simulated at runtime by redefining the boxtypes + * using Fl::set_boxtype(). + */ + +#define BORDER_WIDTH 2 + +/* + * HAVE_GL: + * + * Do you have OpenGL? Set this to 0 if you don't have or plan to use + * OpenGL, and FLTK will be smaller. + */ + +#define HAVE_GL 0 + +/* + * HAVE_GL_GLU_H: + * + * Do you have the OpenGL Utility Library header file? + * (many broken Mesa RPMs do not...) + */ + +#undef HAVE_GL_GLU_H + +/* + * USE_COLORMAP: + * + * Setting this to zero will save a good deal of code (especially for + * fl_draw_image), but FLTK will only work on TrueColor visuals. + */ + +#define USE_COLORMAP 1 + +/* + * HAVE_XINERAMA + * + * Do we have the Xinerama library to support multi-head displays? + */ + +#define HAVE_XINERAMA 0 + +/* + * USE_XFT + * + * Use the new Xft library to draw anti-aliased text. + */ + +#define USE_XFT 0 + +/* + * HAVE_XDBE: + * + * Do we have the X double-buffer extension? + */ + +#define HAVE_XDBE 0 + +/* + * USE_XDBE: + * + * Actually try to use the double-buffer extension? + */ + +#define USE_XDBE HAVE_XDBE + +/* + * USE_QUARTZ: + * + * Use Quartz instead of Quickdraw on Apple Mac OS X machines. + * FLTK was originally ported to Quickdraw which is no longer + * supported by Apple. If USE_QUARTZ is defined, FLTK will be + * compiled using Quartz instead. This flag has no meaning on + * other operating systems. + */ + +#define USE_QUARTZ 0 +#undef __APPLE_QUARTZ__ +#undef __APPLE_QD__ + +/* + * HAVE_OVERLAY: + * + * Use the X overlay extension? FLTK will try to use an overlay + * visual for Fl_Overlay_Window, the Gl_Window overlay, and for the + * menus. Setting this to zero will remove a substantial amount of + * code from FLTK. Overlays have only been tested on SGI servers! + */ + +#define HAVE_OVERLAY 0 + +/* + * HAVE_GL_OVERLAY: + * + * It is possible your GL has an overlay even if X does not. If so, + * set this to 1. + */ + +#define HAVE_GL_OVERLAY HAVE_OVERLAY + +/* + * WORDS_BIGENDIAN: + * + * Byte order of your machine: 1 = big-endian, 0 = little-endian. + */ + +#define WORDS_BIGENDIAN 0 + +/* + * U16, U32, U64: + * + * Types used by fl_draw_image. One of U32 or U64 must be defined. + * U16 is optional but FLTK will work better with it! + */ + +#undef U16 +#undef U32 +#undef U64 + +/* + * HAVE_DIRENT_H, HAVE_SYS_NDIR_H, HAVE_SYS_DIR_H, HAVE_NDIR_H, HAVE_SCANDIR: + * + * Where is <dirent.h> (used only by fl_file_chooser and scandir). + */ + +#undef HAVE_DIRENT_H +#undef HAVE_SYS_NDIR_H +#undef HAVE_SYS_DIR_H +#undef HAVE_NDIR_H +#undef HAVE_SCANDIR + +/* + * Possibly missing sprintf-style functions: + */ + +#undef HAVE_VSNPRINTF +#undef HAVE_SNPRINTF + +/* + * String functions and headers... + */ + +#undef HAVE_STRINGS_H +#undef HAVE_STRCASECMP +#undef HAVE_STRLCAT +#undef HAVE_STRLCPY + +/* + * Do we have POSIX locale support? + */ + +#undef HAVE_LOCALE_H +#undef HAVE_LOCALECONV + +/* + * HAVE_SYS_SELECT_H: + * + * Whether or not select() call has its own header file. + */ + +#undef HAVE_SYS_SELECT_H + +/* + * HAVE_SYS_STDTYPES_H: + * + * Whether or not we have the <sys/stdtypes.h> header file. + */ + +#undef HAVE_SYS_STDTYPES_H + +/* + * USE_POLL: + * + * Use the poll() call provided on Linux and Irix instead of select() + */ + +#define USE_POLL 0 + +/* + * Do we have various image libraries? + */ + +#undef HAVE_LIBPNG +#undef HAVE_LIBZ +#undef HAVE_LIBJPEG + +/* + * Which header file do we include for libpng? + */ + +#undef HAVE_PNG_H +#undef HAVE_LIBPNG_PNG_H + +/* + * Do we have the png_xyz() functions? + */ + +#undef HAVE_PNG_GET_VALID +#undef HAVE_PNG_SET_TRNS_TO_ALPHA + +/* + * Do we have POSIX threading? + */ + +#undef HAVE_PTHREAD +#undef HAVE_PTHREAD_H + +/* + * Do we have the ALSA library? + */ + +#undef HAVE_ALSA_ASOUNDLIB_H + +/* + * Do we have the long long type? + */ + +#undef HAVE_LONG_LONG + +#ifdef HAVE_LONG_LONG +# define FLTK_LLFMT "%lld" +# define FLTK_LLCAST (long long) +#else +# define FLTK_LLFMT "%ld" +# define FLTK_LLCAST (long) +#endif /* HAVE_LONG_LONG */ + +/* + * Do we have the strtoll() function? + */ + +#undef HAVE_STRTOLL + +#ifndef HAVE_STRTOLL +# define strtoll(nptr,endptr,base) strtol((nptr), (endptr), (base)) +#endif /* !HAVE_STRTOLL */ + +/* + * End of "$Id: configh.in 4702 2005-12-14 00:39:55Z mike $". + */ diff --git a/Utilities/FLTK/configure b/Utilities/FLTK/configure new file mode 100755 index 0000000000..80c4ded851 --- /dev/null +++ b/Utilities/FLTK/configure @@ -0,0 +1,12583 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.59. +# +# Copyright (C) 2003 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="src/Fl.cxx" +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#if HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#if HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#if STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# if HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#if HAVE_STRINGS_H +# include <strings.h> +#endif +#if HAVE_INTTYPES_H +# include <inttypes.h> +#else +# if HAVE_STDINT_H +# include <stdint.h> +# endif +#endif +#if HAVE_UNISTD_H +# include <unistd.h> +#endif" + +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS FL_MAJOR_VERSION FL_MINOR_VERSION FL_PATCH_VERSION FL_API_VERSION OPTIM FLLIBNAME GLDEMOS GLLIBNAME IMGLIBNAME LIBEXT LIBNAME LINKFLTK LINKFLTKFORMS LINKFLTKGL LINKFLTKIMG DSOCOMMAND DSOLINK DSONAME FLDSONAME GLDSONAME IMGDSONAME SHAREDSUFFIX LINKSHARED FLUID CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX NROFF GROFF HTMLDOC RANLIB ac_ct_RANLIB AR LIBCOMMAND CPP EGREP LARGEFILE AUDIOLIBS IMAGELIBS JPEG JPEGINC PNG PNGINC ZLIB ZLIBINC X_CFLAGS X_PRE_LIBS X_LIBS X_EXTRA_LIBS FTCONFIG GLLIB HLINKS POSTBUILD THREADS INSTALL_DESKTOP UNINSTALL_DESKTOP CAT1EXT CAT3EXT CAT6EXT MAKEDEPEND LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CXX_set=${CXX+set} +ac_env_CXX_value=$CXX +ac_cv_env_CXX_set=${CXX+set} +ac_cv_env_CXX_value=$CXX +ac_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_env_CXXFLAGS_value=$CXXFLAGS +ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_cv_env_CXXFLAGS_value=$CXXFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +X features: + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-cygwin use the CygWin libraries default=no + --enable-debug turn on debugging default=no + --enable-gl turn on OpenGL support default=yes + --enable-shared turn on shared libraries default=no + --enable-threads enable multi-threading support + --enable-quartz use Quartz instead of Quickdraw (default=no) + --disable-largefile omit support for large files + --enable-localjpeg use local JPEG library, default=auto + --enable-localzlib use local ZLIB library, default=auto + --enable-localpng use local PNG library, default=auto + --enable-xinerama turn on Xinerama support default=no + --enable-xft turn on Xft support default=no + --enable-xdbe turn on Xdbe support default=no + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-optim="flags" use custom optimization flags + --with-links make header links for common misspellings + --with-x use the X Window System + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have + headers in a nonstandard directory <include dir> + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF + +Copyright (C) 2003 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + +FL_MAJOR_VERSION=1 +FL_MINOR_VERSION=1 +FL_PATCH_VERSION=7 +FL_API_VERSION=${FL_MAJOR_VERSION}.${FL_MINOR_VERSION} + + + + + + +uname=`uname` +uversion=`uname -r | sed -e '1,$s/[^0-9]//g'` +if test "x$uname" = xIRIX64; then + uname="IRIX" +fi +if test "x$uname" = x; then + # MingW doesn't provide any output when uname is run, even with "-s"... + uname="CYGWIN" +fi + +CFLAGS="${CFLAGS:=}" +CPPFLAGS="${CPPFLAGS:=}" +CXXFLAGS="${CXXFLAGS:=}" +OPTIM="${OPTIM:=}" + + + +case $uname in + CYGWIN* | MINGW*) + # Handle Cygwin option *first*, before all other tests. + # Check whether --enable-cygwin or --disable-cygwin was given. +if test "${enable_cygwin+set}" = set; then + enableval="$enable_cygwin" + +fi; + if test x$enable_cygwin != xyes; then + CFLAGS="$CFLAGS -mno-cygwin" + CPPFLAGS="$CPPFLAGS -mno-cygwin" + CXXFLAGS="$CXXFLAGS -mno-cygwin" + LDFLAGS="$LDFLAGS -mno-cygwin" + fi + ;; +esac + +LINKFLTK="../lib/libfltk.a" +LINKFLTKFORMS="../lib/libfltk_forms.a" +LINKFLTKGL="../lib/libfltk_gl.a" +LINKFLTKIMG="../lib/libfltk_images.a" +GLDEMOS="gldemos" + +LIBEXT=".a" +LIBNAME="../lib/libfltk.a" +FLLIBNAME="../lib/libfltk_forms.a" +GLLIBNAME="../lib/libfltk_gl.a" +IMGLIBNAME="../lib/libfltk_images.a" + + + + + + + + + + + + +# Check whether --enable-debug or --disable-debug was given. +if test "${enable_debug+set}" = set; then + enableval="$enable_debug" + +fi; +if test x$enable_debug = xyes; then + DEBUGFLAG="-g " +else + DEBUGFLAG="" +fi + +# Check whether --enable-gl or --disable-gl was given. +if test "${enable_gl+set}" = set; then + enableval="$enable_gl" + +fi; + +# Check whether --enable-shared or --disable-shared was given. +if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + +fi; +if test x$enable_shared = xyes; then + PICFLAG=1 + SHAREDSUFFIX="" + FLUID="fluid-shared" + + case $uname in + Darwin*) + DSONAME="libfltk.$FL_API_VERSION.dylib" + FLDSONAME="libfltk_forms.$FL_API_VERSION.dylib" + GLDSONAME="libfltk_gl.$FL_API_VERSION.dylib" + IMGDSONAME="libfltk_images.$FL_API_VERSION.dylib" + DSOCOMMAND="\$(CC) $DSOFLAGS -dynamiclib -lc -o" + ;; + + SunOS* | UNIX_S*) + DSONAME="libfltk.so.$FL_API_VERSION" + FLDSONAME="libfltk_forms.so.$FL_API_VERSION" + GLDSONAME="libfltk_gl.so.$FL_API_VERSION" + IMGDSONAME="libfltk_images.so.$FL_API_VERSION" + DSOCOMMAND="\$(CXX) -h \$@ \$(LDLIBS) -G $DEBUGFLAG -o" + if test "x$libdir" != "x/usr/lib"; then + DSOLINK="-R$libdir" + fi + ;; + HP-UX*) + DSONAME="libfltk.sl.$FL_API_VERSION" + FLDSONAME="libfltk_forms.sl.$FL_API_VERSION" + GLDSONAME="libfltk_gl.sl.$FL_API_VERSION" + IMGDSONAME="libfltk_images.sl.$FL_API_VERSION" + DSOCOMMAND="ld -b -z +h \$@ $DEBUGFLAG -o" + if test "x$libdir" != "x/usr/lib"; then + DSOLINK="-Wl,-rpath,$libdir" + fi + ;; + IRIX*) + DSONAME="libfltk.so.$FL_API_VERSION" + FLDSONAME="libfltk_forms.so.$FL_API_VERSION" + GLDSONAME="libfltk_gl.so.$FL_API_VERSION" + IMGDSONAME="libfltk_images.so.$FL_API_VERSION" + DSOCOMMAND="\$(CXX) -Wl,-soname,\$@,-set_version,sgi1.1 \$(LDLIBS) -shared $DEBUGFLAG -o" + if test "x$libdir" != "x/usr/lib" -a "x$libdir" != "x/usr/lib32" -a "x$libdir" != "x/usr/lib64"; then + DSOLINK="-Wl,-rpath,$libdir" + fi + ;; + OSF1*) + DSONAME="libfltk.so.$FL_API_VERSION" + FLDSONAME="libfltk_forms.so.$FL_API_VERSION" + GLDSONAME="libfltk_gl.so.$FL_API_VERSION" + IMGDSONAME="libfltk_images.so.$FL_API_VERSION" + DSOCOMMAND="\$(CXX) -Wl,-soname,\$@ \$(LDLIBS) -shared $DEBUGFLAG -o" + if test "x$libdir" != "x/usr/lib" -a "x$libdir" != "x/usr/lib32"; then + DSOLINK="-Wl,-rpath,$libdir" + fi + ;; + Linux* | *BSD*) + DSONAME="libfltk.so.$FL_API_VERSION" + FLDSONAME="libfltk_forms.so.$FL_API_VERSION" + GLDSONAME="libfltk_gl.so.$FL_API_VERSION" + IMGDSONAME="libfltk_images.so.$FL_API_VERSION" + DSOCOMMAND="\$(CXX) -Wl,-soname,\$@ \$(LDLIBS) -shared -fPIC $DEBUGFLAG -o" + if test "x$libdir" != "x/usr/lib"; then + DSOLINK="-Wl,-rpath,$libdir" + fi + ;; + AIX*) + DSONAME="libfltk_s.a" + FLDSONAME="libfltk_forms_s.a" + GLDSONAME="libfltk_gl_s.a" + IMGDSONAME="libfltk_images_s.a" + DSOCOMMAND="\$(CXX) -Wl,-bexpall,-bM:SRE,-bnoentry -o" + SHAREDSUFFIX="_s" + ;; + CYGWIN* | MINGW*) + PICFLAG=0 + if test x$enable_cygwin != xyes; then + DSONAME="mgwfltknox-$FL_API_VERSION.dll" + FLDSONAME="mgwfltknox_forms-$FL_API_VERSION.dll" + GLDSONAME="mgwfltknox_gl-$FL_API_VERSION.dll" + IMGDSONAME="mgwfltknox_images-$FL_API_VERSION.dll" + else + DSONAME="cygfltknox-$FL_API_VERSION.dll" + FLDSONAME="cygfltknox_forms-$FL_API_VERSION.dll" + GLDSONAME="cygfltknox_gl-$FL_API_VERSION.dll" + IMGDSONAME="cygfltknox_images-$FL_API_VERSION.dll" + fi + DSOCOMMAND="\$(CXX) -shared -Wl,--whole-archive -Wl,--export-all-symbols -Wl,--enable-auto-import -o \$@" + ;; + *) + { echo "$as_me:$LINENO: WARNING: Shared libraries may not be supported. Trying -shared option with compiler." >&5 +echo "$as_me: WARNING: Shared libraries may not be supported. Trying -shared option with compiler." >&2;} + DSONAME="libfltk.so.$FL_API_VERSION" + FLDSONAME="libfltk_forms.so.$FL_API_VERSION" + GLDSONAME="libfltk_gl.so.$FL_API_VERSION" + IMGDSONAME="libfltk_images.so.$FL_API_VERSION" + DSOCOMMAND="\$(CXX) -Wl,-soname,\$@ \$(LDLIBS) -shared $DEBUGFLAG -o" + ;; + esac + + LINKSHARED="-L../src -lfltk_images$SHAREDSUFFIX -lfltk_forms$SHAREDSUFFIX -lfltk$SHAREDSUFFIX" +else + DSOCOMMAND="echo" + DSOLINK="" + DSONAME="" + FLDSONAME="" + GLDSONAME="" + IMGDSONAME="" + PICFLAG=0 + SHAREDSUFFIX="" + FLUID="fluid" + LINKSHARED="../lib/libfltk_images.a ../lib/libfltk_forms.a ../lib/libfltk.a" +fi + + + + + + + + + + + +# Check whether --enable-threads or --disable-threads was given. +if test "${enable_threads+set}" = set; then + enableval="$enable_threads" + +fi; + + +# Check whether --with-optim or --without-optim was given. +if test "${with_optim+set}" = set; then + withval="$with_optim" + +fi; + +case $uname in + Darwin*) + # Check whether --enable-quartz or --disable-quartz was given. +if test "${enable_quartz+set}" = set; then + enableval="$enable_quartz" + +fi; + if test "x$enable_quartz" = "xyes"; then + cat >>confdefs.h <<\_ACEOF +#define USE_QUARTZ 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define __APPLE_QUARTZ__ 1 +_ACEOF + + else + cat >>confdefs.h <<\_ACEOF +#define __APPLE_QD__ 1 +_ACEOF + + fi + ;; +esac + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 + (eval $ac_compiler --version </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 + (eval $ac_compiler -v </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 + (eval $ac_compiler -V </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std1 is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std1. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include <stdlib.h> +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CXX" && break +done +test -n "$ac_ct_CXX" || ac_ct_CXX="g++" + + CXX=$ac_ct_CXX +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 + (eval $ac_compiler --version </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 + (eval $ac_compiler -v </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 + (eval $ac_compiler -V </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +CXXFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cxx_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include <stdlib.h> +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +# Extract the first word of "nroff", so it can be a program name with args. +set dummy nroff; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_NROFF+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $NROFF in + [\\/]* | ?:[\\/]*) + ac_cv_path_NROFF="$NROFF" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_NROFF="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +NROFF=$ac_cv_path_NROFF + +if test -n "$NROFF"; then + echo "$as_me:$LINENO: result: $NROFF" >&5 +echo "${ECHO_T}$NROFF" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test "x$NROFF" = "x:"; then + # Extract the first word of "groff", so it can be a program name with args. +set dummy groff; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_GROFF+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GROFF in + [\\/]* | ?:[\\/]*) + ac_cv_path_GROFF="$GROFF" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GROFF="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +GROFF=$ac_cv_path_GROFF + +if test -n "$GROFF"; then + echo "$as_me:$LINENO: result: $GROFF" >&5 +echo "${ECHO_T}$GROFF" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + if test "x$GROFF" = "x:"; then + NROFF="echo" + else + NROFF="$GROFF -T ascii" + fi +fi +# Extract the first word of "htmldoc", so it can be a program name with args. +set dummy htmldoc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_HTMLDOC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $HTMLDOC in + [\\/]* | ?:[\\/]*) + ac_cv_path_HTMLDOC="$HTMLDOC" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_HTMLDOC="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +HTMLDOC=$ac_cv_path_HTMLDOC + +if test -n "$HTMLDOC"; then + echo "$as_me:$LINENO: result: $HTMLDOC" >&5 +echo "${ECHO_T}$HTMLDOC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + RANLIB=$ac_ct_RANLIB +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +# Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $AR in + [\\/]* | ?:[\\/]*) + ac_cv_path_AR="$AR" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_AR="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +AR=$ac_cv_path_AR + +if test -n "$AR"; then + echo "$as_me:$LINENO: result: $AR" >&5 +echo "${ECHO_T}$AR" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + +if test "x$AR" = "x:"; then + { { echo "$as_me:$LINENO: error: Configure could not find the library archiver" >&5 +echo "$as_me: error: Configure could not find the library archiver" >&2;} + { (exit aborting.); exit aborting.; }; } +fi + +if test "x$RANLIB" != "x:"; then + LIBCOMMAND="$AR cr" +else + LIBCOMMAND="$AR crs" +fi + + + + +echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 +echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 +if test "${ac_cv_c_bigendian+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # See if sys/param.h defines the BYTE_ORDER macro. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/param.h> + +int +main () +{ +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + # It does; now see whether it defined to BIG_ENDIAN or not. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/param.h> + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_bigendian=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +# It does not; compile a test program. +if test "$cross_compiling" = yes; then + # try to guess the endianness by grepping values into an object file + ac_cv_c_bigendian=unknown + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; +short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } +short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; +void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } +int +main () +{ + _ascii (); _ebcdic (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then + ac_cv_c_bigendian=yes +fi +if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +int +main () +{ + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long l; + char c[sizeof (long)]; + } u; + u.l = 1; + exit (u.c[sizeof (long) - 1] == 1); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_bigendian=yes +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 +echo "${ECHO_T}$ac_cv_c_bigendian" >&6 +case $ac_cv_c_bigendian in + yes) + +cat >>confdefs.h <<\_ACEOF +#define WORDS_BIGENDIAN 1 +_ACEOF + ;; + no) + ;; + *) + { { echo "$as_me:$LINENO: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&5 +echo "$as_me: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ctype.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +echo "$as_me:$LINENO: checking for short" >&5 +echo $ECHO_N "checking for short... $ECHO_C" >&6 +if test "${ac_cv_type_short+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((short *) 0) + return 0; +if (sizeof (short)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_short=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_short=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_short" >&5 +echo "${ECHO_T}$ac_cv_type_short" >&6 + +echo "$as_me:$LINENO: checking size of short" >&5 +echo $ECHO_N "checking size of short... $ECHO_C" >&6 +if test "${ac_cv_sizeof_short+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$ac_cv_type_short" = yes; then + # The cast to unsigned long works around a bug in the HP C Compiler + # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects + # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. + # This bug is HP SR number 8606223364. + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (short))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (short))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (short))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (short))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo= ac_hi= +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (short))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr '(' $ac_mid ')' + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof_short=$ac_lo;; +'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (short), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (short), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } ;; +esac +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +long longval () { return (long) (sizeof (short)); } +unsigned long ulongval () { return (long) (sizeof (short)); } +#include <stdio.h> +#include <stdlib.h> +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + exit (1); + if (((long) (sizeof (short))) < 0) + { + long i = longval (); + if (i != ((long) (sizeof (short)))) + exit (1); + fprintf (f, "%ld\n", i); + } + else + { + unsigned long i = ulongval (); + if (i != ((long) (sizeof (short)))) + exit (1); + fprintf (f, "%lu\n", i); + } + exit (ferror (f) || fclose (f) != 0); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_short=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: cannot compute sizeof (short), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (short), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.val +else + ac_cv_sizeof_short=0 +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_short" >&5 +echo "${ECHO_T}$ac_cv_sizeof_short" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_SHORT $ac_cv_sizeof_short +_ACEOF + + +echo "$as_me:$LINENO: checking for int" >&5 +echo $ECHO_N "checking for int... $ECHO_C" >&6 +if test "${ac_cv_type_int+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((int *) 0) + return 0; +if (sizeof (int)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_int=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_int=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5 +echo "${ECHO_T}$ac_cv_type_int" >&6 + +echo "$as_me:$LINENO: checking size of int" >&5 +echo $ECHO_N "checking size of int... $ECHO_C" >&6 +if test "${ac_cv_sizeof_int+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$ac_cv_type_int" = yes; then + # The cast to unsigned long works around a bug in the HP C Compiler + # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects + # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. + # This bug is HP SR number 8606223364. + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (int))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (int))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (int))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo= ac_hi= +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr '(' $ac_mid ')' + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof_int=$ac_lo;; +'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (int), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } ;; +esac +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +long longval () { return (long) (sizeof (int)); } +unsigned long ulongval () { return (long) (sizeof (int)); } +#include <stdio.h> +#include <stdlib.h> +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + exit (1); + if (((long) (sizeof (int))) < 0) + { + long i = longval (); + if (i != ((long) (sizeof (int)))) + exit (1); + fprintf (f, "%ld\n", i); + } + else + { + unsigned long i = ulongval (); + if (i != ((long) (sizeof (int)))) + exit (1); + fprintf (f, "%lu\n", i); + } + exit (ferror (f) || fclose (f) != 0); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_int=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (int), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.val +else + ac_cv_sizeof_int=0 +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5 +echo "${ECHO_T}$ac_cv_sizeof_int" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_INT $ac_cv_sizeof_int +_ACEOF + + +echo "$as_me:$LINENO: checking for long" >&5 +echo $ECHO_N "checking for long... $ECHO_C" >&6 +if test "${ac_cv_type_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((long *) 0) + return 0; +if (sizeof (long)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_long=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_long=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_long" >&5 +echo "${ECHO_T}$ac_cv_type_long" >&6 + +echo "$as_me:$LINENO: checking size of long" >&5 +echo $ECHO_N "checking size of long... $ECHO_C" >&6 +if test "${ac_cv_sizeof_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$ac_cv_type_long" = yes; then + # The cast to unsigned long works around a bug in the HP C Compiler + # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects + # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. + # This bug is HP SR number 8606223364. + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (long))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (long))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (long))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo= ac_hi= +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr '(' $ac_mid ')' + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof_long=$ac_lo;; +'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (long), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } ;; +esac +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +long longval () { return (long) (sizeof (long)); } +unsigned long ulongval () { return (long) (sizeof (long)); } +#include <stdio.h> +#include <stdlib.h> +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + exit (1); + if (((long) (sizeof (long))) < 0) + { + long i = longval (); + if (i != ((long) (sizeof (long)))) + exit (1); + fprintf (f, "%ld\n", i); + } + else + { + unsigned long i = ulongval (); + if (i != ((long) (sizeof (long)))) + exit (1); + fprintf (f, "%lu\n", i); + } + exit (ferror (f) || fclose (f) != 0); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_long=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (long), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.val +else + ac_cv_sizeof_long=0 +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5 +echo "${ECHO_T}$ac_cv_sizeof_long" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + +if test $ac_cv_sizeof_short -eq 2; then + cat >>confdefs.h <<\_ACEOF +#define U16 unsigned short +_ACEOF + +fi +if test $ac_cv_sizeof_int -eq 4; then + cat >>confdefs.h <<\_ACEOF +#define U32 unsigned +_ACEOF + +else + if test $ac_cv_sizeof_long -eq 4; then + cat >>confdefs.h <<\_ACEOF +#define U32 unsigned long +_ACEOF + + fi +fi +if test $ac_cv_sizeof_int -eq 8; then + cat >>confdefs.h <<\_ACEOF +#define U64 unsigned +_ACEOF + +else + if test $ac_cv_sizeof_long -eq 8; then + cat >>confdefs.h <<\_ACEOF +#define U64 unsigned long +_ACEOF + + fi +fi + + +echo "$as_me:$LINENO: checking whether the compiler recognizes bool as a built-in type" >&5 +echo $ECHO_N "checking whether the compiler recognizes bool as a built-in type... $ECHO_C" >&6 +if test "${ac_cv_cxx_bool+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + + + ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int f(int x){return 1;} + int f(char x){return 1;} + int f(bool x){return 1;} + +int +main () +{ + + bool b = true; + return f(b); + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_cxx_bool=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_cxx_bool=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +echo "$as_me:$LINENO: result: $ac_cv_cxx_bool" >&5 +echo "${ECHO_T}$ac_cv_cxx_bool" >&6 + +if test "$ac_cv_cxx_bool" != yes; then + CXXFLAGS="-Dbool=char -Dfalse=0 -Dtrue=1 $CXXFLAGS" +fi + + + + + + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 +echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6 +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +ac_cv_search_opendir=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char opendir (); +int +main () +{ +opendir (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir="none required" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test "$ac_cv_search_opendir" = no; then + for ac_lib in dir; do + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char opendir (); +int +main () +{ +opendir (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir="-l$ac_lib" +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done +fi +LIBS=$ac_func_search_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6 +if test "$ac_cv_search_opendir" != no; then + test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS" + +fi + +else + echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6 +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +ac_cv_search_opendir=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char opendir (); +int +main () +{ +opendir (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir="none required" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test "$ac_cv_search_opendir" = no; then + for ac_lib in x; do + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char opendir (); +int +main () +{ +opendir (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir="-l$ac_lib" +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done +fi +LIBS=$ac_func_search_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6 +if test "$ac_cv_search_opendir" != no; then + test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS" + +fi + +fi + +if test "${ac_cv_header_sys_select_h+set}" = set; then + echo "$as_me:$LINENO: checking for sys/select.h" >&5 +echo $ECHO_N "checking for sys/select.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_select_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_select_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_select_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking sys/select.h usability" >&5 +echo $ECHO_N "checking sys/select.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <sys/select.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking sys/select.h presence" >&5 +echo $ECHO_N "checking sys/select.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/select.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: sys/select.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: sys/select.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/select.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: sys/select.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: sys/select.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: sys/select.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/select.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: sys/select.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/select.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: sys/select.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/select.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: sys/select.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/select.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: sys/select.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/select.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: sys/select.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for sys/select.h" >&5 +echo $ECHO_N "checking for sys/select.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_select_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_sys_select_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_select_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_select_h" >&6 + +fi +if test $ac_cv_header_sys_select_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_SYS_SELECT_H 1 +_ACEOF + +fi + + +if test "${ac_cv_header_sys_stdtypes_h+set}" = set; then + echo "$as_me:$LINENO: checking for sys/stdtypes.h" >&5 +echo $ECHO_N "checking for sys/stdtypes.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_stdtypes_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_stdtypes_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_stdtypes_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking sys/stdtypes.h usability" >&5 +echo $ECHO_N "checking sys/stdtypes.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <sys/stdtypes.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking sys/stdtypes.h presence" >&5 +echo $ECHO_N "checking sys/stdtypes.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/stdtypes.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: sys/stdtypes.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: sys/stdtypes.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/stdtypes.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: sys/stdtypes.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: sys/stdtypes.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: sys/stdtypes.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/stdtypes.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: sys/stdtypes.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/stdtypes.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: sys/stdtypes.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/stdtypes.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: sys/stdtypes.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/stdtypes.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: sys/stdtypes.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/stdtypes.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: sys/stdtypes.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for sys/stdtypes.h" >&5 +echo $ECHO_N "checking for sys/stdtypes.h... $ECHO_C" >&6 +if test "${ac_cv_header_sys_stdtypes_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_sys_stdtypes_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sys_stdtypes_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_stdtypes_h" >&6 + +fi +if test $ac_cv_header_sys_stdtypes_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_SYS_SELECT_H 1 +_ACEOF + +fi + + +echo "$as_me:$LINENO: checking for scandir" >&5 +echo $ECHO_N "checking for scandir... $ECHO_C" >&6 +if test "${ac_cv_func_scandir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define scandir to an innocuous variant, in case <limits.h> declares scandir. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define scandir innocuous_scandir + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char scandir (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef scandir + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char scandir (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_scandir) || defined (__stub___scandir) +choke me +#else +char (*f) () = scandir; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != scandir; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_scandir=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_scandir=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_scandir" >&5 +echo "${ECHO_T}$ac_cv_func_scandir" >&6 +if test $ac_cv_func_scandir = yes; then + if test "x$uname" = xSunOS -o "x$uname" = xQNX; then + { echo "$as_me:$LINENO: WARNING: Not using $uname scandir emulation function." >&5 +echo "$as_me: WARNING: Not using $uname scandir emulation function." >&2;} + else + cat >>confdefs.h <<\_ACEOF +#define HAVE_SCANDIR 1 +_ACEOF + + fi +fi + +echo "$as_me:$LINENO: checking for vsnprintf" >&5 +echo $ECHO_N "checking for vsnprintf... $ECHO_C" >&6 +if test "${ac_cv_func_vsnprintf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define vsnprintf to an innocuous variant, in case <limits.h> declares vsnprintf. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define vsnprintf innocuous_vsnprintf + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char vsnprintf (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef vsnprintf + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char vsnprintf (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_vsnprintf) || defined (__stub___vsnprintf) +choke me +#else +char (*f) () = vsnprintf; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != vsnprintf; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_vsnprintf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_vsnprintf=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_vsnprintf" >&5 +echo "${ECHO_T}$ac_cv_func_vsnprintf" >&6 +if test $ac_cv_func_vsnprintf = yes; then + + case "$uname" in + HP-UX*) + if test "$uversion" = "1020"; then + { echo "$as_me:$LINENO: WARNING: Not using built-in vsnprintf function because you are running HP-UX 10.20." >&5 +echo "$as_me: WARNING: Not using built-in vsnprintf function because you are running HP-UX 10.20." >&2;} + else + cat >>confdefs.h <<\_ACEOF +#define HAVE_VSNPRINTF 1 +_ACEOF + + fi + ;; + + OSF1*) + if test "$uversion" = "40"; then + { echo "$as_me:$LINENO: WARNING: Not using built-in vsnprintf function because you are running Tru64 4.0." >&5 +echo "$as_me: WARNING: Not using built-in vsnprintf function because you are running Tru64 4.0." >&2;} + else + cat >>confdefs.h <<\_ACEOF +#define HAVE_VSNPRINTF 1 +_ACEOF + + fi + ;; + + *) + cat >>confdefs.h <<\_ACEOF +#define HAVE_VSNPRINTF 1 +_ACEOF + + ;; + esac +fi + +echo "$as_me:$LINENO: checking for snprintf" >&5 +echo $ECHO_N "checking for snprintf... $ECHO_C" >&6 +if test "${ac_cv_func_snprintf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define snprintf to an innocuous variant, in case <limits.h> declares snprintf. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define snprintf innocuous_snprintf + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char snprintf (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef snprintf + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char snprintf (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_snprintf) || defined (__stub___snprintf) +choke me +#else +char (*f) () = snprintf; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != snprintf; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_snprintf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_snprintf=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_snprintf" >&5 +echo "${ECHO_T}$ac_cv_func_snprintf" >&6 +if test $ac_cv_func_snprintf = yes; then + + case "$uname" in + HP-UX*) + if test "$uversion" = "1020"; then + { echo "$as_me:$LINENO: WARNING: Not using built-in snprintf function because you are running HP-UX 10.20." >&5 +echo "$as_me: WARNING: Not using built-in snprintf function because you are running HP-UX 10.20." >&2;} + else + cat >>confdefs.h <<\_ACEOF +#define HAVE_SNPRINTF 1 +_ACEOF + + fi + ;; + + OSF1*) + if test "$uversion" = "40"; then + { echo "$as_me:$LINENO: WARNING: Not using built-in snprintf function because you are running Tru64 4.0." >&5 +echo "$as_me: WARNING: Not using built-in snprintf function because you are running Tru64 4.0." >&2;} + else + cat >>confdefs.h <<\_ACEOF +#define HAVE_SNPRINTF 1 +_ACEOF + + fi + ;; + + *) + cat >>confdefs.h <<\_ACEOF +#define HAVE_SNPRINTF 1 +_ACEOF + + ;; + esac +fi + +if test "${ac_cv_header_strings_h+set}" = set; then + echo "$as_me:$LINENO: checking for strings.h" >&5 +echo $ECHO_N "checking for strings.h... $ECHO_C" >&6 +if test "${ac_cv_header_strings_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_strings_h" >&5 +echo "${ECHO_T}$ac_cv_header_strings_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking strings.h usability" >&5 +echo $ECHO_N "checking strings.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <strings.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking strings.h presence" >&5 +echo $ECHO_N "checking strings.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <strings.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: strings.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: strings.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: strings.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: strings.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: strings.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: strings.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: strings.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: strings.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: strings.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: strings.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: strings.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: strings.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: strings.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: strings.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: strings.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: strings.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for strings.h" >&5 +echo $ECHO_N "checking for strings.h... $ECHO_C" >&6 +if test "${ac_cv_header_strings_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_strings_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_strings_h" >&5 +echo "${ECHO_T}$ac_cv_header_strings_h" >&6 + +fi +if test $ac_cv_header_strings_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_STRINGS_H 1 +_ACEOF + +fi + + + + + +for ac_func in strcasecmp strlcat strlcpy +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +if test "${ac_cv_header_locale_h+set}" = set; then + echo "$as_me:$LINENO: checking for locale.h" >&5 +echo $ECHO_N "checking for locale.h... $ECHO_C" >&6 +if test "${ac_cv_header_locale_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_locale_h" >&5 +echo "${ECHO_T}$ac_cv_header_locale_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking locale.h usability" >&5 +echo $ECHO_N "checking locale.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <locale.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking locale.h presence" >&5 +echo $ECHO_N "checking locale.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <locale.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: locale.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: locale.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: locale.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: locale.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: locale.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: locale.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: locale.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: locale.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: locale.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: locale.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: locale.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: locale.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: locale.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: locale.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: locale.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: locale.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for locale.h" >&5 +echo $ECHO_N "checking for locale.h... $ECHO_C" >&6 +if test "${ac_cv_header_locale_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_locale_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_locale_h" >&5 +echo "${ECHO_T}$ac_cv_header_locale_h" >&6 + +fi +if test $ac_cv_header_locale_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_LOCALE_H 1 +_ACEOF + +fi + + + +for ac_func in localeconv +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +echo "$as_me:$LINENO: checking for library containing pow" >&5 +echo $ECHO_N "checking for library containing pow... $ECHO_C" >&6 +if test "${ac_cv_search_pow+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +ac_cv_search_pow=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pow (); +int +main () +{ +pow (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_pow="none required" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test "$ac_cv_search_pow" = no; then + for ac_lib in m; do + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pow (); +int +main () +{ +pow (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_pow="-l$ac_lib" +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done +fi +LIBS=$ac_func_search_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_search_pow" >&5 +echo "${ECHO_T}$ac_cv_search_pow" >&6 +if test "$ac_cv_search_pow" != no; then + test "$ac_cv_search_pow" = "none required" || LIBS="$ac_cv_search_pow $LIBS" + +fi + + +# Check whether --enable-largefile or --disable-largefile was given. +if test "${enable_largefile+set}" = set; then + enableval="$enable_largefile" + +fi; +if test "$enable_largefile" != no; then + + echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5 +echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6 +if test "${ac_cv_sys_largefile_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_sys_largefile_CC=no + if test "$GCC" != yes; then + ac_save_CC=$CC + while :; do + # IRIX 6.2 and later do not support large files by default, + # so use the C compiler's -n32 option if that helps. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext + CC="$CC -n32" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sys_largefile_CC=' -n32'; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext + break + done + CC=$ac_save_CC + rm -f conftest.$ac_ext + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5 +echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6 + if test "$ac_cv_sys_largefile_CC" != no; then + CC=$CC$ac_cv_sys_largefile_CC + fi + + echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5 +echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6 +if test "${ac_cv_sys_file_offset_bits+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + while :; do + ac_cv_sys_file_offset_bits=no + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _FILE_OFFSET_BITS 64 +#include <sys/types.h> + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sys_file_offset_bits=64; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + break +done +fi +echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5 +echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6 +if test "$ac_cv_sys_file_offset_bits" != no; then + +cat >>confdefs.h <<_ACEOF +#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits +_ACEOF + +fi +rm -f conftest* + echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5 +echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6 +if test "${ac_cv_sys_large_files+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + while :; do + ac_cv_sys_large_files=no + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _LARGE_FILES 1 +#include <sys/types.h> + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sys_large_files=1; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + break +done +fi +echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5 +echo "${ECHO_T}$ac_cv_sys_large_files" >&6 +if test "$ac_cv_sys_large_files" != no; then + +cat >>confdefs.h <<_ACEOF +#define _LARGE_FILES $ac_cv_sys_large_files +_ACEOF + +fi +rm -f conftest* +fi + + +LARGEFILE="" +if test x$enable_largefile != xno; then + LARGEFILE="-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE" + + if test $ac_cv_sys_large_files = 1; then + LARGEFILE="$LARGEFILE -D_LARGE_FILES" + fi + + if test $ac_cv_sys_file_offset_bits = 64; then + LARGEFILE="$LARGEFILE -D_FILE_OFFSET_BITS=64" + fi +fi + + +echo "$as_me:$LINENO: checking for long long int" >&5 +echo $ECHO_N "checking for long long int... $ECHO_C" >&6 +if test "${ac_cv_c_long_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$GCC" = yes; then + ac_cv_c_long_long=yes + else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +long long int i; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_long_long=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_long_long=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_c_long_long" >&5 +echo "${ECHO_T}$ac_cv_c_long_long" >&6 + +if test $ac_cv_c_long_long = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_LONG_LONG 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for strtoll" >&5 +echo $ECHO_N "checking for strtoll... $ECHO_C" >&6 +if test "${ac_cv_func_strtoll+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define strtoll to an innocuous variant, in case <limits.h> declares strtoll. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define strtoll innocuous_strtoll + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char strtoll (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef strtoll + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strtoll (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_strtoll) || defined (__stub___strtoll) +choke me +#else +char (*f) () = strtoll; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != strtoll; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_strtoll=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_strtoll=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_strtoll" >&5 +echo "${ECHO_T}$ac_cv_func_strtoll" >&6 +if test $ac_cv_func_strtoll = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_STRTOLL 1 +_ACEOF + +fi + + +AUDIOLIBS="" + +case $uname in + CYGWIN* | MINGW*) + AUDIOLIBS="-lwinmm" + ;; + + Darwin*) + AUDIOLIBS="-framework CoreAudio" + ;; + + *) + if test "${ac_cv_header_alsa_asoundlib_h+set}" = set; then + echo "$as_me:$LINENO: checking for alsa/asoundlib.h" >&5 +echo $ECHO_N "checking for alsa/asoundlib.h... $ECHO_C" >&6 +if test "${ac_cv_header_alsa_asoundlib_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_alsa_asoundlib_h" >&5 +echo "${ECHO_T}$ac_cv_header_alsa_asoundlib_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking alsa/asoundlib.h usability" >&5 +echo $ECHO_N "checking alsa/asoundlib.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <alsa/asoundlib.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking alsa/asoundlib.h presence" >&5 +echo $ECHO_N "checking alsa/asoundlib.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <alsa/asoundlib.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: alsa/asoundlib.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: alsa/asoundlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: alsa/asoundlib.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: alsa/asoundlib.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: alsa/asoundlib.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: alsa/asoundlib.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: alsa/asoundlib.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: alsa/asoundlib.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: alsa/asoundlib.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: alsa/asoundlib.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: alsa/asoundlib.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: alsa/asoundlib.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: alsa/asoundlib.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: alsa/asoundlib.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: alsa/asoundlib.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: alsa/asoundlib.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for alsa/asoundlib.h" >&5 +echo $ECHO_N "checking for alsa/asoundlib.h... $ECHO_C" >&6 +if test "${ac_cv_header_alsa_asoundlib_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_alsa_asoundlib_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_alsa_asoundlib_h" >&5 +echo "${ECHO_T}$ac_cv_header_alsa_asoundlib_h" >&6 + +fi +if test $ac_cv_header_alsa_asoundlib_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_ALSA_ASOUNDLIB_H 1 +_ACEOF + + AUDIOLIBS="-lasound" +fi + + + ;; +esac + + + +SAVELIBS="$LIBS" +IMAGELIBS="" + + + +# Check whether --enable-localjpeg or --disable-localjpeg was given. +if test "${enable_localjpeg+set}" = set; then + enableval="$enable_localjpeg" + if test x$enable_localjpeg = xyes; then + ac_cv_lib_jpeg_jpeg_CreateCompress=no + fi +fi; + +echo "$as_me:$LINENO: checking for jpeg_CreateCompress in -ljpeg" >&5 +echo $ECHO_N "checking for jpeg_CreateCompress in -ljpeg... $ECHO_C" >&6 +if test "${ac_cv_lib_jpeg_jpeg_CreateCompress+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ljpeg $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char jpeg_CreateCompress (); +int +main () +{ +jpeg_CreateCompress (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_jpeg_jpeg_CreateCompress=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_jpeg_jpeg_CreateCompress=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_jpeg_jpeg_CreateCompress" >&5 +echo "${ECHO_T}$ac_cv_lib_jpeg_jpeg_CreateCompress" >&6 +if test $ac_cv_lib_jpeg_jpeg_CreateCompress = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBJPEG 1 +_ACEOF + + JPEGINC="" + JPEG="" + IMAGELIBS="-ljpeg $IMAGELIBS" +else + if test x$enable_localjpeg = xno; then + JPEGINC="" + JPEG="" + else + cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBJPEG 1 +_ACEOF + + JPEGINC="-I../jpeg" + JPEG="jpeg" + IMAGELIBS="-lfltk_jpeg $IMAGELIBS" + fi +fi + + +# Check whether --enable-localzlib or --disable-localzlib was given. +if test "${enable_localzlib+set}" = set; then + enableval="$enable_localzlib" + if test x$enable_localzlib = xyes; then + ac_cv_lib_z_gzgets=no + fi +fi; + +echo "$as_me:$LINENO: checking for gzgets in -lz" >&5 +echo $ECHO_N "checking for gzgets in -lz... $ECHO_C" >&6 +if test "${ac_cv_lib_z_gzgets+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gzgets (); +int +main () +{ +gzgets (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_z_gzgets=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_z_gzgets=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_z_gzgets" >&5 +echo "${ECHO_T}$ac_cv_lib_z_gzgets" >&6 +if test $ac_cv_lib_z_gzgets = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBZ 1 +_ACEOF + + ZLIBINC="" + ZLIB="" + LIBS="-lz $LIBS" + IMAGELIBS="-lz $IMAGELIBS" +else + if test x$enable_localzlib = xno; then + ZLIBINC="" + ZLIB="" + else + cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBZ 1 +_ACEOF + + ZLIBINC="-I../zlib" + ZLIB="zlib" + LIBS="-lfltk_z $LIBS" + IMAGELIBS="-lfltk_z $IMAGELIBS" + fi +fi + + +# Check whether --enable-localpng or --disable-localpng was given. +if test "${enable_localpng+set}" = set; then + enableval="$enable_localpng" + if test x$enable_localpng = xyes; then + ac_cv_lib_png_png_set_tRNS_to_alpha=no + fi +fi; + +echo "$as_me:$LINENO: checking for png_set_tRNS_to_alpha in -lpng" >&5 +echo $ECHO_N "checking for png_set_tRNS_to_alpha in -lpng... $ECHO_C" >&6 +if test "${ac_cv_lib_png_png_set_tRNS_to_alpha+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpng $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char png_set_tRNS_to_alpha (); +int +main () +{ +png_set_tRNS_to_alpha (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_png_png_set_tRNS_to_alpha=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_png_png_set_tRNS_to_alpha=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_png_png_set_tRNS_to_alpha" >&5 +echo "${ECHO_T}$ac_cv_lib_png_png_set_tRNS_to_alpha" >&6 +if test $ac_cv_lib_png_png_set_tRNS_to_alpha = yes; then + + PNGINC="" + PNG="" + IMAGELIBS="-lpng $IMAGELIBS" + cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBPNG 1 +_ACEOF + + if test "${ac_cv_header_png_h+set}" = set; then + echo "$as_me:$LINENO: checking for png.h" >&5 +echo $ECHO_N "checking for png.h... $ECHO_C" >&6 +if test "${ac_cv_header_png_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_png_h" >&5 +echo "${ECHO_T}$ac_cv_header_png_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking png.h usability" >&5 +echo $ECHO_N "checking png.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <png.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking png.h presence" >&5 +echo $ECHO_N "checking png.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <png.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: png.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: png.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: png.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: png.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: png.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: png.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: png.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: png.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: png.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: png.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for png.h" >&5 +echo $ECHO_N "checking for png.h... $ECHO_C" >&6 +if test "${ac_cv_header_png_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_png_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_png_h" >&5 +echo "${ECHO_T}$ac_cv_header_png_h" >&6 + +fi +if test $ac_cv_header_png_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_PNG_H 1 +_ACEOF + +fi + + +else + + if test x$enable_localpng = xno; then + PNGINC="" + PNG="" + else + cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBPNG 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define HAVE_PNG_H 1 +_ACEOF + + PNGINC="-I../png" + PNG="png" + IMAGELIBS="-lfltk_png $IMAGELIBS" + fi +fi + + + + + + + + + +LIBS="$SAVELIBS" + + + +have_pthread=no + +if test "x$enable_threads" = xyes; then + if test "${ac_cv_header_pthread_h+set}" = set; then + echo "$as_me:$LINENO: checking for pthread.h" >&5 +echo $ECHO_N "checking for pthread.h... $ECHO_C" >&6 +if test "${ac_cv_header_pthread_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_pthread_h" >&5 +echo "${ECHO_T}$ac_cv_header_pthread_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking pthread.h usability" >&5 +echo $ECHO_N "checking pthread.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <pthread.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking pthread.h presence" >&5 +echo $ECHO_N "checking pthread.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <pthread.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: pthread.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: pthread.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: pthread.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: pthread.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: pthread.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: pthread.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: pthread.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: pthread.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: pthread.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: pthread.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: pthread.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: pthread.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: pthread.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: pthread.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: pthread.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: pthread.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for pthread.h" >&5 +echo $ECHO_N "checking for pthread.h... $ECHO_C" >&6 +if test "${ac_cv_header_pthread_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_pthread_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_pthread_h" >&5 +echo "${ECHO_T}$ac_cv_header_pthread_h" >&6 + +fi +if test $ac_cv_header_pthread_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTHREAD_H 1 +_ACEOF + +fi + + + +echo "$as_me:$LINENO: checking for pthread_create in -lpthread" >&5 +echo $ECHO_N "checking for pthread_create in -lpthread... $ECHO_C" >&6 +if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pthread_create (); +int +main () +{ +pthread_create (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_pthread_pthread_create=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_pthread_pthread_create=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_create" >&5 +echo "${ECHO_T}$ac_cv_lib_pthread_pthread_create" >&6 +if test $ac_cv_lib_pthread_pthread_create = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPTHREAD 1 +_ACEOF + + LIBS="-lpthread $LIBS" + +fi + + + if test "x$ac_cv_lib_pthread_pthread_create" = xyes -a x$ac_cv_header_pthread_h = xyes; then + have_pthread=yes + else + echo "$as_me:$LINENO: checking for pthread_create using -pthread" >&5 +echo $ECHO_N "checking for pthread_create using -pthread... $ECHO_C" >&6 + SAVELIBS="$LIBS" + LIBS="-pthread $LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <pthread.h> +int +main () +{ +pthread_create(0, 0, 0, 0); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + LIBS="-pthread $SAVELIBS" + have_pthread=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +LIBS="$SAVELIBS" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + echo "$as_me:$LINENO: result: $have_pthread" >&5 +echo "${ECHO_T}$have_pthread" >&6 + fi +fi + +HLINKS= +POSTBUILD=: +THREADS= + + +# Check whether --with-links or --without-links was given. +if test "${with_links+set}" = set; then + withval="$with_links" + +fi; + +INSTALL_DESKTOP="" +UNINSTALL_DESKTOP="" + +case $uname in + CYGWIN* | MINGW*) + CFLAGS="-mwindows -DWIN32 $CFLAGS" + CXXFLAGS="-mwindows -DWIN32 $CXXFLAGS" + LDFLAGS="-mwindows $LDFLAGS" + LIBS="$LIBS -lole32 -luuid -lcomctl32 -lwsock32" + OPTIM="$OPTIM" + + if test x$enable_gl != xno; then + if test "${ac_cv_header_GL_gl_h+set}" = set; then + echo "$as_me:$LINENO: checking for GL/gl.h" >&5 +echo $ECHO_N "checking for GL/gl.h... $ECHO_C" >&6 +if test "${ac_cv_header_GL_gl_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_GL_gl_h" >&5 +echo "${ECHO_T}$ac_cv_header_GL_gl_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking GL/gl.h usability" >&5 +echo $ECHO_N "checking GL/gl.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <GL/gl.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking GL/gl.h presence" >&5 +echo $ECHO_N "checking GL/gl.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <GL/gl.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: GL/gl.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: GL/gl.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: GL/gl.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: GL/gl.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: GL/gl.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: GL/gl.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: GL/gl.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: GL/gl.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: GL/gl.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: GL/gl.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for GL/gl.h" >&5 +echo $ECHO_N "checking for GL/gl.h... $ECHO_C" >&6 +if test "${ac_cv_header_GL_gl_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_GL_gl_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_GL_gl_h" >&5 +echo "${ECHO_T}$ac_cv_header_GL_gl_h" >&6 + +fi +if test $ac_cv_header_GL_gl_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_GL 1 +_ACEOF + + GLLIB="-lopengl32" +fi + + + if test "${ac_cv_header_GL_glu_h+set}" = set; then + echo "$as_me:$LINENO: checking for GL/glu.h" >&5 +echo $ECHO_N "checking for GL/glu.h... $ECHO_C" >&6 +if test "${ac_cv_header_GL_glu_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_GL_glu_h" >&5 +echo "${ECHO_T}$ac_cv_header_GL_glu_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking GL/glu.h usability" >&5 +echo $ECHO_N "checking GL/glu.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <GL/glu.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking GL/glu.h presence" >&5 +echo $ECHO_N "checking GL/glu.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <GL/glu.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: GL/glu.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: GL/glu.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/glu.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: GL/glu.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: GL/glu.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: GL/glu.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/glu.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: GL/glu.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/glu.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: GL/glu.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/glu.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: GL/glu.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/glu.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: GL/glu.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/glu.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: GL/glu.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for GL/glu.h" >&5 +echo $ECHO_N "checking for GL/glu.h... $ECHO_C" >&6 +if test "${ac_cv_header_GL_glu_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_GL_glu_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_GL_glu_h" >&5 +echo "${ECHO_T}$ac_cv_header_GL_glu_h" >&6 + +fi +if test $ac_cv_header_GL_glu_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_GL_GLU_H 1 +_ACEOF + + GLLIB="-lglu32 $GLLIB" +fi + + + else + LINKFLTKGL="" + GLLIBNAME="" + GLDSONAME="" + GLDEMOS="" + fi + + if test "x$enable_threads" = xyes; then + if test x$have_pthread = xyes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTHREAD 1 +_ACEOF + + fi + + THREADS="threads.exe" + fi + + # Don't make symlinks since Windows is not case sensitive. + if test "x$with_links" != xyes; then + HLINKS="#" + fi + ;; + + Darwin*) + # MacOS X uses Carbon for graphics... + LIBS="$LIBS -framework Carbon -framework ApplicationServices" + + if test x$have_pthread = xyes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTHREAD 1 +_ACEOF + + THREADS="threads" + fi + + if test x$enable_gl != xno; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_GL 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define HAVE_GL_GLU_H 1 +_ACEOF + + GLLIB="-framework AGL -framework OpenGL" + else + LINKFLTKGL="" + GLLIBNAME="" + GLDSONAME="" + GLDEMOS="" + fi + + # Don't make symlinks because HFS+ is not case sensitive... + if test "x$with_links" != xyes; then + HLINKS="#" + fi + + # Add a postbuild step after linking applications + POSTBUILD="/Developer/Tools/Rez -t APPL -o" + + # Install/Uninstall FLUID application + INSTALL_DESKTOP="install-osx" + UNINSTALL_DESKTOP="uninstall-osx" + ;; + + *) + # All others are UNIX/X11... + if test x$have_pthread = xyes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTHREAD 1 +_ACEOF + + THREADS="threads" + fi + + echo "$as_me:$LINENO: checking for X" >&5 +echo $ECHO_N "checking for X... $ECHO_C" >&6 + + +# Check whether --with-x or --without-x was given. +if test "${with_x+set}" = set; then + withval="$with_x" + +fi; +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then + # Both variables are already set. + have_x=yes + else + if test "${ac_cv_have_x+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=no ac_x_libraries=no +rm -fr conftest.dir +if mkdir conftest.dir; then + cd conftest.dir + # Make sure to not put "make" in the Imakefile rules, since we grep it out. + cat >Imakefile <<'_ACEOF' +acfindx: + @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"' +_ACEOF + if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering...", which would confuse us. + eval `${MAKE-make} acfindx 2>/dev/null | grep -v make` + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl; do + if test ! -f $ac_im_usrlibdir/libX11.$ac_extension && + test -f $ac_im_libdir/libX11.$ac_extension; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case $ac_im_incroot in + /usr/include) ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; + esac + case $ac_im_usrlibdir in + /usr/lib | /lib) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; + esac + fi + cd .. + rm -fr conftest.dir +fi + +# Standard set of common directories for X headers. +# Check X11 before X11Rn because it is often a symlink to the current release. +ac_x_header_dirs=' +/usr/X11/include +/usr/X11R6/include +/usr/X11R5/include +/usr/X11R4/include + +/usr/include/X11 +/usr/include/X11R6 +/usr/include/X11R5 +/usr/include/X11R4 + +/usr/local/X11/include +/usr/local/X11R6/include +/usr/local/X11R5/include +/usr/local/X11R4/include + +/usr/local/include/X11 +/usr/local/include/X11R6 +/usr/local/include/X11R5 +/usr/local/include/X11R4 + +/usr/X386/include +/usr/x386/include +/usr/XFree86/include/X11 + +/usr/include +/usr/local/include +/usr/unsupported/include +/usr/athena/include +/usr/local/x11r5/include +/usr/lpp/Xamples/include + +/usr/openwin/include +/usr/openwin/share/include' + +if test "$ac_x_includes" = no; then + # Guess where to find include files, by looking for Intrinsic.h. + # First, try using that file with no special directory specified. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <X11/Intrinsic.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # We can compile using X headers with no special include directory. +ac_x_includes= +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + for ac_dir in $ac_x_header_dirs; do + if test -r "$ac_dir/X11/Intrinsic.h"; then + ac_x_includes=$ac_dir + break + fi +done +fi +rm -f conftest.err conftest.$ac_ext +fi # $ac_x_includes = no + +if test "$ac_x_libraries" = no; then + # Check for the libraries. + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS=$LIBS + LIBS="-lXt $LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <X11/Intrinsic.h> +int +main () +{ +XtMalloc (0) + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + LIBS=$ac_save_LIBS +# We can link X programs with no special library path. +ac_x_libraries= +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +LIBS=$ac_save_LIBS +for ac_dir in `echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` +do + # Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl; do + if test -r $ac_dir/libXt.$ac_extension; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi # $ac_x_libraries = no + +if test "$ac_x_includes" = no || test "$ac_x_libraries" = no; then + # Didn't find X anywhere. Cache the known absence of X. + ac_cv_have_x="have_x=no" +else + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries" +fi +fi + + fi + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + echo "$as_me:$LINENO: result: $have_x" >&5 +echo "${ECHO_T}$have_x" >&6 + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$x_includes ac_x_libraries=$x_libraries" + echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5 +echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6 +fi + +if test "$no_x" = yes; then + # Not all programs may use this symbol, but it does not hurt to define it. + +cat >>confdefs.h <<\_ACEOF +#define X_DISPLAY_MISSING 1 +_ACEOF + + X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= +else + if test -n "$x_includes"; then + X_CFLAGS="$X_CFLAGS -I$x_includes" + fi + + # It would also be nice to do this for all -L options, not just this one. + if test -n "$x_libraries"; then + X_LIBS="$X_LIBS -L$x_libraries" + # For Solaris; some versions of Sun CC require a space after -R and + # others require no space. Words are not sufficient . . . . + case `(uname -sr) 2>/dev/null` in + "SunOS 5"*) + echo "$as_me:$LINENO: checking whether -R must be followed by a space" >&5 +echo $ECHO_N "checking whether -R must be followed by a space... $ECHO_C" >&6 + ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_R_nospace=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_R_nospace=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test $ac_R_nospace = yes; then + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + X_LIBS="$X_LIBS -R$x_libraries" + else + LIBS="$ac_xsave_LIBS -R $x_libraries" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_R_space=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_R_space=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test $ac_R_space = yes; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + X_LIBS="$X_LIBS -R $x_libraries" + else + echo "$as_me:$LINENO: result: neither works" >&5 +echo "${ECHO_T}neither works" >&6 + fi + fi + LIBS=$ac_xsave_LIBS + esac + fi + + # Check for system-dependent libraries X programs must link with. + # Do this before checking for the system-independent R6 libraries + # (-lICE), since we may need -lsocket or whatever for X linking. + + if test "$ISC" = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" + else + # Martyn Johnson says this is needed for Ultrix, if the X + # libraries were built with DECnet support. And Karl Berry says + # the Alpha needs dnet_stub (dnet does not exist). + ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XOpenDisplay (); +int +main () +{ +XOpenDisplay (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet" >&5 +echo $ECHO_N "checking for dnet_ntoa in -ldnet... $ECHO_C" >&6 +if test "${ac_cv_lib_dnet_dnet_ntoa+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dnet_ntoa (); +int +main () +{ +dnet_ntoa (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dnet_dnet_ntoa=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dnet_dnet_ntoa=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 +echo "${ECHO_T}$ac_cv_lib_dnet_dnet_ntoa" >&6 +if test $ac_cv_lib_dnet_dnet_ntoa = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" +fi + + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet_stub" >&5 +echo $ECHO_N "checking for dnet_ntoa in -ldnet_stub... $ECHO_C" >&6 +if test "${ac_cv_lib_dnet_stub_dnet_ntoa+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet_stub $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dnet_ntoa (); +int +main () +{ +dnet_ntoa (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dnet_stub_dnet_ntoa=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dnet_stub_dnet_ntoa=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 +echo "${ECHO_T}$ac_cv_lib_dnet_stub_dnet_ntoa" >&6 +if test $ac_cv_lib_dnet_stub_dnet_ntoa = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" +fi + + fi +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$ac_xsave_LIBS" + + # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, + # to get the SysV transport functions. + # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) + # needs -lnsl. + # The nsl library prevents programs from opening the X display + # on Irix 5.2, according to T.E. Dickey. + # The functions gethostbyname, getservbyname, and inet_addr are + # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. + echo "$as_me:$LINENO: checking for gethostbyname" >&5 +echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6 +if test "${ac_cv_func_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define gethostbyname to an innocuous variant, in case <limits.h> declares gethostbyname. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define gethostbyname innocuous_gethostbyname + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char gethostbyname (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef gethostbyname + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname) +choke me +#else +char (*f) () = gethostbyname; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != gethostbyname; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6 + + if test $ac_cv_func_gethostbyname = no; then + echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 +echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6 +if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main () +{ +gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_nsl_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_nsl_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6 +if test $ac_cv_lib_nsl_gethostbyname = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" +fi + + if test $ac_cv_lib_nsl_gethostbyname = no; then + echo "$as_me:$LINENO: checking for gethostbyname in -lbsd" >&5 +echo $ECHO_N "checking for gethostbyname in -lbsd... $ECHO_C" >&6 +if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbsd $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main () +{ +gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_bsd_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_bsd_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_bsd_gethostbyname" >&6 +if test $ac_cv_lib_bsd_gethostbyname = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" +fi + + fi + fi + + # lieder@skyler.mavd.honeywell.com says without -lsocket, + # socket/setsockopt and other routines are undefined under SCO ODT + # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary + # on later versions), says Simon Leinen: it contains gethostby* + # variants that don't use the name server (or something). -lsocket + # must be given before -lnsl if both are needed. We assume that + # if connect needs -lnsl, so does gethostbyname. + echo "$as_me:$LINENO: checking for connect" >&5 +echo $ECHO_N "checking for connect... $ECHO_C" >&6 +if test "${ac_cv_func_connect+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define connect to an innocuous variant, in case <limits.h> declares connect. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define connect innocuous_connect + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char connect (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef connect + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char connect (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_connect) || defined (__stub___connect) +choke me +#else +char (*f) () = connect; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != connect; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_connect=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_connect=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5 +echo "${ECHO_T}$ac_cv_func_connect" >&6 + + if test $ac_cv_func_connect = no; then + echo "$as_me:$LINENO: checking for connect in -lsocket" >&5 +echo $ECHO_N "checking for connect in -lsocket... $ECHO_C" >&6 +if test "${ac_cv_lib_socket_connect+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $X_EXTRA_LIBS $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char connect (); +int +main () +{ +connect (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_socket_connect=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_socket_connect=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_socket_connect" >&5 +echo "${ECHO_T}$ac_cv_lib_socket_connect" >&6 +if test $ac_cv_lib_socket_connect = yes; then + X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" +fi + + fi + + # Guillermo Gomez says -lposix is necessary on A/UX. + echo "$as_me:$LINENO: checking for remove" >&5 +echo $ECHO_N "checking for remove... $ECHO_C" >&6 +if test "${ac_cv_func_remove+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define remove to an innocuous variant, in case <limits.h> declares remove. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define remove innocuous_remove + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char remove (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef remove + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char remove (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_remove) || defined (__stub___remove) +choke me +#else +char (*f) () = remove; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != remove; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_remove=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_remove=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_remove" >&5 +echo "${ECHO_T}$ac_cv_func_remove" >&6 + + if test $ac_cv_func_remove = no; then + echo "$as_me:$LINENO: checking for remove in -lposix" >&5 +echo $ECHO_N "checking for remove in -lposix... $ECHO_C" >&6 +if test "${ac_cv_lib_posix_remove+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lposix $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char remove (); +int +main () +{ +remove (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_posix_remove=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_posix_remove=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_posix_remove" >&5 +echo "${ECHO_T}$ac_cv_lib_posix_remove" >&6 +if test $ac_cv_lib_posix_remove = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" +fi + + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + echo "$as_me:$LINENO: checking for shmat" >&5 +echo $ECHO_N "checking for shmat... $ECHO_C" >&6 +if test "${ac_cv_func_shmat+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define shmat to an innocuous variant, in case <limits.h> declares shmat. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define shmat innocuous_shmat + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shmat (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef shmat + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shmat (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_shmat) || defined (__stub___shmat) +choke me +#else +char (*f) () = shmat; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != shmat; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_shmat=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_shmat=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_shmat" >&5 +echo "${ECHO_T}$ac_cv_func_shmat" >&6 + + if test $ac_cv_func_shmat = no; then + echo "$as_me:$LINENO: checking for shmat in -lipc" >&5 +echo $ECHO_N "checking for shmat in -lipc... $ECHO_C" >&6 +if test "${ac_cv_lib_ipc_shmat+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lipc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shmat (); +int +main () +{ +shmat (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_ipc_shmat=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_ipc_shmat=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_ipc_shmat" >&5 +echo "${ECHO_T}$ac_cv_lib_ipc_shmat" >&6 +if test $ac_cv_lib_ipc_shmat = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" +fi + + fi + fi + + # Check for libraries that X11R6 Xt/Xaw programs need. + ac_save_LDFLAGS=$LDFLAGS + test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" + # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to + # check for ICE first), but we must link in the order -lSM -lICE or + # we get undefined symbols. So assume we have SM if we have ICE. + # These have to be linked with before -lX11, unlike the other + # libraries we check for below, so use a different variable. + # John Interrante, Karl Berry + echo "$as_me:$LINENO: checking for IceConnectionNumber in -lICE" >&5 +echo $ECHO_N "checking for IceConnectionNumber in -lICE... $ECHO_C" >&6 +if test "${ac_cv_lib_ICE_IceConnectionNumber+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lICE $X_EXTRA_LIBS $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char IceConnectionNumber (); +int +main () +{ +IceConnectionNumber (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_ICE_IceConnectionNumber=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_ICE_IceConnectionNumber=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 +echo "${ECHO_T}$ac_cv_lib_ICE_IceConnectionNumber" >&6 +if test $ac_cv_lib_ICE_IceConnectionNumber = yes; then + X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" +fi + + LDFLAGS=$ac_save_LDFLAGS + +fi + + + if test x$no_x = xyes; then + { { echo "$as_me:$LINENO: error: Configure could not find required X11 libraries" >&5 +echo "$as_me: error: Configure could not find required X11 libraries" >&2;} + { (exit aborting.); exit aborting.; }; } + fi + + if test "x$X_PRE_LIBS" != x; then + { echo "$as_me:$LINENO: WARNING: Ignoring libraries \"$X_PRE_LIBS\" requested by configure." >&5 +echo "$as_me: WARNING: Ignoring libraries \"$X_PRE_LIBS\" requested by configure." >&2;} + fi + + LIBS="$LIBS -lXext -lX11 $X_EXTRA_LIBS" + CFLAGS="$CFLAGS $X_CFLAGS" + CXXFLAGS="$CXXFLAGS $X_CFLAGS" + LDFLAGS="$X_LIBS $LDFLAGS" + + if test "x$x_includes" != x; then + ac_cpp="$ac_cpp -I$x_includes" + fi + + GLLIB= + + if test x$enable_gl != xno; then + echo "$as_me:$LINENO: checking for library containing dlopen" >&5 +echo $ECHO_N "checking for library containing dlopen... $ECHO_C" >&6 +if test "${ac_cv_search_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +ac_cv_search_dlopen=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_dlopen="none required" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test "$ac_cv_search_dlopen" = no; then + for ac_lib in dl; do + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_dlopen="-l$ac_lib" +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done +fi +LIBS=$ac_func_search_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_search_dlopen" >&5 +echo "${ECHO_T}$ac_cv_search_dlopen" >&6 +if test "$ac_cv_search_dlopen" != no; then + test "$ac_cv_search_dlopen" = "none required" || LIBS="$ac_cv_search_dlopen $LIBS" + +fi + + if test "${ac_cv_header_GL_gl_h+set}" = set; then + echo "$as_me:$LINENO: checking for GL/gl.h" >&5 +echo $ECHO_N "checking for GL/gl.h... $ECHO_C" >&6 +if test "${ac_cv_header_GL_gl_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_GL_gl_h" >&5 +echo "${ECHO_T}$ac_cv_header_GL_gl_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking GL/gl.h usability" >&5 +echo $ECHO_N "checking GL/gl.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <GL/gl.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking GL/gl.h presence" >&5 +echo $ECHO_N "checking GL/gl.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <GL/gl.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: GL/gl.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: GL/gl.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: GL/gl.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: GL/gl.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: GL/gl.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: GL/gl.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: GL/gl.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: GL/gl.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: GL/gl.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: GL/gl.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for GL/gl.h" >&5 +echo $ECHO_N "checking for GL/gl.h... $ECHO_C" >&6 +if test "${ac_cv_header_GL_gl_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_GL_gl_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_GL_gl_h" >&5 +echo "${ECHO_T}$ac_cv_header_GL_gl_h" >&6 + +fi +if test $ac_cv_header_GL_gl_h = yes; then + echo "$as_me:$LINENO: checking for glXMakeCurrent in -lGL" >&5 +echo $ECHO_N "checking for glXMakeCurrent in -lGL... $ECHO_C" >&6 +if test "${ac_cv_lib_GL_glXMakeCurrent+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lGL \ + -lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char glXMakeCurrent (); +int +main () +{ +glXMakeCurrent (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_GL_glXMakeCurrent=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_GL_glXMakeCurrent=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_GL_glXMakeCurrent" >&5 +echo "${ECHO_T}$ac_cv_lib_GL_glXMakeCurrent" >&6 +if test $ac_cv_lib_GL_glXMakeCurrent = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_GL 1 +_ACEOF + GLLIB="-lGL" +else + \ + echo "$as_me:$LINENO: checking for glXMakeCurrent in -lMesaGL" >&5 +echo $ECHO_N "checking for glXMakeCurrent in -lMesaGL... $ECHO_C" >&6 +if test "${ac_cv_lib_MesaGL_glXMakeCurrent+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lMesaGL \ + -lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char glXMakeCurrent (); +int +main () +{ +glXMakeCurrent (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_MesaGL_glXMakeCurrent=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_MesaGL_glXMakeCurrent=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_MesaGL_glXMakeCurrent" >&5 +echo "${ECHO_T}$ac_cv_lib_MesaGL_glXMakeCurrent" >&6 +if test $ac_cv_lib_MesaGL_glXMakeCurrent = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_GL 1 +_ACEOF + GLLIB=" -lMesaGL" +fi + +fi + + +fi + + + if test "${ac_cv_header_GL_glu_h+set}" = set; then + echo "$as_me:$LINENO: checking for GL/glu.h" >&5 +echo $ECHO_N "checking for GL/glu.h... $ECHO_C" >&6 +if test "${ac_cv_header_GL_glu_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_GL_glu_h" >&5 +echo "${ECHO_T}$ac_cv_header_GL_glu_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking GL/glu.h usability" >&5 +echo $ECHO_N "checking GL/glu.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <GL/glu.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking GL/glu.h presence" >&5 +echo $ECHO_N "checking GL/glu.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <GL/glu.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: GL/glu.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: GL/glu.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/glu.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: GL/glu.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: GL/glu.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: GL/glu.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/glu.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: GL/glu.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/glu.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: GL/glu.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/glu.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: GL/glu.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/glu.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: GL/glu.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/glu.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: GL/glu.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for GL/glu.h" >&5 +echo $ECHO_N "checking for GL/glu.h... $ECHO_C" >&6 +if test "${ac_cv_header_GL_glu_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_GL_glu_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_GL_glu_h" >&5 +echo "${ECHO_T}$ac_cv_header_GL_glu_h" >&6 + +fi +if test $ac_cv_header_GL_glu_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_GL_GLU_H 1 +_ACEOF + + if test x$ac_cv_lib_GL_glXMakeCurrent = xyes; then + GLLIB="-lGLU $GLLIB" + fi + if test x$ac_cv_lib_MesaGL_glXMakeCurrent = xyes; then + GLLIB="-lMesaGLU $GLLIB" + fi + +fi + + + + if test x$ac_cv_lib_GL_glXMakeCurrent != xyes -a x$ac_cv_lib_MesaGL_glXMakeCurrent != xyes; then + LINKFLTKGL="" + GLLIBNAME="" + GLDSONAME="" + GLDEMOS="" + fi + else + LINKFLTKGL="" + GLLIBNAME="" + GLDSONAME="" + GLDEMOS="" + fi + + # Check whether --enable-xinerama or --disable-xinerama was given. +if test "${enable_xinerama+set}" = set; then + enableval="$enable_xinerama" + +fi; + + if test x$enable_xinerama = xyes; then + echo "$as_me:$LINENO: checking for XineramaIsActive in -lXinerama" >&5 +echo $ECHO_N "checking for XineramaIsActive in -lXinerama... $ECHO_C" >&6 +if test "${ac_cv_lib_Xinerama_XineramaIsActive+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXinerama $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XineramaIsActive (); +int +main () +{ +XineramaIsActive (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xinerama_XineramaIsActive=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xinerama_XineramaIsActive=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xinerama_XineramaIsActive" >&5 +echo "${ECHO_T}$ac_cv_lib_Xinerama_XineramaIsActive" >&6 +if test $ac_cv_lib_Xinerama_XineramaIsActive = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_XINERAMA 1 +_ACEOF + + LIBS="-lXinerama $LIBS" +fi + + fi + + # Check whether --enable-xft or --disable-xft was given. +if test "${enable_xft+set}" = set; then + enableval="$enable_xft" + +fi; + + if test x$enable_xft = xyes; then + # Extract the first word of "freetype-config", so it can be a program name with args. +set dummy freetype-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_FTCONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $FTCONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_FTCONFIG="$FTCONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_FTCONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +FTCONFIG=$ac_cv_path_FTCONFIG + +if test -n "$FTCONFIG"; then + echo "$as_me:$LINENO: result: $FTCONFIG" >&5 +echo "${ECHO_T}$FTCONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + + if test "x$FTCONFIG" != "x:"; then + CPPFLAGS="`$FTCONFIG --cflags` $CPPFLAGS" + CXXFLAGS="`$FTCONFIG --cflags` $CXXFLAGS" + + if test "${ac_cv_header_X11_Xft_Xft_h+set}" = set; then + echo "$as_me:$LINENO: checking for X11/Xft/Xft.h" >&5 +echo $ECHO_N "checking for X11/Xft/Xft.h... $ECHO_C" >&6 +if test "${ac_cv_header_X11_Xft_Xft_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_X11_Xft_Xft_h" >&5 +echo "${ECHO_T}$ac_cv_header_X11_Xft_Xft_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking X11/Xft/Xft.h usability" >&5 +echo $ECHO_N "checking X11/Xft/Xft.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <X11/Xft/Xft.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking X11/Xft/Xft.h presence" >&5 +echo $ECHO_N "checking X11/Xft/Xft.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <X11/Xft/Xft.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: X11/Xft/Xft.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: X11/Xft/Xft.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: X11/Xft/Xft.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: X11/Xft/Xft.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: X11/Xft/Xft.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: X11/Xft/Xft.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: X11/Xft/Xft.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: X11/Xft/Xft.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: X11/Xft/Xft.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: X11/Xft/Xft.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: X11/Xft/Xft.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: X11/Xft/Xft.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: X11/Xft/Xft.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: X11/Xft/Xft.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: X11/Xft/Xft.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: X11/Xft/Xft.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for X11/Xft/Xft.h" >&5 +echo $ECHO_N "checking for X11/Xft/Xft.h... $ECHO_C" >&6 +if test "${ac_cv_header_X11_Xft_Xft_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_X11_Xft_Xft_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_X11_Xft_Xft_h" >&5 +echo "${ECHO_T}$ac_cv_header_X11_Xft_Xft_h" >&6 + +fi +if test $ac_cv_header_X11_Xft_Xft_h = yes; then + echo "$as_me:$LINENO: checking for XftDrawCreate in -lXft" >&5 +echo $ECHO_N "checking for XftDrawCreate in -lXft... $ECHO_C" >&6 +if test "${ac_cv_lib_Xft_XftDrawCreate+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXft $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XftDrawCreate (); +int +main () +{ +XftDrawCreate (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xft_XftDrawCreate=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xft_XftDrawCreate=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xft_XftDrawCreate" >&5 +echo "${ECHO_T}$ac_cv_lib_Xft_XftDrawCreate" >&6 +if test $ac_cv_lib_Xft_XftDrawCreate = yes; then + cat >>confdefs.h <<\_ACEOF +#define USE_XFT 1 +_ACEOF + + LIBS="-lXft $LIBS" +fi + +fi + + + fi + fi + + # Check whether --enable-xdbe or --disable-xdbe was given. +if test "${enable_xdbe+set}" = set; then + enableval="$enable_xdbe" + +fi; + + if test x$enable_xdbe = xyes; then + echo "$as_me:$LINENO: checking for X11/extensions/Xdbe.h" >&5 +echo $ECHO_N "checking for X11/extensions/Xdbe.h... $ECHO_C" >&6 +if test "${ac_cv_header_X11_extensions_Xdbe_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <X11/Xlib.h> + +#include <X11/extensions/Xdbe.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_X11_extensions_Xdbe_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_X11_extensions_Xdbe_h=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_header_X11_extensions_Xdbe_h" >&5 +echo "${ECHO_T}$ac_cv_header_X11_extensions_Xdbe_h" >&6 +if test $ac_cv_header_X11_extensions_Xdbe_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_XDBE 1 +_ACEOF + +fi + + + fi + + echo "$as_me:$LINENO: checking for X overlay visuals" >&5 +echo $ECHO_N "checking for X overlay visuals... $ECHO_C" >&6 +if test "${ac_cv_have_overlay+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if xprop -root 2>/dev/null | grep -c "SERVER_OVERLAY_VISUALS" >/dev/null; then + ac_cv_have_overlay=yes + else + ac_cv_have_overlay=no + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_have_overlay" >&5 +echo "${ECHO_T}$ac_cv_have_overlay" >&6 + + if test x$ac_cv_have_overlay = xyes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_OVERLAY 1 +_ACEOF + + fi + + # Make symlinks since UNIX/Linux is case sensitive. + if test "x$with_links" = xno; then + HLINKS="#" + fi + + # Install/Uninstall FLUID application support files + INSTALL_DESKTOP="install-linux" + UNINSTALL_DESKTOP="uninstall-linux" + ;; +esac + + + + + + + + + + +case "$uname" in + *BSD* | Darwin*) + # *BSD + CAT1EXT=0 + CAT3EXT=0 + CAT6EXT=0 + ;; + IRIX*) + # SGI IRIX + CAT1EXT=z + CAT3EXT=z + CAT6EXT=z + ;; + *) + # All others + CAT1EXT=1 + CAT3EXT=3 + CAT6EXT=3 + ;; +esac + + + + + +if test "$mandir" = "\${prefix}/man" -a "$prefix" = "/usr"; then + case "$uname" in + *BSD* | Darwin* | Linux*) + # *BSD, Darwin, and Linux + mandir="\${prefix}/share/man" + ;; + IRIX*) + # SGI IRIX + mandir="\${prefix}/share/catman" + ;; + esac +fi + +if test "$prefix" = NONE; then + prefix=/usr/local +fi + +if test "$exec_prefix" = NONE; then + exec_prefix="\${prefix}" +fi + +if test "$uname" = "IRIX" -a $uversion -ge 62 -a "$libdir" = "\${exec_prefix}/lib" -a "$exec_prefix" = "\${prefix}" -a "$prefix" = "/usr"; then + libdir="/usr/lib32" +fi + +MAKEDEPEND="\$(CXX) -M" + + + +if test -n "$GCC"; then + # Show all standard warnings + unused variables, conversion errors, + # and inlining problems when compiling... + OPTIM="-Wall -Wunused -Wno-format-y2k $OPTIM" + + # The following additional warnings are useful for tracking down problems... + #OPTIM="-Wshadow -Wconversion $OPTIM" + + # Set the default compiler optimizations... + if test -z "$DEBUGFLAG"; then + # + # Note: Can't use -fomit-frame-pointer - prevents tools like + # libsafe from working! + # + # Don't use -fforce-mem, -fforce-addr, or -fcaller-saves. + # They all seem to make either no difference or enlarge + # the code by a few hundred bytes. + # + # "-Os" seems to be the best compromise between speed and + # code size. "-O3" and higher seem to make no effective + # difference in the speed of the code, but does bloat the + # library 10+%. + # + + if test "x$with_optim" != x; then + OPTIM="$with_optim $OPTIM" + else + OPTIM="-Os $OPTIM" + fi + fi + + # Generate position-independent code when needed... + if test $PICFLAG = 1; then + OPTIM="$OPTIM -fPIC" + fi + + # See if GCC supports -fno-exceptions... + echo "$as_me:$LINENO: checking if GCC supports -fno-exceptions" >&5 +echo $ECHO_N "checking if GCC supports -fno-exceptions... $ECHO_C" >&6 + OLDCFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fno-exceptions" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + OPTIM="$OPTIM -fno-exceptions" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$OLDCFLAGS" + + # See if we are running Solaris; if so, try the -fpermissive option... + # This option is required on some versions of Solaris to work around + # bugs in the X headers up through Solaris 7. + # + # Unlike the other compiler/optimization settings, this one is placed + # in CFLAGS and CXXFLAGS so that fltk-config will provide the option + # to clients - otherwise client apps will not compile properly... + if test "$uname" = SunOS; then + echo "$as_me:$LINENO: checking if GCC supports -fpermissive" >&5 +echo $ECHO_N "checking if GCC supports -fpermissive... $ECHO_C" >&6 + + OLDCFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fpermissive" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + CXXFLAGS="$CXXFLAGS -fpermissive" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +CFLAGS="$OLDCFLAGS" + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + fi +else + case "$uname" in + IRIX*) + # Running some flavor of IRIX; see which version and + # set things up according... + if test "$uversion" -ge 62; then + # We are running IRIX 6.2 or higher; uncomment the following + # lines if you don't have IDO 7.2 or higher: + # + # CXX="CC -n32 -mips3" + # CC="cc -n32 -mips3" + # LD="ld -n32 -mips3" + # MAKEDEPEND="CC -M" + + if test "x`grep abi=n32 /etc/compiler.defaults`" = x; then + { echo "$as_me:$LINENO: WARNING: FOR BEST RESULTS BEFORE COMPILING: setenv SGI_ABI \"-n32 -mips3\"" >&5 +echo "$as_me: WARNING: FOR BEST RESULTS BEFORE COMPILING: setenv SGI_ABI \"-n32 -mips3\"" >&2;} + fi + + OPTIM="-fullwarn $OPTIM" + fi + if test -z "$DEBUGFLAG"; then + if test "x$with_optim" != x; then + OPTIM="$with_optim $OPTIM" + else + OPTIM="-O2 $OPTIM" + if test $uversion -gt 62; then + OPTIM="-OPT:Olimit=4000 $OPTIM" + fi + fi + fi + ;; + HP-UX*) + # Running HP-UX; these options should work for the HP compilers. + if test -z "$DEBUGFLAG"; then + if test "x$with_optim" != x; then + OPTIM="$with_optim $OPTIM" + else + OPTIM="+O2 $OPTIM" + fi + fi + + if test "x$with_optim" = x; then + OPTIM="$OPTIM +DAportable" + fi + + if test $PICFLAG = 1; then + OPTIM="+z $OPTIM" + fi + + OPTIM="$OPTIM +W336,501,736,740,749,829" + ;; + OSF1*) + # Running Digital/Tru64 UNIX; these options should work for the + # Digital/Compaq/NewHP compilers. + if test -z "$DEBUGFLAG"; then + if test "x$with_optim" != x; then + OPTIM="$with_optim $OPTIM" + else + OPTIM="-O2 $OPTIM" + fi + fi + ;; + SunOS*) + # Solaris + if test -z "$DEBUGFLAG"; then + if test "x$with_optim" != x; then + OPTIM="$with_optim $OPTIM" + else + OPTIM="-xO3 $OPTIM" + fi + fi + + if test $PICFLAG = 1; then + OPTIM="-KPIC $OPTIM" + fi + ;; + AIX*) + if test -z "$DEBUGFLAG"; then + if test "x$with_optim" != x; then + OPTIM="$with_optim $OPTIM" + else + OPTIM="-O2 $OPTIM" + fi + fi + + { echo "$as_me:$LINENO: WARNING: The AIX C and C++ compilers are known not to correctly compile the FLTK library." >&5 +echo "$as_me: WARNING: The AIX C and C++ compilers are known not to correctly compile the FLTK library." >&2;} + ;; + *) + # Running some other operating system; inform the user they + # should contribute the necessary options to fltk-bugs@fltk.org... + { echo "$as_me:$LINENO: WARNING: Building FLTK with default compiler optimizations" >&5 +echo "$as_me: WARNING: Building FLTK with default compiler optimizations" >&2;} + { echo "$as_me:$LINENO: WARNING: Contact fltk-bugs@fltk.org with uname and compiler options." >&5 +echo "$as_me: WARNING: Contact fltk-bugs@fltk.org with uname and compiler options." >&2;} + ;; + esac +fi + +OPTIM="$DEBUGFLAG $OPTIM" + +if test x$prefix = xNONE; then + cat >>confdefs.h <<_ACEOF +#define FLTK_DOCDIR "/usr/local/share/doc/fltk" +_ACEOF + +else + cat >>confdefs.h <<_ACEOF +#define FLTK_DOCDIR "$prefix/share/doc/fltk" +_ACEOF + +fi + +if test x$prefix = xNONE; then + cat >>confdefs.h <<_ACEOF +#define FLTK_DATADIR "/usr/local/share/fltk" +_ACEOF + +else + cat >>confdefs.h <<_ACEOF +#define FLTK_DATADIR "$prefix/share/fltk" +_ACEOF + +fi + + ac_config_headers="$ac_config_headers config.h:configh.in" + + ac_config_files="$ac_config_files makeinclude fltk.list fltk-config FL/Makefile" +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by $as_me, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to <bug-autoconf@gnu.org>." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.59, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + + + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "makeinclude" ) CONFIG_FILES="$CONFIG_FILES makeinclude" ;; + "fltk.list" ) CONFIG_FILES="$CONFIG_FILES fltk.list" ;; + "fltk-config" ) CONFIG_FILES="$CONFIG_FILES fltk-config" ;; + "FL/Makefile" ) CONFIG_FILES="$CONFIG_FILES FL/Makefile" ;; + "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h:configh.in" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@FL_MAJOR_VERSION@,$FL_MAJOR_VERSION,;t t +s,@FL_MINOR_VERSION@,$FL_MINOR_VERSION,;t t +s,@FL_PATCH_VERSION@,$FL_PATCH_VERSION,;t t +s,@FL_API_VERSION@,$FL_API_VERSION,;t t +s,@OPTIM@,$OPTIM,;t t +s,@FLLIBNAME@,$FLLIBNAME,;t t +s,@GLDEMOS@,$GLDEMOS,;t t +s,@GLLIBNAME@,$GLLIBNAME,;t t +s,@IMGLIBNAME@,$IMGLIBNAME,;t t +s,@LIBEXT@,$LIBEXT,;t t +s,@LIBNAME@,$LIBNAME,;t t +s,@LINKFLTK@,$LINKFLTK,;t t +s,@LINKFLTKFORMS@,$LINKFLTKFORMS,;t t +s,@LINKFLTKGL@,$LINKFLTKGL,;t t +s,@LINKFLTKIMG@,$LINKFLTKIMG,;t t +s,@DSOCOMMAND@,$DSOCOMMAND,;t t +s,@DSOLINK@,$DSOLINK,;t t +s,@DSONAME@,$DSONAME,;t t +s,@FLDSONAME@,$FLDSONAME,;t t +s,@GLDSONAME@,$GLDSONAME,;t t +s,@IMGDSONAME@,$IMGDSONAME,;t t +s,@SHAREDSUFFIX@,$SHAREDSUFFIX,;t t +s,@LINKSHARED@,$LINKSHARED,;t t +s,@FLUID@,$FLUID,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@CXX@,$CXX,;t t +s,@CXXFLAGS@,$CXXFLAGS,;t t +s,@ac_ct_CXX@,$ac_ct_CXX,;t t +s,@NROFF@,$NROFF,;t t +s,@GROFF@,$GROFF,;t t +s,@HTMLDOC@,$HTMLDOC,;t t +s,@RANLIB@,$RANLIB,;t t +s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t +s,@AR@,$AR,;t t +s,@LIBCOMMAND@,$LIBCOMMAND,;t t +s,@CPP@,$CPP,;t t +s,@EGREP@,$EGREP,;t t +s,@LARGEFILE@,$LARGEFILE,;t t +s,@AUDIOLIBS@,$AUDIOLIBS,;t t +s,@IMAGELIBS@,$IMAGELIBS,;t t +s,@JPEG@,$JPEG,;t t +s,@JPEGINC@,$JPEGINC,;t t +s,@PNG@,$PNG,;t t +s,@PNGINC@,$PNGINC,;t t +s,@ZLIB@,$ZLIB,;t t +s,@ZLIBINC@,$ZLIBINC,;t t +s,@X_CFLAGS@,$X_CFLAGS,;t t +s,@X_PRE_LIBS@,$X_PRE_LIBS,;t t +s,@X_LIBS@,$X_LIBS,;t t +s,@X_EXTRA_LIBS@,$X_EXTRA_LIBS,;t t +s,@FTCONFIG@,$FTCONFIG,;t t +s,@GLLIB@,$GLLIB,;t t +s,@HLINKS@,$HLINKS,;t t +s,@POSTBUILD@,$POSTBUILD,;t t +s,@THREADS@,$THREADS,;t t +s,@INSTALL_DESKTOP@,$INSTALL_DESKTOP,;t t +s,@UNINSTALL_DESKTOP@,$UNINSTALL_DESKTOP,;t t +s,@CAT1EXT@,$CAT1EXT,;t t +s,@CAT3EXT@,$CAT3EXT,;t t +s,@CAT6EXT@,$CAT6EXT,;t t +s,@MAKEDEPEND@,$MAKEDEPEND,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_HEADER section. +# + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' +ac_dC=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' +ac_uC=' ' +ac_uD=',;t' + +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + # Do quote $f, to prevent DOS paths from being IFS'd. + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + +_ACEOF + +# Transform confdefs.h into two sed scripts, `conftest.defines' and +# `conftest.undefs', that substitutes the proper values into +# config.h.in to produce config.h. The first handles `#define' +# templates, and the second `#undef' templates. +# And first: Protect against being on the right side of a sed subst in +# config.status. Protect against being in an unquoted here document +# in config.status. +rm -f conftest.defines conftest.undefs +# Using a here document instead of a string reduces the quoting nightmare. +# Putting comments in sed scripts is not portable. +# +# `end' is used to avoid that the second main sed command (meant for +# 0-ary CPP macros) applies to n-ary macro definitions. +# See the Autoconf documentation for `clear'. +cat >confdef2sed.sed <<\_ACEOF +s/[\\&,]/\\&/g +s,[\\$`],\\&,g +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +t end +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +: end +_ACEOF +# If some macros were called several times there might be several times +# the same #defines, which is useless. Nevertheless, we may not want to +# sort them, since we want the *last* AC-DEFINE to be honored. +uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines +sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs +rm -f confdef2sed.sed + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >>conftest.undefs <<\_ACEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +_ACEOF + +# Break up conftest.defines because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS +echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS +echo ' :' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.defines >/dev/null +do + # Write a limited-size here document to $tmp/defines.sed. + echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS + # Speed up: don't consider the non `#define' lines. + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/defines.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines +echo ' fi # grep' >>$CONFIG_STATUS +echo >>$CONFIG_STATUS + +# Break up conftest.undefs because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #undef templates' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.undefs >/dev/null +do + # Write a limited-size here document to $tmp/undefs.sed. + echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS + # Speed up: don't consider the non `#undef' + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/undefs.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail + rm -f conftest.undefs + mv conftest.tail conftest.undefs +done +rm -f conftest.undefs + +cat >>$CONFIG_STATUS <<\_ACEOF + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + echo "/* Generated by configure. */" >$tmp/config.h + else + echo "/* $ac_file. Generated by configure. */" >$tmp/config.h + fi + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if diff $ac_file $tmp/config.h >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + + +chmod +x fltk-config + diff --git a/Utilities/FLTK/configure.in b/Utilities/FLTK/configure.in new file mode 100644 index 0000000000..5165f84cf7 --- /dev/null +++ b/Utilities/FLTK/configure.in @@ -0,0 +1,1005 @@ +dnl -*- sh -*- +dnl the "configure" script is made from this by running GNU "autoconf" +dnl +dnl "$Id: configure.in 4756 2006-01-15 18:36:16Z mike $" +dnl +dnl Configuration script for the Fast Light Tool Kit (FLTK). +dnl +dnl Copyright 1998-2006 by Bill Spitzak and others. +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Library General Public +dnl License as published by the Free Software Foundation; either +dnl version 2 of the License, or (at your option) any later version. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Library General Public License for more details. +dnl +dnl You should have received a copy of the GNU Library General Public +dnl License along with this library; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +dnl USA. +dnl +dnl Please report all bugs and problems on the following page: +dnl +dnl http://www.fltk.org/str.php +dnl + +dnl We need at least autoconf 2.13... +AC_PREREQ(2.13) + +dnl Required file in package... +AC_INIT(src/Fl.cxx) + +dnl FLTK library versions... +FL_MAJOR_VERSION=1 +FL_MINOR_VERSION=1 +FL_PATCH_VERSION=7 +FL_API_VERSION=${FL_MAJOR_VERSION}.${FL_MINOR_VERSION} + +AC_SUBST(FL_MAJOR_VERSION) +AC_SUBST(FL_MINOR_VERSION) +AC_SUBST(FL_PATCH_VERSION) +AC_SUBST(FL_API_VERSION) + +dnl Get the operating system and version number... +uname=`uname` +uversion=`uname -r | sed -e '1,$s/[[^0-9]]//g'` +if test "x$uname" = xIRIX64; then + uname="IRIX" +fi +if test "x$uname" = x; then + # MingW doesn't provide any output when uname is run, even with "-s"... + uname="CYGWIN" +fi + +dnl Don't automatically add "-g" to compiler options... +CFLAGS="${CFLAGS:=}" +CPPFLAGS="${CPPFLAGS:=}" +CXXFLAGS="${CXXFLAGS:=}" +OPTIM="${OPTIM:=}" + +AC_SUBST(OPTIM) + +dnl OS-specific pre-tests... +case $uname in + CYGWIN* | MINGW*) + # Handle Cygwin option *first*, before all other tests. + AC_ARG_ENABLE(cygwin, [ --enable-cygwin use the CygWin libraries [default=no]]) + if test x$enable_cygwin != xyes; then + CFLAGS="$CFLAGS -mno-cygwin" + CPPFLAGS="$CPPFLAGS -mno-cygwin" + CXXFLAGS="$CXXFLAGS -mno-cygwin" + LDFLAGS="$LDFLAGS -mno-cygwin" + fi + ;; +esac + +dnl Define the libraries and link options we'll need. +LINKFLTK="../lib/libfltk.a" +LINKFLTKFORMS="../lib/libfltk_forms.a" +LINKFLTKGL="../lib/libfltk_gl.a" +LINKFLTKIMG="../lib/libfltk_images.a" +GLDEMOS="gldemos" + +LIBEXT=".a" +LIBNAME="../lib/libfltk.a" +FLLIBNAME="../lib/libfltk_forms.a" +GLLIBNAME="../lib/libfltk_gl.a" +IMGLIBNAME="../lib/libfltk_images.a" + +AC_SUBST(FLLIBNAME) +AC_SUBST(GLDEMOS) +AC_SUBST(GLLIBNAME) +AC_SUBST(IMGLIBNAME) +AC_SUBST(LIBEXT) +AC_SUBST(LIBNAME) +AC_SUBST(LINKFLTK) +AC_SUBST(LINKFLTKFORMS) +AC_SUBST(LINKFLTKGL) +AC_SUBST(LINKFLTKIMG) + +dnl Handle compile-time options... +AC_ARG_ENABLE(debug, [ --enable-debug turn on debugging [default=no]]) +if test x$enable_debug = xyes; then + DEBUGFLAG="-g " +else + DEBUGFLAG="" +fi + +AC_ARG_ENABLE(gl, [ --enable-gl turn on OpenGL support [default=yes]]) + +AC_ARG_ENABLE(shared, [ --enable-shared turn on shared libraries [default=no]]) +if test x$enable_shared = xyes; then + PICFLAG=1 + SHAREDSUFFIX="" + FLUID="fluid-shared" + + case $uname in + Darwin*) + DSONAME="libfltk.$FL_API_VERSION.dylib" + FLDSONAME="libfltk_forms.$FL_API_VERSION.dylib" + GLDSONAME="libfltk_gl.$FL_API_VERSION.dylib" + IMGDSONAME="libfltk_images.$FL_API_VERSION.dylib" + DSOCOMMAND="\$(CC) $DSOFLAGS -dynamiclib -lc -o" + ;; + + SunOS* | UNIX_S*) + DSONAME="libfltk.so.$FL_API_VERSION" + FLDSONAME="libfltk_forms.so.$FL_API_VERSION" + GLDSONAME="libfltk_gl.so.$FL_API_VERSION" + IMGDSONAME="libfltk_images.so.$FL_API_VERSION" + DSOCOMMAND="\$(CXX) -h \$@ \$(LDLIBS) -G $DEBUGFLAG -o" + if test "x$libdir" != "x/usr/lib"; then + DSOLINK="-R$libdir" + fi + ;; + HP-UX*) + DSONAME="libfltk.sl.$FL_API_VERSION" + FLDSONAME="libfltk_forms.sl.$FL_API_VERSION" + GLDSONAME="libfltk_gl.sl.$FL_API_VERSION" + IMGDSONAME="libfltk_images.sl.$FL_API_VERSION" + DSOCOMMAND="ld -b -z +h \$@ $DEBUGFLAG -o" + if test "x$libdir" != "x/usr/lib"; then + DSOLINK="-Wl,-rpath,$libdir" + fi + ;; + IRIX*) + DSONAME="libfltk.so.$FL_API_VERSION" + FLDSONAME="libfltk_forms.so.$FL_API_VERSION" + GLDSONAME="libfltk_gl.so.$FL_API_VERSION" + IMGDSONAME="libfltk_images.so.$FL_API_VERSION" + DSOCOMMAND="\$(CXX) -Wl,-soname,\$@,-set_version,sgi1.1 \$(LDLIBS) -shared $DEBUGFLAG -o" + if test "x$libdir" != "x/usr/lib" -a "x$libdir" != "x/usr/lib32" -a "x$libdir" != "x/usr/lib64"; then + DSOLINK="-Wl,-rpath,$libdir" + fi + ;; + OSF1*) + DSONAME="libfltk.so.$FL_API_VERSION" + FLDSONAME="libfltk_forms.so.$FL_API_VERSION" + GLDSONAME="libfltk_gl.so.$FL_API_VERSION" + IMGDSONAME="libfltk_images.so.$FL_API_VERSION" + DSOCOMMAND="\$(CXX) -Wl,-soname,\$@ \$(LDLIBS) -shared $DEBUGFLAG -o" + if test "x$libdir" != "x/usr/lib" -a "x$libdir" != "x/usr/lib32"; then + DSOLINK="-Wl,-rpath,$libdir" + fi + ;; + Linux* | *BSD*) + DSONAME="libfltk.so.$FL_API_VERSION" + FLDSONAME="libfltk_forms.so.$FL_API_VERSION" + GLDSONAME="libfltk_gl.so.$FL_API_VERSION" + IMGDSONAME="libfltk_images.so.$FL_API_VERSION" + DSOCOMMAND="\$(CXX) -Wl,-soname,\$@ \$(LDLIBS) -shared -fPIC $DEBUGFLAG -o" + if test "x$libdir" != "x/usr/lib"; then + DSOLINK="-Wl,-rpath,$libdir" + fi + ;; + AIX*) + DSONAME="libfltk_s.a" + FLDSONAME="libfltk_forms_s.a" + GLDSONAME="libfltk_gl_s.a" + IMGDSONAME="libfltk_images_s.a" + DSOCOMMAND="\$(CXX) -Wl,-bexpall,-bM:SRE,-bnoentry -o" + SHAREDSUFFIX="_s" + ;; + CYGWIN* | MINGW*) + PICFLAG=0 + if test x$enable_cygwin != xyes; then + DSONAME="mgwfltknox-$FL_API_VERSION.dll" + FLDSONAME="mgwfltknox_forms-$FL_API_VERSION.dll" + GLDSONAME="mgwfltknox_gl-$FL_API_VERSION.dll" + IMGDSONAME="mgwfltknox_images-$FL_API_VERSION.dll" + else + DSONAME="cygfltknox-$FL_API_VERSION.dll" + FLDSONAME="cygfltknox_forms-$FL_API_VERSION.dll" + GLDSONAME="cygfltknox_gl-$FL_API_VERSION.dll" + IMGDSONAME="cygfltknox_images-$FL_API_VERSION.dll" + fi + DSOCOMMAND="\$(CXX) -shared -Wl,--whole-archive -Wl,--export-all-symbols -Wl,--enable-auto-import -o \$@" + ;; + *) + AC_MSG_WARN(Shared libraries may not be supported. Trying -shared option with compiler.) + DSONAME="libfltk.so.$FL_API_VERSION" + FLDSONAME="libfltk_forms.so.$FL_API_VERSION" + GLDSONAME="libfltk_gl.so.$FL_API_VERSION" + IMGDSONAME="libfltk_images.so.$FL_API_VERSION" + DSOCOMMAND="\$(CXX) -Wl,-soname,\$@ \$(LDLIBS) -shared $DEBUGFLAG -o" + ;; + esac + + LINKSHARED="-L../src -lfltk_images$SHAREDSUFFIX -lfltk_forms$SHAREDSUFFIX -lfltk$SHAREDSUFFIX" +else + DSOCOMMAND="echo" + DSOLINK="" + DSONAME="" + FLDSONAME="" + GLDSONAME="" + IMGDSONAME="" + PICFLAG=0 + SHAREDSUFFIX="" + FLUID="fluid" + LINKSHARED="../lib/libfltk_images.a ../lib/libfltk_forms.a ../lib/libfltk.a" +fi + +AC_SUBST(DSOCOMMAND) +AC_SUBST(DSOLINK) +AC_SUBST(DSONAME) +AC_SUBST(FLDSONAME) +AC_SUBST(GLDSONAME) +AC_SUBST(IMGDSONAME) +AC_SUBST(SHAREDSUFFIX) +AC_SUBST(LINKSHARED) +AC_SUBST(FLUID) + +AC_ARG_ENABLE(threads, [ --enable-threads enable multi-threading support]) + +AC_ARG_WITH(optim, [ --with-optim="flags" use custom optimization flags]) + +case $uname in + Darwin*) + AC_ARG_ENABLE(quartz, [ --enable-quartz use Quartz instead of Quickdraw (default=no)]) + if test "x$enable_quartz" = "xyes"; then + AC_DEFINE(USE_QUARTZ, 1) + AC_DEFINE(__APPLE_QUARTZ__) + else + AC_DEFINE(__APPLE_QD__) + fi + ;; +esac + +dnl Find commands... +AC_PROG_CC +AC_PROG_CXX +dnl AC_PROG_INSTALL +AC_PATH_PROG(NROFF,nroff) +if test "x$NROFF" = "x:"; then + AC_PATH_PROG(GROFF,groff) + if test "x$GROFF" = "x:"; then + NROFF="echo" + else + NROFF="$GROFF -T ascii" + fi +fi +AC_PATH_PROG(HTMLDOC,htmldoc) + +dnl How do we make libraries? +AC_PROG_RANLIB +AC_PATH_PROG(AR, ar) + +if test "x$AR" = "x:"; then + AC_MSG_ERROR(Configure could not find the library archiver, aborting.) +fi + +if test "x$RANLIB" != "x:"; then + LIBCOMMAND="$AR cr" +else + LIBCOMMAND="$AR crs" +fi + +AC_SUBST(LIBCOMMAND) + +dnl Architecture checks... +AC_C_BIGENDIAN + +AC_CHECK_SIZEOF(short, 2) +AC_CHECK_SIZEOF(int, 4) +AC_CHECK_SIZEOF(long, 4) +if test $ac_cv_sizeof_short -eq 2; then + AC_DEFINE(U16,unsigned short) +fi +if test $ac_cv_sizeof_int -eq 4; then + AC_DEFINE(U32,unsigned) +else + if test $ac_cv_sizeof_long -eq 4; then + AC_DEFINE(U32,unsigned long) + fi +fi +if test $ac_cv_sizeof_int -eq 8; then + AC_DEFINE(U64,unsigned) +else + if test $ac_cv_sizeof_long -eq 8; then + AC_DEFINE(U64,unsigned long) + fi +fi + +dnl Does the C++ compiler support the bool type? +AC_CACHE_CHECK(whether the compiler recognizes bool as a built-in type, + ac_cv_cxx_bool,[ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([ + int f(int x){return 1;} + int f(char x){return 1;} + int f(bool x){return 1;} + ],[ + bool b = true; + return f(b); + ], ac_cv_cxx_bool=yes, ac_cv_cxx_bool=no) + AC_LANG_RESTORE + ]) + +if test "$ac_cv_cxx_bool" != yes; then + CXXFLAGS="-Dbool=char -Dfalse=0 -Dtrue=1 $CXXFLAGS" +fi + +dnl Standard headers and functions... +AC_HEADER_DIRENT +AC_CHECK_HEADER(sys/select.h,AC_DEFINE(HAVE_SYS_SELECT_H)) +AC_CHECK_HEADER(sys/stdtypes.h,AC_DEFINE(HAVE_SYS_SELECT_H)) +AC_CHECK_FUNC(scandir, + if test "x$uname" = xSunOS -o "x$uname" = xQNX; then + AC_MSG_WARN(Not using $uname scandir emulation function.) + else + AC_DEFINE(HAVE_SCANDIR) + fi) +AC_CHECK_FUNC(vsnprintf,[ + case "$uname" in + HP-UX*) + if test "$uversion" = "1020"; then + AC_MSG_WARN(Not using built-in vsnprintf function because you are running HP-UX 10.20.) + else + AC_DEFINE(HAVE_VSNPRINTF) + fi + ;; + + OSF1*) + if test "$uversion" = "40"; then + AC_MSG_WARN(Not using built-in vsnprintf function because you are running Tru64 4.0.) + else + AC_DEFINE(HAVE_VSNPRINTF) + fi + ;; + + *) + AC_DEFINE(HAVE_VSNPRINTF) + ;; + esac]) +AC_CHECK_FUNC(snprintf,[ + case "$uname" in + HP-UX*) + if test "$uversion" = "1020"; then + AC_MSG_WARN(Not using built-in snprintf function because you are running HP-UX 10.20.) + else + AC_DEFINE(HAVE_SNPRINTF) + fi + ;; + + OSF1*) + if test "$uversion" = "40"; then + AC_MSG_WARN(Not using built-in snprintf function because you are running Tru64 4.0.) + else + AC_DEFINE(HAVE_SNPRINTF) + fi + ;; + + *) + AC_DEFINE(HAVE_SNPRINTF) + ;; + esac]) +AC_CHECK_HEADER(strings.h, AC_DEFINE(HAVE_STRINGS_H)) +AC_CHECK_FUNCS(strcasecmp strlcat strlcpy) + +AC_CHECK_HEADER(locale.h, AC_DEFINE(HAVE_LOCALE_H)) +AC_CHECK_FUNCS(localeconv) + +dnl FLTK library uses math library functions... +AC_SEARCH_LIBS(pow, m) + +dnl Check for largefile support... +AC_SYS_LARGEFILE + +dnl Define largefile options as needed... +LARGEFILE="" +if test x$enable_largefile != xno; then + LARGEFILE="-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE" + + if test $ac_cv_sys_large_files = 1; then + LARGEFILE="$LARGEFILE -D_LARGE_FILES" + fi + + if test $ac_cv_sys_file_offset_bits = 64; then + LARGEFILE="$LARGEFILE -D_FILE_OFFSET_BITS=64" + fi +fi +AC_SUBST(LARGEFILE) + +dnl Check for "long long" support... +AC_CACHE_CHECK(for long long int, ac_cv_c_long_long, + [if test "$GCC" = yes; then + ac_cv_c_long_long=yes + else + AC_TRY_COMPILE(,[long long int i;], + ac_cv_c_long_long=yes, + ac_cv_c_long_long=no) + fi]) + +if test $ac_cv_c_long_long = yes; then + AC_DEFINE(HAVE_LONG_LONG) +fi + +AC_CHECK_FUNC(strtoll, AC_DEFINE(HAVE_STRTOLL)) + +dnl Check for audio libraries... +AUDIOLIBS="" + +case $uname in + CYGWIN* | MINGW*) + dnl Cygwin environment... + AUDIOLIBS="-lwinmm" + ;; + + Darwin*) + AUDIOLIBS="-framework CoreAudio" + ;; + + *) + AC_CHECK_HEADER(alsa/asoundlib.h, + AC_DEFINE(HAVE_ALSA_ASOUNDLIB_H) + AUDIOLIBS="-lasound") + ;; +esac + +AC_SUBST(AUDIOLIBS) + +dnl Check for image libraries... +SAVELIBS="$LIBS" +IMAGELIBS="" + +AC_SUBST(IMAGELIBS) + +AC_ARG_ENABLE(localjpeg, [ --enable-localjpeg use local JPEG library, default=auto], + [if test x$enable_localjpeg = xyes; then + ac_cv_lib_jpeg_jpeg_CreateCompress=no + fi]) + +AC_CHECK_LIB(jpeg,jpeg_CreateCompress, + AC_DEFINE(HAVE_LIBJPEG) + JPEGINC="" + JPEG="" + IMAGELIBS="-ljpeg $IMAGELIBS", + if test x$enable_localjpeg = xno; then + JPEGINC="" + JPEG="" + else + AC_DEFINE(HAVE_LIBJPEG) + JPEGINC="-I../jpeg" + JPEG="jpeg" + IMAGELIBS="-lfltk_jpeg $IMAGELIBS" + fi) + +AC_ARG_ENABLE(localzlib, [ --enable-localzlib use local ZLIB library, default=auto], + [if test x$enable_localzlib = xyes; then + ac_cv_lib_z_gzgets=no + fi]) + +AC_CHECK_LIB(z,gzgets, + AC_DEFINE(HAVE_LIBZ) + ZLIBINC="" + ZLIB="" + LIBS="-lz $LIBS" + IMAGELIBS="-lz $IMAGELIBS", + if test x$enable_localzlib = xno; then + ZLIBINC="" + ZLIB="" + else + AC_DEFINE(HAVE_LIBZ) + ZLIBINC="-I../zlib" + ZLIB="zlib" + LIBS="-lfltk_z $LIBS" + IMAGELIBS="-lfltk_z $IMAGELIBS" + fi) + +AC_ARG_ENABLE(localpng, [ --enable-localpng use local PNG library, default=auto], + [if test x$enable_localpng = xyes; then + ac_cv_lib_png_png_set_tRNS_to_alpha=no + fi]) + +AC_CHECK_LIB(png,png_set_tRNS_to_alpha, [ + PNGINC="" + PNG="" + IMAGELIBS="-lpng $IMAGELIBS" + AC_DEFINE(HAVE_LIBPNG) + AC_CHECK_HEADER(png.h, AC_DEFINE(HAVE_PNG_H))],[ + if test x$enable_localpng = xno; then + PNGINC="" + PNG="" + else + AC_DEFINE(HAVE_LIBPNG) + AC_DEFINE(HAVE_PNG_H) + PNGINC="-I../png" + PNG="png" + IMAGELIBS="-lfltk_png $IMAGELIBS" + fi]) + +AC_SUBST(JPEG) +AC_SUBST(JPEGINC) +AC_SUBST(PNG) +AC_SUBST(PNGINC) +AC_SUBST(ZLIB) +AC_SUBST(ZLIBINC) + +dnl Restore original LIBS settings... +LIBS="$SAVELIBS" + +dnl See if we need a .exe extension on executables... +AC_EXEEXT + +dnl Check for pthreads for multi-threaded apps... +have_pthread=no + +if test "x$enable_threads" = xyes; then + AC_CHECK_HEADER(pthread.h, AC_DEFINE(HAVE_PTHREAD_H)) + AC_CHECK_LIB(pthread, pthread_create) + + if test "x$ac_cv_lib_pthread_pthread_create" = xyes -a x$ac_cv_header_pthread_h = xyes; then + have_pthread=yes + else + dnl *BSD uses -pthread option... + AC_MSG_CHECKING([for pthread_create using -pthread]) + SAVELIBS="$LIBS" + LIBS="-pthread $LIBS" + AC_TRY_LINK([#include <pthread.h>], + [pthread_create(0, 0, 0, 0);], + LIBS="-pthread $SAVELIBS" + have_pthread=yes, + LIBS="$SAVELIBS") + AC_MSG_RESULT([$have_pthread]) + fi +fi + +dnl Define OS-specific stuff... +HLINKS= +POSTBUILD=: +THREADS= + +AC_ARG_WITH(links, [ --with-links make header links for common misspellings]) + +INSTALL_DESKTOP="" +UNINSTALL_DESKTOP="" + +case $uname in + CYGWIN* | MINGW*) + dnl Cygwin environment... + CFLAGS="-mwindows -DWIN32 $CFLAGS" + CXXFLAGS="-mwindows -DWIN32 $CXXFLAGS" + LDFLAGS="-mwindows $LDFLAGS" + LIBS="$LIBS -lole32 -luuid -lcomctl32 -lwsock32" + OPTIM="$OPTIM" + + if test x$enable_gl != xno; then + AC_CHECK_HEADER(GL/gl.h, + AC_DEFINE(HAVE_GL) + GLLIB="-lopengl32") + AC_CHECK_HEADER(GL/glu.h, + AC_DEFINE(HAVE_GL_GLU_H) + GLLIB="-lglu32 $GLLIB") + else + LINKFLTKGL="" + GLLIBNAME="" + GLDSONAME="" + GLDEMOS="" + fi + + if test "x$enable_threads" = xyes; then + if test x$have_pthread = xyes; then + AC_DEFINE(HAVE_PTHREAD) + fi + + THREADS="threads.exe" + fi + + # Don't make symlinks since Windows is not case sensitive. + if test "x$with_links" != xyes; then + HLINKS="#" + fi + ;; + + Darwin*) + # MacOS X uses Carbon for graphics... + LIBS="$LIBS -framework Carbon -framework ApplicationServices" + + if test x$have_pthread = xyes; then + AC_DEFINE(HAVE_PTHREAD) + THREADS="threads" + fi + + if test x$enable_gl != xno; then + AC_DEFINE(HAVE_GL) + AC_DEFINE(HAVE_GL_GLU_H) + GLLIB="-framework AGL -framework OpenGL" + else + LINKFLTKGL="" + GLLIBNAME="" + GLDSONAME="" + GLDEMOS="" + fi + + # Don't make symlinks because HFS+ is not case sensitive... + if test "x$with_links" != xyes; then + HLINKS="#" + fi + + # Add a postbuild step after linking applications + POSTBUILD="/Developer/Tools/Rez -t APPL -o" + + # Install/Uninstall FLUID application + INSTALL_DESKTOP="install-osx" + UNINSTALL_DESKTOP="uninstall-osx" + ;; + + *) + # All others are UNIX/X11... + if test x$have_pthread = xyes; then + AC_DEFINE(HAVE_PTHREAD) + THREADS="threads" + fi + + dnl Check for X11... + AC_PATH_XTRA + + if test x$no_x = xyes; then + AC_MSG_ERROR(Configure could not find required X11 libraries, aborting.) + fi + + if test "x$X_PRE_LIBS" != x; then + AC_MSG_WARN(Ignoring libraries \"$X_PRE_LIBS\" requested by configure.) + fi + + LIBS="$LIBS -lXext -lX11 $X_EXTRA_LIBS" + CFLAGS="$CFLAGS $X_CFLAGS" + CXXFLAGS="$CXXFLAGS $X_CFLAGS" + LDFLAGS="$X_LIBS $LDFLAGS" + + if test "x$x_includes" != x; then + ac_cpp="$ac_cpp -I$x_includes" + fi + + dnl Check for OpenGL unless disabled... + GLLIB= + + if test x$enable_gl != xno; then + AC_SEARCH_LIBS(dlopen, dl) + AC_CHECK_HEADER(GL/gl.h, + AC_CHECK_LIB(GL, glXMakeCurrent, AC_DEFINE(HAVE_GL) GLLIB="-lGL", \ + AC_CHECK_LIB(MesaGL,glXMakeCurrent, AC_DEFINE(HAVE_GL) GLLIB=" -lMesaGL",,\ + -lm), \ + -lm) + ) + AC_CHECK_HEADER(GL/glu.h, + AC_DEFINE(HAVE_GL_GLU_H) + if test x$ac_cv_lib_GL_glXMakeCurrent = xyes; then + GLLIB="-lGLU $GLLIB" + fi + if test x$ac_cv_lib_MesaGL_glXMakeCurrent = xyes; then + GLLIB="-lMesaGLU $GLLIB" + fi + ) + + if test x$ac_cv_lib_GL_glXMakeCurrent != xyes -a x$ac_cv_lib_MesaGL_glXMakeCurrent != xyes; then + LINKFLTKGL="" + GLLIBNAME="" + GLDSONAME="" + GLDEMOS="" + fi + else + LINKFLTKGL="" + GLLIBNAME="" + GLDSONAME="" + GLDEMOS="" + fi + + dnl Check for Xinerama support unless disabled... + AC_ARG_ENABLE(xinerama, [ --enable-xinerama turn on Xinerama support [default=no]]) + + if test x$enable_xinerama = xyes; then + AC_CHECK_LIB(Xinerama,XineramaIsActive, + AC_DEFINE(HAVE_XINERAMA) + LIBS="-lXinerama $LIBS") + fi + + dnl Check for the Xft library unless disabled... + AC_ARG_ENABLE(xft, [ --enable-xft turn on Xft support [default=no]]) + + if test x$enable_xft = xyes; then + AC_PATH_PROG(FTCONFIG,freetype-config) + + if test "x$FTCONFIG" != "x:"; then + CPPFLAGS="`$FTCONFIG --cflags` $CPPFLAGS" + CXXFLAGS="`$FTCONFIG --cflags` $CXXFLAGS" + + AC_CHECK_HEADER(X11/Xft/Xft.h, + AC_CHECK_LIB(Xft, XftDrawCreate, + AC_DEFINE(USE_XFT) + LIBS="-lXft $LIBS")) + fi + fi + + dnl Check for the Xdbe extension unless disabled... + AC_ARG_ENABLE(xdbe, [ --enable-xdbe turn on Xdbe support [default=no]]) + + if test x$enable_xdbe = xyes; then + AC_CHECK_HEADER(X11/extensions/Xdbe.h, AC_DEFINE(HAVE_XDBE),, + [#include <X11/Xlib.h>]) + fi + + dnl Check for overlay visuals... + AC_CACHE_CHECK(for X overlay visuals, ac_cv_have_overlay, + if xprop -root 2>/dev/null | grep -c "SERVER_OVERLAY_VISUALS" >/dev/null; then + ac_cv_have_overlay=yes + else + ac_cv_have_overlay=no + fi) + + if test x$ac_cv_have_overlay = xyes; then + AC_DEFINE(HAVE_OVERLAY) + fi + + # Make symlinks since UNIX/Linux is case sensitive. + if test "x$with_links" = xno; then + HLINKS="#" + fi + + # Install/Uninstall FLUID application support files + INSTALL_DESKTOP="install-linux" + UNINSTALL_DESKTOP="uninstall-linux" + ;; +esac + +AC_SUBST(GLDEMOS) +AC_SUBST(GLLIB) +AC_SUBST(HLINKS) +AC_SUBST(POSTBUILD) +AC_SUBST(THREADS) + +AC_SUBST(INSTALL_DESKTOP) +AC_SUBST(UNINSTALL_DESKTOP) + +dnl Figure out the appropriate formatted man page extension... +case "$uname" in + *BSD* | Darwin*) + # *BSD + CAT1EXT=0 + CAT3EXT=0 + CAT6EXT=0 + ;; + IRIX*) + # SGI IRIX + CAT1EXT=z + CAT3EXT=z + CAT6EXT=z + ;; + *) + # All others + CAT1EXT=1 + CAT3EXT=3 + CAT6EXT=3 + ;; +esac + +AC_SUBST(CAT1EXT) +AC_SUBST(CAT3EXT) +AC_SUBST(CAT6EXT) + +dnl Fix "mandir" variable... +if test "$mandir" = "\${prefix}/man" -a "$prefix" = "/usr"; then + case "$uname" in + *BSD* | Darwin* | Linux*) + # *BSD, Darwin, and Linux + mandir="\${prefix}/share/man" + ;; + IRIX*) + # SGI IRIX + mandir="\${prefix}/share/catman" + ;; + esac +fi + +dnl Fix "libdir" variable... +if test "$prefix" = NONE; then + prefix=/usr/local +fi + +if test "$exec_prefix" = NONE; then + exec_prefix="\${prefix}" +fi + +if test "$uname" = "IRIX" -a $uversion -ge 62 -a "$libdir" = "\${exec_prefix}/lib" -a "$exec_prefix" = "\${prefix}" -a "$prefix" = "/usr"; then + libdir="/usr/lib32" +fi + +dnl Define the command used to update the dependencies (this option +dnl mainly for FLTK core developers - not necessary for users) +MAKEDEPEND="\$(CXX) -M" +AC_SUBST(MAKEDEPEND) + +dnl Add warnings to compiler switches: +dnl do this last so messing with switches does not break tests + +if test -n "$GCC"; then + # Show all standard warnings + unused variables, conversion errors, + # and inlining problems when compiling... + OPTIM="-Wall -Wunused -Wno-format-y2k $OPTIM" + + # The following additional warnings are useful for tracking down problems... + #OPTIM="-Wshadow -Wconversion $OPTIM" + + # Set the default compiler optimizations... + if test -z "$DEBUGFLAG"; then + # + # Note: Can't use -fomit-frame-pointer - prevents tools like + # libsafe from working! + # + # Don't use -fforce-mem, -fforce-addr, or -fcaller-saves. + # They all seem to make either no difference or enlarge + # the code by a few hundred bytes. + # + # "-Os" seems to be the best compromise between speed and + # code size. "-O3" and higher seem to make no effective + # difference in the speed of the code, but does bloat the + # library 10+%. + # + + if test "x$with_optim" != x; then + OPTIM="$with_optim $OPTIM" + else + OPTIM="-Os $OPTIM" + fi + fi + + # Generate position-independent code when needed... + if test $PICFLAG = 1; then + OPTIM="$OPTIM -fPIC" + fi + + # See if GCC supports -fno-exceptions... + AC_MSG_CHECKING(if GCC supports -fno-exceptions) + OLDCFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fno-exceptions" + AC_TRY_COMPILE(,, + OPTIM="$OPTIM -fno-exceptions" + AC_MSG_RESULT(yes), + AC_MSG_RESULT(no)) + CFLAGS="$OLDCFLAGS" + + # See if we are running Solaris; if so, try the -fpermissive option... + # This option is required on some versions of Solaris to work around + # bugs in the X headers up through Solaris 7. + # + # Unlike the other compiler/optimization settings, this one is placed + # in CFLAGS and CXXFLAGS so that fltk-config will provide the option + # to clients - otherwise client apps will not compile properly... + if test "$uname" = SunOS; then + AC_MSG_CHECKING(if GCC supports -fpermissive) + + OLDCFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fpermissive" + AC_TRY_COMPILE(,, + CXXFLAGS="$CXXFLAGS -fpermissive" + AC_MSG_RESULT(yes), + CFLAGS="$OLDCFLAGS" + AC_MSG_RESULT(no)) + fi +else + case "$uname" in + IRIX*) + # Running some flavor of IRIX; see which version and + # set things up according... + if test "$uversion" -ge 62; then + # We are running IRIX 6.2 or higher; uncomment the following + # lines if you don't have IDO 7.2 or higher: + # + # CXX="CC -n32 -mips3" + # CC="cc -n32 -mips3" + # LD="ld -n32 -mips3" + # MAKEDEPEND="CC -M" + + if test "x`grep abi=n32 /etc/compiler.defaults`" = x; then + AC_MSG_WARN(FOR BEST RESULTS BEFORE COMPILING: setenv SGI_ABI \"-n32 -mips3\") + fi + + OPTIM="-fullwarn $OPTIM" + fi + if test -z "$DEBUGFLAG"; then + if test "x$with_optim" != x; then + OPTIM="$with_optim $OPTIM" + else + OPTIM="-O2 $OPTIM" + if test $uversion -gt 62; then + OPTIM="-OPT:Olimit=4000 $OPTIM" + fi + fi + fi + ;; + HP-UX*) + # Running HP-UX; these options should work for the HP compilers. + if test -z "$DEBUGFLAG"; then + if test "x$with_optim" != x; then + OPTIM="$with_optim $OPTIM" + else + OPTIM="+O2 $OPTIM" + fi + fi + + if test "x$with_optim" = x; then + OPTIM="$OPTIM +DAportable" + fi + + if test $PICFLAG = 1; then + OPTIM="+z $OPTIM" + fi + + OPTIM="$OPTIM +W336,501,736,740,749,829" + ;; + OSF1*) + # Running Digital/Tru64 UNIX; these options should work for the + # Digital/Compaq/NewHP compilers. + if test -z "$DEBUGFLAG"; then + if test "x$with_optim" != x; then + OPTIM="$with_optim $OPTIM" + else + OPTIM="-O2 $OPTIM" + fi + fi + ;; + SunOS*) + # Solaris + if test -z "$DEBUGFLAG"; then + if test "x$with_optim" != x; then + OPTIM="$with_optim $OPTIM" + else + OPTIM="-xO3 $OPTIM" + fi + fi + + if test $PICFLAG = 1; then + OPTIM="-KPIC $OPTIM" + fi + ;; + AIX*) + if test -z "$DEBUGFLAG"; then + if test "x$with_optim" != x; then + OPTIM="$with_optim $OPTIM" + else + OPTIM="-O2 $OPTIM" + fi + fi + + AC_MSG_WARN(The AIX C and C++ compilers are known not to correctly compile the FLTK library.) + ;; + *) + # Running some other operating system; inform the user they + # should contribute the necessary options to fltk-bugs@fltk.org... + AC_MSG_WARN(Building FLTK with default compiler optimizations) + AC_MSG_WARN(Contact fltk-bugs@fltk.org with uname and compiler options.) + ;; + esac +fi + +OPTIM="$DEBUGFLAG $OPTIM" + +dnl Define the FLTK documentation directory... +if test x$prefix = xNONE; then + AC_DEFINE_UNQUOTED(FLTK_DOCDIR, "/usr/local/share/doc/fltk") +else + AC_DEFINE_UNQUOTED(FLTK_DOCDIR, "$prefix/share/doc/fltk") +fi + +dnl Define the FLTK data directory... +if test x$prefix = xNONE; then + AC_DEFINE_UNQUOTED(FLTK_DATADIR, "/usr/local/share/fltk") +else + AC_DEFINE_UNQUOTED(FLTK_DATADIR, "$prefix/share/fltk") +fi + +dnl Write all of the files... +AC_CONFIG_HEADER(config.h:configh.in) +AC_OUTPUT(makeinclude fltk.list fltk-config FL/Makefile) + +dnl Make sure the fltk-config script is executable... +chmod +x fltk-config + +dnl +dnl End of "$Id: configure.in 4756 2006-01-15 18:36:16Z mike $". +dnl diff --git a/Utilities/FLTK/fltk-config.in b/Utilities/FLTK/fltk-config.in new file mode 100755 index 0000000000..b7b3e80128 --- /dev/null +++ b/Utilities/FLTK/fltk-config.in @@ -0,0 +1,308 @@ +#!/bin/sh +# +# "$Id: fltk-config.in 4689 2005-12-07 20:13:12Z mike $" +# +# FLTK configuration utility. +# +# Copyright 2000-2005 by Bill Spitzak and others. +# Original version Copyright 2000 by James Dean Palmer +# Adapted by Vincent Penne and Michael Sweet +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. +# +# Please report all bugs and problems on the following page: +# +# http://www.fltk.org/str.php +# + +MAJOR_VERSION=@FL_MAJOR_VERSION@ +MINOR_VERSION=@FL_MINOR_VERSION@ +PATCH_VERSION=@FL_PATCH_VERSION@ +VERSION="$MAJOR_VERSION.$MINOR_VERSION.$PATCH_VERSION" +APIVERSION="$MAJOR_VERSION.$MINOR_VERSION" + +### BEGIN fltk-config +selfdir=`dirname $0` + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +exec_prefix_set=no +bindir=@bindir@ +includedir=@includedir@ +libdir=@libdir@ +srcdir=@srcdir@ + +# compiler names +CC="@CC@" +CXX="@CXX@" + +# post-process command (only needed for MacOS) +POSTBUILD="@POSTBUILD@" + +# flags for C++ compiler: +CFLAGS="@CFLAGS@" +CXXFLAGS="@CXXFLAGS@" +LDFLAGS="@LDFLAGS@" +LDLIBS="@LIBS@" + +# Check for local invocation, and update paths accordingly... +if test -f "$selfdir/FL/Fl_Window.H"; then + bindir="$selfdir/fluid" + includedir="$selfdir" + libdir="$selfdir/lib" + + if test -f "$libdir/libfltk_jpeg.a"; then + CFLAGS="-I$includedir/jpeg $CFLAGS" + CXXFLAGS="-I$includedir/jpeg $CXXFLAGS" + fi + + if test -f "$libdir/libfltk_z.a"; then + CFLAGS="-I$includedir/zlib $CFLAGS" + CXXFLAGS="-I$includedir/zlib $CXXFLAGS" + fi + + if test -f "$libdir/libfltk_png.a"; then + CFLAGS="-I$includedir/png $CFLAGS" + CXXFLAGS="-I$includedir/png $CXXFLAGS" + fi +fi + +if test -d $includedir/FL/images; then + CFLAGS="-I$includedir/FL/images $CFLAGS" + CXXFLAGS="-I$includedir/FL/images $CXXFLAGS" +fi + +# libraries to link with: +LIBNAME="@LIBNAME@" +DSONAME="@DSONAME@" +DSOLINK="@DSOLINK@" +IMAGELIBS="@IMAGELIBS@" +SHAREDSUFFIX="@SHAREDSUFFIX@" + +usage () +{ + echo "Usage: fltk-config [OPTIONS] +Options: + [--version] + [--api-version] + +Options telling what we are doing: + [--use-gl] use GL + [--use-images] use extra image formats (PNG, JPEG) + [--use-glut] use glut compatibility layer + [--use-forms] use forms compatibility layer + +Options telling what information we request: + [--cc] return C compiler used to compile FLTK + [--cxx] return C++ compiler used to compile FLTK + [--cflags] return flags to compile C using FLTK + [--cxxflags] return flags to compile C++ using FLTK + [--ldflags] return flags to link against FLTK + [--ldstaticflags] return flags to link against static FLTK library + even if there are DSOs installed + [--libs] return FLTK libraries full path for dependencies + +Option to compile and link an application: + [-g] compile the program with debugging information + [--compile program.cxx] + [--post program] +" + exit $1 +} + +if test $# -eq 0; then + usage 1 +fi + +no_plugins=no +compile= +post= +debug= + +# Parse command line options +while test $# -gt 0 +do + case "$1" in + -*=*) + optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` + ;; + *) + optarg= + ;; + esac + + case $1 in + --version) + echo $VERSION + ;; + --api-version) + echo $APIVERSION + ;; + --cc) + echo $CC + ;; + --cxx) + echo $CXX + ;; + --use-gl | --use-glut) + use_gl=yes + ;; + --use-forms) + use_forms=yes + ;; + --use-images) + use_images=yes + ;; + --cflags) + echo_cflags=yes + ;; + --cxxflags) + echo_cxxflags=yes + ;; + --ldflags) + echo_ldflags=yes + ;; + --ldstaticflags) + echo_ldstaticflags=yes + ;; + --libs) + echo_libs=yes + ;; + -g) + debug=-g + ;; + --compile) + compile=$2 + post=$2 + shift + ;; + --post) + post=$2 + shift + ;; + *) + echo_help=yes + ;; + esac + shift +done + +if test "$includedir" != /usr/include; then + includes=-I$includedir +else + includes= +fi + +if test "$libdir" != /usr/lib -a "$libdir" != /usr/lib32; then + libs=-L$libdir +else + libs= +fi + +# Calculate needed libraries +LDSTATIC="$libdir/libfltk.a $LDLIBS" +LDLIBS="-lfltk$SHAREDSUFFIX $LDLIBS" +LIBS="$libdir/libfltk.a" + +if test x$use_forms = xyes; then + LDLIBS="-lfltk_forms$SHAREDSUFFIX $LDLIBS" + LDSTATIC="$libdir/libfltk_forms.a $LDSTATIC" + LIBS="$LIBS $libdir/libfltk_forms.a" +fi +if test x$use_gl = xyes; then + LDLIBS="-lfltk_gl$SHAREDSUFFIX @GLLIB@ $LDLIBS" + LDSTATIC="$libdir/libfltk_gl.a @GLLIB@ $LDSTATIC" + LIBS="$LIBS $libdir/libfltk_gl.a" +fi +if test x$use_images = xyes; then + LDLIBS="-lfltk_images$SHAREDSUFFIX $IMAGELIBS $LDLIBS" + LDSTATIC="$libdir/libfltk_images.a $IMAGELIBS $LDSTATIC" +fi + +LDLIBS="$DSOLINK $LDFLAGS $libs $LDLIBS" +LDSTATIC="$LDFLAGS $libs $LDSTATIC" + +# Answer to user requests +if test -n "$echo_help"; then + usage 1 +fi + +if test -n "$compile"; then + case $compile in + *.cxx) + prog=`basename $compile .cxx` + ;; + *.cpp) + prog=`basename $compile .cpp` + ;; + *.cc) + prog=`basename $compile .cc` + ;; + *.C) + prog=`basename $compile .C` + ;; + *) + echo "ERROR: Unknown/bad C++ source file extension on \"$compile\"!" + exit 1 + ;; + esac + + post=$prog + + echo $CXX $includes $CXXFLAGS $debug -o $prog $compile $LDSTATIC + $CXX $includes $CXXFLAGS $debug -o $prog $compile $LDSTATIC +fi + +if test -n "$post" -a "$POSTBUILD" != ":"; then + echo $POSTBUILD $post $includedir/FL/mac.r + $POSTBUILD $post $includedir/FL/mac.r +fi + +if test "$echo_cflags" = "yes"; then + echo $includes $CFLAGS +fi + +if test "$echo_cxxflags" = "yes"; then + echo $includes $CXXFLAGS +fi + +if test "$echo_ldflags" = "yes"; then + my_libs= + libdirs=$libs + + for i in $LDLIBS ; do + if test $i != -L$libdir ; then + if test -z "$my_libs" ; then + my_libs="$i" + else + my_libs="$my_libs $i" + fi + fi + done + echo $libdirs $my_libs +fi + +if test "$echo_ldstaticflags" = "yes"; then + echo $LDSTATIC +fi + +if test "$echo_libs" = "yes"; then + echo $LIBS +fi + +# +# End of "$Id: fltk-config.in 4689 2005-12-07 20:13:12Z mike $". +# diff --git a/Utilities/FLTK/fltk.list.in b/Utilities/FLTK/fltk.list.in new file mode 100644 index 0000000000..2678e68281 --- /dev/null +++ b/Utilities/FLTK/fltk.list.in @@ -0,0 +1,404 @@ +# +# "$Id: fltk.list.in 4761 2006-01-15 20:33:10Z mike $" +# +# EPM product list file for the Fast Light Tool Kit (FLTK). +# +# (EPM can be found at http://www.easysw.com/epm/) +# +# Copyright 1998-2006 by Bill Spitzak and others. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. +# +# Please report all bugs and problems on the following page: +# +# http://www.fltk.org/str.php +# + +%product Fast Light Tool Kit (FLTK) +%copyright 1998-2006 by Bill Spitzak and others. +%vendor FLTK Development Team +%license COPYING +%readme README +%version @FL_MAJOR_VERSION@.@FL_MINOR_VERSION@.@FL_PATCH_VERSION@ +%description The Fast Light Tool Kit ("FLTK", pronounced "fulltick") is a +%description cross-platform C++ GUI toolkit for UNIX(r)/Linux(r) (X11), +%description Microsoft(r) Windows(r), and MacOS(r) X. FLTK provides modern +%description GUI functionality without the bloat and supports 3D graphics via +%description OpenGL(r) and its built-in GLUT emulation. + +$prefix=@prefix@ +$exec_prefix=@exec_prefix@ +$bindir=@bindir@ +$datadir=@datadir@ +$includedir=@includedir@ +$libdir=@libdir@ +$mandir=@mandir@ +$docdir=$(datadir)/doc/fltk + +$CAT1EXT=@CAT1EXT@ +$CAT3EXT=@CAT3EXT@ +$CAT6EXT=@CAT6EXT@ + +$DSONAME=@DSONAME@ +$FLDSONAME=@FLDSONAME@ +$FLLIBNAME=@FLLIBNAME@ +$GLDSONAME=@GLDSONAME@ +$GLLIBNAME=@GLLIBNAME@ +$FLUID=@FLUID@ +$JPEG=@JPEG@ +$PNG=@PNG@ +$ZLIB=@ZLIB@ + +%if DSONAME +%system aix +f 0555 root sys $libdir/libfltk_s.a src/libfltk_s.a nostrip() +%system hpux +f 0555 root sys $libdir/libfltk.sl.@FL_API_VERSION@ src/libfltk.sl.@FL_API_VERSION@ nostrip() +%system darwin +f 0555 root sys $libdir/libfltk.@FL_API_VERSION@.dylib src/libfltk.@FL_API_VERSION@.dylib nostrip() +%system !aix !darwin !hpux +f 0555 root sys $libdir/libfltk.so.@FL_API_VERSION@ src/libfltk.so.@FL_API_VERSION@ nostrip() +%system all + +%system aix +f 0555 root sys $libdir/libfltk_forms_s.a src/libfltk_forms_s.a nostrip() +%system hpux +f 0555 root sys $libdir/libfltk_forms.sl.@FL_API_VERSION@ src/libfltk_forms.sl.@FL_API_VERSION@ nostrip() +%system darwin +f 0555 root sys $libdir/libfltk_forms.@FL_API_VERSION@.dylib src/libfltk_forms.@FL_API_VERSION@.dylib nostrip() +%system !aix !darwin !hpux +f 0555 root sys $libdir/libfltk_forms.so.@FL_API_VERSION@ src/libfltk_forms.so.@FL_API_VERSION@ nostrip() +%system all + +%system aix +f 0555 root sys $libdir/libfltk_images_s.a src/libfltk_images_s.a nostrip() +%system hpux +f 0555 root sys $libdir/libfltk_images.sl.@FL_API_VERSION@ src/libfltk_images.sl.@FL_API_VERSION@ nostrip() +%system darwin +f 0555 root sys $libdir/libfltk_images.@FL_API_VERSION@.dylib src/libfltk_images.@FL_API_VERSION@.dylib nostrip() +%system !aix !darwin !hpux +f 0555 root sys $libdir/libfltk_images.so.@FL_API_VERSION@ src/libfltk_images.so.@FL_API_VERSION@ nostrip() +%system all +%endif + +%if GLDSONAME +%system aix +f 0555 root sys $libdir/libfltk_gl_s.a src/libfltk_gl_s.a nostrip() +%system hpux +f 0555 root sys $libdir/libfltk_gl.sl.@FL_API_VERSION@ src/libfltk_gl.sl.@FL_API_VERSION@ nostrip() +%system darwin +f 0555 root sys $libdir/libfltk_gl.@FL_API_VERSION@.dylib src/libfltk_gl.@FL_API_VERSION@.dylib nostrip() +%system !aix !darwin !hpux +f 0555 root sys $libdir/libfltk_gl.so.@FL_API_VERSION@ src/libfltk_gl.so.@FL_API_VERSION@ nostrip() +%system all +%endif + + +%subpackage devel +%description FLTK Development Environment +%description Install fltk-devel if you need to develop FLTK applications. +%description You'll need to install the fltk package if you plan to run +%description dynamically linked applications. + +%system darwin +f 0444 root sys $includedir/FL/mac.r FL/mac.r +l 0444 root sys /usr/include/gcc/darwin/3.1/g++-v3/FL $includedir/FL + +d 0555 root sys /Applications/fluid.app - +d 0555 root sys /Applications/fluid.app/Contents - +f 0444 root sys /Applications/fluid.app/Contents/Info.plist fluid/fluid.app/Contents/Info.plist +f 0444 root sys /Applications/fluid.app/Contents/PkgInfo fluid/fluid.app/Contents/PkgInfo +d 0555 root sys /Applications/fluid.app/Contents/MacOS - +l 0555 root sys /Applications/fluid.app/Contents/MacOS/fluid $bindir/fluid +d 0555 root sys /Applications/fluid.app/Contents/Resources - +f 0444 root sys /Applications/fluid.app/Contents/Resources/fluid.icns fluid/fluid.app/Contents/Resources/fluid.icns +%postinstall $bindir/fltk-config --post $bindir/fluid +%postremove /bin/rm -rf /Applications/fluid.app + +%system !darwin +f 0444 root sys /usr/share/applnk/Development/fluid.desktop fluid/fluid.desktop +f 0444 root sys /usr/share/icons/hicolor/16x16/apps/fluid.png fluid/icons/fluid-16.png +f 0444 root sys /usr/share/icons/hicolor/32x32/apps/fluid.png fluid/icons/fluid-32.png +f 0444 root sys /usr/share/icons/hicolor/48x48/apps/fluid.png fluid/icons/fluid-48.png +f 0444 root sys /usr/share/icons/hicolor/64x64/apps/fluid.png fluid/icons/fluid-64.png +f 0444 root sys /usr/share/icons/hicolor/128x128/apps/fluid.png fluid/icons/fluid-128.png +f 0444 root sys /usr/share/mimelnk/application/x-fluid.desktop fluid/x-fluid.desktop + +%system all + +# FLUID +f 0555 root sys $bindir/fluid fluid/$FLUID +f 0555 root sys $bindir/fltk-config fltk-config + +# Man pages +f 0444 root sys $mandir/cat1/fluid.$CAT1EXT documentation/fluid.$CAT1EXT +f 0444 root sys $mandir/cat1/fltk-config.$CAT1EXT documentation/fltk-config.$CAT1EXT +f 0444 root sys $mandir/cat3/fltk.$CAT3EXT documentation/fltk.$CAT3EXT +f 0444 root sys $mandir/man1/fluid.1 documentation/fluid.man +f 0444 root sys $mandir/man1/fltk-config.1 documentation/fltk-config.man +f 0444 root sys $mandir/man3/fltk.3 documentation/fltk.man + +# Library files +f 0444 root sys $libdir/libfltk.a lib/libfltk.a +f 0444 root sys $libdir/libfltk_forms.a lib/libfltk_forms.a +f 0444 root sys $libdir/libfltk_images.a lib/libfltk_images.a +%if GLLIBNAME +f 0444 root sys $libdir/libfltk_gl.a lib/libfltk_gl.a +%endif + +%if JPEG +f 0444 root sys $libdir/libfltk_jpeg.a lib/libfltk_jpeg.a +%endif + +%if PNG +f 0444 root sys $libdir/libfltk_png.a lib/libfltk_png.a +%endif + +%if ZLIB +f 0444 root sys $libdir/libfltk_z.a lib/libfltk_z.a +%endif + +%if DSONAME +%system hpux +l 0000 root sys $libdir/libfltk.sl libfltk.sl.@FL_API_VERSION@ +%system darwin +l 0000 root sys $libdir/libfltk.dylib libfltk.@FL_API_VERSION@.dylib +%system !aix !darwin !hpux +l 0000 root sys $libdir/libfltk.so libfltk.so.@FL_API_VERSION@ +%system all + +%system hpux +l 0000 root sys $libdir/libfltk_forms.sl libfltk_forms.sl.@FL_API_VERSION@ +%system darwin +l 0000 root sys $libdir/libfltk_forms.dylib libfltk_forms.@FL_API_VERSION@.dylib +%system !aix !darwin !hpux +l 0000 root sys $libdir/libfltk_forms.so libfltk_forms.so.@FL_API_VERSION@ +%system all + +%system hpux +l 0000 root sys $libdir/libfltk_images.sl libfltk_images.sl.@FL_API_VERSION@ +%system darwin +l 0000 root sys $libdir/libfltk_images.dylib libfltk_images.@FL_API_VERSION@.dylib +%system !aix !darwin !hpux +l 0000 root sys $libdir/libfltk_images.so libfltk_images.so.@FL_API_VERSION@ +%system all +%endif + +%if GLDSONAME +%system hpux +l 0000 root sys $libdir/libfltk_gl.sl libfltk_gl.sl.@FL_API_VERSION@ +%system darwin +l 0000 root sys $libdir/libfltk_gl.dylib libfltk_gl.@FL_API_VERSION@.dylib +%system !aix !darwin !hpux +l 0000 root sys $libdir/libfltk_gl.so libfltk_gl.so.@FL_API_VERSION@ +%system all +%endif + +# Header files +f 0444 root sys $includedir/FL/ FL/*.[hH] + +%if JPEG +f 0444 root sys $includedir/FL/images/jconfig.h jpeg/jconfig.h +f 0444 root sys $includedir/FL/images/jerror.h jpeg/jerror.h +f 0444 root sys $includedir/FL/images/jmorecfg.h jpeg/jmorecfg.h +f 0444 root sys $includedir/FL/images/jpeglib.h jpeg/jpeglib.h +%endif + +%if PNG +f 0444 root sys $includedir/FL/images/png.h png/png.h +f 0444 root sys $includedir/FL/images/pngconf.h png/pngconf.h +%endif + +%if ZLIB +f 0444 root sys $includedir/FL/images/zconf.h zlib/zconf.h +f 0444 root sys $includedir/FL/images/zlib.h zlib/zlib.h +f 0444 root sys $includedir/FL/images/zutil.h zlib/zutil.h +%endif + +%system !darwin +# Symlinks to handle common case problems... +l 0000 root sys $includedir/Fl FL +l 0000 root sys $includedir/FL/Enumerations.h Enumerations.H +l 0000 root sys $includedir/FL/Fl.h Fl.H +l 0000 root sys $includedir/FL/Fl_Adjuster.h Fl_Adjuster.H +l 0000 root sys $includedir/FL/Fl_Bitmap.h Fl_Bitmap.H +l 0000 root sys $includedir/FL/Fl_BMP_Image.h Fl_BMP_Image.H +l 0000 root sys $includedir/FL/Fl_Box.h Fl_Box.H +l 0000 root sys $includedir/FL/Fl_Browser.h Fl_Browser.H +l 0000 root sys $includedir/FL/Fl_Browser_.h Fl_Browser_.H +l 0000 root sys $includedir/FL/Fl_Button.h Fl_Button.H +l 0000 root sys $includedir/FL/Fl_Chart.h Fl_Chart.H +l 0000 root sys $includedir/FL/Fl_Check_Browser.h Fl_Check_Browser.H +l 0000 root sys $includedir/FL/Fl_Check_Button.h Fl_Check_Button.H +l 0000 root sys $includedir/FL/Fl_Choice.h Fl_Choice.H +l 0000 root sys $includedir/FL/Fl_Clock.h Fl_Clock.H +l 0000 root sys $includedir/FL/Fl_Color_Chooser.h Fl_Color_Chooser.H +l 0000 root sys $includedir/FL/Fl_Counter.h Fl_Counter.H +l 0000 root sys $includedir/FL/Fl_Dial.h Fl_Dial.H +l 0000 root sys $includedir/FL/Fl_Double_Window.h Fl_Double_Window.H +l 0000 root sys $includedir/FL/Fl_File_Browser.h Fl_File_Browser.H +l 0000 root sys $includedir/FL/Fl_File_Chooser.h Fl_File_Chooser.H +l 0000 root sys $includedir/FL/Fl_File_Icon.h Fl_File_Icon.H +l 0000 root sys $includedir/FL/Fl_Fill_Dial.h Fl_Fill_Dial.H +l 0000 root sys $includedir/FL/Fl_Fill_Slider.h Fl_Fill_Slider.H +l 0000 root sys $includedir/FL/Fl_Float_Input.h Fl_Float_Input.H +l 0000 root sys $includedir/FL/Fl_FormsBitmap.h Fl_FormsBitmap.H +l 0000 root sys $includedir/FL/Fl_FormsPixmap.h Fl_FormsPixmap.H +l 0000 root sys $includedir/FL/Fl_Free.h Fl_Free.H +l 0000 root sys $includedir/FL/Fl_GIF_Image.h Fl_GIF_Image.H +l 0000 root sys $includedir/FL/Fl_Gl_Window.h Fl_Gl_Window.H +l 0000 root sys $includedir/FL/Fl_Group.h Fl_Group.H +l 0000 root sys $includedir/FL/Fl_Help_Dialog.h Fl_Help_Dialog.H +l 0000 root sys $includedir/FL/Fl_Help_View.h Fl_Help_View.H +l 0000 root sys $includedir/FL/Fl_Hold_Browser.h Fl_Hold_Browser.H +l 0000 root sys $includedir/FL/Fl_Hor_Fill_Slider.h Fl_Hor_Fill_Slider.H +l 0000 root sys $includedir/FL/Fl_Hor_Nice_Slider.h Fl_Hor_Nice_Slider.H +l 0000 root sys $includedir/FL/Fl_Hor_Slider.h Fl_Hor_Slider.H +l 0000 root sys $includedir/FL/Fl_Hor_Value_Slider.h Fl_Hor_Value_Slider.H +l 0000 root sys $includedir/FL/Fl_Image.h Fl_Image.H +l 0000 root sys $includedir/FL/Fl_JPEG_Image.h Fl_JPEG_Image.H +l 0000 root sys $includedir/FL/Fl_Input.h Fl_Input.H +l 0000 root sys $includedir/FL/Fl_Input_.h Fl_Input_.H +l 0000 root sys $includedir/FL/Fl_Input_Choice.h Fl_Input_Choice.H +l 0000 root sys $includedir/FL/Fl_Int_Input.h Fl_Int_Input.H +l 0000 root sys $includedir/FL/Fl_Light_Button.h Fl_Light_Button.H +l 0000 root sys $includedir/FL/Fl_Line_Dial.h Fl_Line_Dial.H +l 0000 root sys $includedir/FL/Fl_Menu.h Fl_Menu.H +l 0000 root sys $includedir/FL/Fl_Menu_.h Fl_Menu_.H +l 0000 root sys $includedir/FL/Fl_Menu_Bar.h Fl_Menu_Bar.H +l 0000 root sys $includedir/FL/Fl_Menu_Button.h Fl_Menu_Button.H +l 0000 root sys $includedir/FL/Fl_Menu_Item.h Fl_Menu_Item.H +l 0000 root sys $includedir/FL/Fl_Menu_Window.h Fl_Menu_Window.H +l 0000 root sys $includedir/FL/Fl_Multi_Browser.h Fl_Multi_Browser.H +l 0000 root sys $includedir/FL/Fl_Multi_Label.h Fl_Multi_Label.H +l 0000 root sys $includedir/FL/Fl_Multiline_Input.h Fl_Multiline_Input.H +l 0000 root sys $includedir/FL/Fl_Multiline_Output.h Fl_Multiline_Output.H +l 0000 root sys $includedir/FL/Fl_Nice_Slider.h Fl_Nice_Slider.H +l 0000 root sys $includedir/FL/Fl_Object.h Fl_Object.H +l 0000 root sys $includedir/FL/Fl_Output.h Fl_Output.H +l 0000 root sys $includedir/FL/Fl_Overlay_Window.h Fl_Overlay_Window.H +l 0000 root sys $includedir/FL/Fl_Pack.h Fl_Pack.H +l 0000 root sys $includedir/FL/Fl_Pixmap.h Fl_Pixmap.H +l 0000 root sys $includedir/FL/Fl_PNG_Image.h Fl_PNG_Image.H +l 0000 root sys $includedir/FL/Fl_PNM_Image.h Fl_PNM_Image.H +l 0000 root sys $includedir/FL/Fl_Positioner.h Fl_Positioner.H +l 0000 root sys $includedir/FL/Fl_Progress.h Fl_Progress.H +l 0000 root sys $includedir/FL/Fl_Radio_Button.h Fl_Radio_Button.H +l 0000 root sys $includedir/FL/Fl_Radio_Light_Button.h Fl_Radio_Light_Button.H +l 0000 root sys $includedir/FL/Fl_Radio_Round_Button.h Fl_Radio_Round_Button.H +l 0000 root sys $includedir/FL/Fl_Repeat_Button.h Fl_Repeat_Button.H +l 0000 root sys $includedir/FL/Fl_Return_Button.h Fl_Return_Button.H +l 0000 root sys $includedir/FL/Fl_Roller.h Fl_Roller.H +l 0000 root sys $includedir/FL/Fl_Round_Button.h Fl_Round_Button.H +l 0000 root sys $includedir/FL/Fl_Round_Clock.h Fl_Round_Clock.H +l 0000 root sys $includedir/FL/Fl_Scroll.h Fl_Scroll.H +l 0000 root sys $includedir/FL/Fl_Scrollbar.h Fl_Scrollbar.H +l 0000 root sys $includedir/FL/Fl_Secret_Input.h Fl_Secret_Input.H +l 0000 root sys $includedir/FL/Fl_Select_Browser.h Fl_Select_Browser.H +l 0000 root sys $includedir/FL/Fl_Simple_Counter.h Fl_Simple_Counter.H +l 0000 root sys $includedir/FL/Fl_Single_Window.h Fl_Single_Window.H +l 0000 root sys $includedir/FL/Fl_Slider.h Fl_Slider.H +l 0000 root sys $includedir/FL/Fl_Spinner.h Fl_Spinner.H +l 0000 root sys $includedir/FL/Fl_Tabs.h Fl_Tabs.H +l 0000 root sys $includedir/FL/Fl_Tile.h Fl_Tile.H +l 0000 root sys $includedir/FL/Fl_Timer.h Fl_Timer.H +l 0000 root sys $includedir/FL/Fl_Toggle_Button.h Fl_Toggle_Button.H +l 0000 root sys $includedir/FL/Fl_Toggle_Light_Button.h Fl_Toggle_Light_Button.H +l 0000 root sys $includedir/FL/Fl_Toggle_Round_Button.h Fl_Toggle_Round_Button.H +l 0000 root sys $includedir/FL/Fl_Tooltip.h Fl_Tooltip.H +l 0000 root sys $includedir/FL/Fl_Valuator.h Fl_Valuator.H +l 0000 root sys $includedir/FL/Fl_Value_Input.h Fl_Value_Input.H +l 0000 root sys $includedir/FL/Fl_Value_Output.h Fl_Value_Output.H +l 0000 root sys $includedir/FL/Fl_Value_Slider.h Fl_Value_Slider.H +l 0000 root sys $includedir/FL/Fl_Widget.h Fl_Widget.H +l 0000 root sys $includedir/FL/Fl_Window.h Fl_Window.H +l 0000 root sys $includedir/FL/Fl_XBM_Image.h Fl_XBM_Image.H +l 0000 root sys $includedir/FL/Fl_XPM_Image.h Fl_XPM_Image.H +l 0000 root sys $includedir/FL/filename.h filename.H +l 0000 root sys $includedir/FL/fl_ask.h fl_ask.H +l 0000 root sys $includedir/FL/fl_draw.h fl_draw.H +l 0000 root sys $includedir/FL/fl_file_chooser.h Fl_File_Chooser.H +l 0000 root sys $includedir/FL/fl_file_chooser.H Fl_File_Chooser.H +l 0000 root sys $includedir/FL/fl_message.h fl_message.H +l 0000 root sys $includedir/FL/fl_show_colormap.h fl_show_colormap.H +l 0000 root sys $includedir/FL/fl_show_input.h fl_show_input.H +l 0000 root sys $includedir/FL/forms.h forms.H +l 0000 root sys $includedir/FL/gl_draw.h gl_draw.H +l 0000 root sys $includedir/FL/glut.h glut.H +l 0000 root sys $includedir/FL/win32.h win32.H +l 0000 root sys $includedir/FL/x.h x.H +%system all + +# Documentation +d 0555 root sys $docdir - +f 0444 root sys $docdir/ documentation/*.gif +f 0444 root sys $docdir/ documentation/*.html +f 0444 root sys $docdir/ documentation/*.jpg +f 0444 root sys $docdir/COPYING COPYING +f 0444 root sys $docdir/CHANGES CHANGES + +# Examples +d 0555 root sys $docdir/examples +f 0444 root sys $docdir/examples/config.h config.h +f 0444 root sys $docdir/examples/ test/*.cxx +f 0444 root sys $docdir/examples/ test/*.fl +f 0444 root sys $docdir/examples/ test/*.h + +%subpackage games +%description FLTK Games +%description Install fltk-games to play checkers or Sudoku on your computer. + +%system darwin +d 0555 root sys /Applications/checkers.app - +d 0555 root sys /Applications/checkers.app/Contents - +f 0444 root sys /Applications/checkers.app/Contents/Info.plist test/checkers.app/Contents/Info.plist +f 0444 root sys /Applications/checkers.app/Contents/PkgInfo test/checkers.app/Contents/PkgInfo +d 0555 root sys /Applications/checkers.app/Contents/MacOS - +f 0555 root sys /Applications/checkers.app/Contents/MacOS/checkers test/checkers +d 0555 root sys /Applications/checkers.app/Contents/Resources - +f 0444 root sys /Applications/checkers.app/Contents/Resources/checkers.icns test/checkers.app/Contents/Resources/checkers.icns +%postremove /bin/rm -rf /Applications/checkers.app + +d 0555 root sys /Applications/sudoku.app - +d 0555 root sys /Applications/sudoku.app/Contents - +f 0444 root sys /Applications/sudoku.app/Contents/Info.plist test/sudoku.app/Contents/Info.plist +f 0444 root sys /Applications/sudoku.app/Contents/PkgInfo test/sudoku.app/Contents/PkgInfo +d 0555 root sys /Applications/sudoku.app/Contents/MacOS - +f 0555 root sys /Applications/sudoku.app/Contents/MacOS/sudoku test/sudoku +d 0555 root sys /Applications/sudoku.app/Contents/Resources - +f 0444 root sys /Applications/sudoku.app/Contents/Resources/sudoku.icns test/sudoku.app/Contents/Resources/sudoku.icns +%postremove /bin/rm -rf /Applications/sudoku.app + +%system !darwin +f 0555 root sys $bindir/checkers test/checkers +f 0444 root sys /usr/share/applnk/Games/checkers.desktop test/checkers.desktop +f 0444 root sys /usr/share/icons/hicolor/32x32/apps/checkers.png checkers/checkers-32.png +f 0444 root sys /usr/share/icons/hicolor/128x128/apps/checkers.png checkers/checkers-128.png + +f 0555 root sys $bindir/sudoku test/sudoku +f 0444 root sys /usr/share/applnk/Games/sudoku.desktop test/sudoku.desktop +f 0444 root sys /usr/share/icons/hicolor/32x32/apps/sudoku.png sudoku/sudoku-32.png +f 0444 root sys /usr/share/icons/hicolor/128x128/apps/sudoku.png sudoku/sudoku-128.png + +%system all +f 0444 root sys $mandir/cat6/checkers.$CAT6EXT documentation/checkers.$CAT6EXT +f 0444 root sys $mandir/cat6/sudoku.$CAT6EXT documentation/sudoku.$CAT6EXT +f 0444 root sys $mandir/man6/checkers.6 documentation/checkers.man +f 0444 root sys $mandir/man6/sudoku.6 documentation/sudoku.man + +# +# End of "$Id: fltk.list.in 4761 2006-01-15 20:33:10Z mike $". +# diff --git a/Utilities/FLTK/fltk.spec b/Utilities/FLTK/fltk.spec new file mode 100644 index 0000000000..ce4d72fe6a --- /dev/null +++ b/Utilities/FLTK/fltk.spec @@ -0,0 +1,143 @@ +# +# "$Id: fltk.spec.in 4756 2006-01-15 18:36:16Z mike $" +# +# RPM spec file for FLTK. +# +# Copyright 1998-2006 by Bill Spitzak and others. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. +# +# Please report all bugs and problems on the following page: +# +# http://www.fltk.org/str.php +# + +%define version 1.1.7 +%define release 1 +%define prefix /usr + +Summary: Fast Light Tool Kit (FLTK) +Name: fltk +Version: %{version} +Release: %{release} +License: LGPL +Group: System Environment/Libraries +Source: ftp://ftp.easysw.com/pub/fltk/1.1.7/fltk-1.1.7-source.tar.bz2 +URL: http://www.fltk.org/ +Packager: FLTK Developer <fltk@fltk.org> +# use BuildRoot so as not to disturb the version already installed +BuildRoot: /var/tmp/fltk-%{PACKAGE_VERSION} + +%description +The Fast Light Tool Kit ("FLTK", pronounced "fulltick") is a +cross-platform C++ GUI toolkit for UNIX(r)/Linux(r) (X11), +Microsoft(r) Windows(r), and MacOS(r) X. FLTK provides modern +GUI functionality without the bloat and supports 3D graphics via +OpenGL(r) and its built-in GLUT emulation. + +%package devel +Summary: FLTK Development Environment +Group: Development/Libraries + +%description devel +Install fltk-devel if you need to develop FLTK applications. +You'll need to install the fltk package if you plan to run +dynamically linked applications. + +%package games +Summary: FLTK Games +Group: Games + +%description games +Install fltk-games to play checkers or Sudoku on your computer. + +%prep +%setup + +%build +CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{prefix} --mandir=%{_mandir} --enable-shared --enable-xft --enable-xdbe --enable-xinerama + +# If we got this far, all prerequisite libraries must be here. +make + +%install +# these lines just make sure the directory structure in the +# RPM_BUILD_ROOT exists +rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT + +make -e DESTDIR=$RPM_BUILD_ROOT install install-desktop + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%dir %{prefix}/lib +%{prefix}/lib/libfltk*.so.* + +%files devel +%defattr(-,root,root) + +%dir %{prefix}/bin +%{prefix}/bin/fltk-config +%{prefix}/bin/fluid + +%dir %{prefix}/include/FL +%{prefix}/include/FL/* +%{prefix}/include/Fl + +%dir %{prefix}/lib +%{prefix}/lib/libfltk*.so +%{prefix}/lib/libfltk*.a + +%dir %{_mandir} +%{_mandir}/cat1/* +%{_mandir}/cat3/* +%{_mandir}/man1/* +%{_mandir}/man3/* + +%dir %{prefix}/share/doc/fltk +%{prefix}/share/doc/fltk/* + +%dir %{prefix}/share/applnk +%{prefix}/share/applnk/Development/* + +%dir %{prefix}/share/icons +%{prefix}/share/icons/hicolor/*/apps/fluid.png + +%dir %{prefix}/share/mimelnk +%{prefix}/share/mimelnk/* + +%files games +%dir %{prefix}/bin +%{prefix}/bin/checkers +%{prefix}/bin/sudoku + +%dir %{_mandir} +%{_mandir}/cat6/* +%{_mandir}/man6/* + +%dir %{prefix}/share/applnk +%{prefix}/share/applnk/Games/* + +%dir %{prefix}/share/icons +%{prefix}/share/icons/hicolor/*/apps/checkers.png +%{prefix}/share/icons/hicolor/*/apps/sudoku.png + +# +# End of "$Id: fltk.spec.in 4756 2006-01-15 18:36:16Z mike $". +# diff --git a/Utilities/FLTK/fltk.spec.in b/Utilities/FLTK/fltk.spec.in new file mode 100644 index 0000000000..97273d36b6 --- /dev/null +++ b/Utilities/FLTK/fltk.spec.in @@ -0,0 +1,143 @@ +# +# "$Id: fltk.spec.in 4756 2006-01-15 18:36:16Z mike $" +# +# RPM spec file for FLTK. +# +# Copyright 1998-2006 by Bill Spitzak and others. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. +# +# Please report all bugs and problems on the following page: +# +# http://www.fltk.org/str.php +# + +%define version @VERSION@ +%define release @RELEASE@ +%define prefix /usr + +Summary: Fast Light Tool Kit (FLTK) +Name: fltk +Version: %{version} +Release: %{release} +License: LGPL +Group: System Environment/Libraries +Source: ftp://ftp.fltk.org/pub/fltk/%{version}/fltk-%{version}-source.tar.gz +URL: http://www.fltk.org/ +Packager: FLTK Developer <fltk@fltk.org> +# use BuildRoot so as not to disturb the version already installed +BuildRoot: /var/tmp/fltk-%{PACKAGE_VERSION} + +%description +The Fast Light Tool Kit ("FLTK", pronounced "fulltick") is a +cross-platform C++ GUI toolkit for UNIX(r)/Linux(r) (X11), +Microsoft(r) Windows(r), and MacOS(r) X. FLTK provides modern +GUI functionality without the bloat and supports 3D graphics via +OpenGL(r) and its built-in GLUT emulation. + +%package devel +Summary: FLTK Development Environment +Group: Development/Libraries + +%description devel +Install fltk-devel if you need to develop FLTK applications. +You'll need to install the fltk package if you plan to run +dynamically linked applications. + +%package games +Summary: FLTK Games +Group: Games + +%description games +Install fltk-games to play checkers or Sudoku on your computer. + +%prep +%setup + +%build +CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{prefix} --mandir=%{_mandir} --enable-shared --enable-xft --enable-xdbe --enable-xinerama + +# If we got this far, all prerequisite libraries must be here. +make + +%install +# these lines just make sure the directory structure in the +# RPM_BUILD_ROOT exists +rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT + +make -e DESTDIR=$RPM_BUILD_ROOT install install-desktop + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%dir %{prefix}/lib +%{prefix}/lib/libfltk*.so.* + +%files devel +%defattr(-,root,root) + +%dir %{prefix}/bin +%{prefix}/bin/fltk-config +%{prefix}/bin/fluid + +%dir %{prefix}/include/FL +%{prefix}/include/FL/* +%{prefix}/include/Fl + +%dir %{prefix}/lib +%{prefix}/lib/libfltk*.so +%{prefix}/lib/libfltk*.a + +%dir %{_mandir} +%{_mandir}/cat1/* +%{_mandir}/cat3/* +%{_mandir}/man1/* +%{_mandir}/man3/* + +%dir %{prefix}/share/doc/fltk +%{prefix}/share/doc/fltk/* + +%dir %{prefix}/share/applnk +%{prefix}/share/applnk/Development/* + +%dir %{prefix}/share/icons +%{prefix}/share/icons/hicolor/*/apps/fluid.png + +%dir %{prefix}/share/mimelnk +%{prefix}/share/mimelnk/* + +%files games +%dir %{prefix}/bin +%{prefix}/bin/checkers +%{prefix}/bin/sudoku + +%dir %{_mandir} +%{_mandir}/cat6/* +%{_mandir}/man6/* + +%dir %{prefix}/share/applnk +%{prefix}/share/applnk/Games/* + +%dir %{prefix}/share/icons +%{prefix}/share/icons/hicolor/*/apps/checkers.png +%{prefix}/share/icons/hicolor/*/apps/sudoku.png + +# +# End of "$Id: fltk.spec.in 4756 2006-01-15 18:36:16Z mike $". +# diff --git a/Utilities/FLTK/fltk.xpm b/Utilities/FLTK/fltk.xpm new file mode 100644 index 0000000000..c0c232c167 --- /dev/null +++ b/Utilities/FLTK/fltk.xpm @@ -0,0 +1,225 @@ +/* XPM */ +static char * fltk_xpm[] = { +"229 70 152 2", +" c None", +". c #000066", +"+ c #68689A", +"@ c #9292AF", +"# c #232377", +"$ c #CCCCCC", +"% c #31317E", +"& c #7878A2", +"* c #5D5D95", +"= c #1F1F76", +"- c #31317F", +"; c #11116F", +"> c #B4B4C0", +", c #ADADBC", +"' c #4C4C8C", +") c #595993", +"! c #3A3A83", +"~ c #7373A0", +"{ c #51518E", +"] c #A1A1B6", +"^ c #49498B", +"/ c #8989AA", +"( c #020267", +"_ c #050568", +": c #444488", +"< c #71719F", +"[ c #1A1A73", +"} c #5E5E95", +"| c #9E9EB5", +"1 c #252578", +"2 c #A4A4B8", +"3 c #666699", +"4 c #2B2B7C", +"5 c #8383A7", +"6 c #10106E", +"7 c #6D6D9D", +"8 c #0B0B6B", +"9 c #CBCBCB", +"0 c #010166", +"a c #7979A2", +"b c #6E6E9D", +"c c #0A0A6B", +"d c #7676A1", +"e c #C9C9CA", +"f c #2A2A7B", +"g c #9696B1", +"h c #6A6A9B", +"i c #262679", +"j c #49498A", +"k c #C2C2C7", +"l c #47478A", +"m c #BCBCC4", +"n c #424287", +"o c #4A4A8B", +"p c #C5C5C9", +"q c #454588", +"r c #BBBBC3", +"s c #434388", +"t c #69699B", +"u c #535390", +"v c #5B5B93", +"w c #73739F", +"x c #CACACB", +"y c #8888AA", +"z c #050569", +"A c #7F7FA5", +"B c #7575A0", +"C c #8C8CAC", +"D c #8A8AAB", +"E c #13136F", +"F c #09096B", +"G c #C8C8CA", +"H c #040468", +"I c #7474A0", +"J c #8F8FAD", +"K c #12126F", +"L c #08086A", +"M c #70709E", +"N c #C7C7CA", +"O c #0D0D6C", +"P c #07076A", +"Q c #8B8BAC", +"R c #8787AA", +"S c #6F6F9D", +"T c #0F0F6E", +"U c #7575A1", +"V c #8787A9", +"W c #CBCBCC", +"X c #11116E", +"Y c #7777A2", +"Z c #8585A9", +"` c #8B8BAB", +" . c #8383A8", +".. c #030367", +"+. c #070769", +"@. c #8484A8", +"#. c #0F0F6D", +"$. c #0D0D6D", +"%. c #0C0C6C", +"&. c #8181A7", +"*. c #ABABBC", +"=. c #B5B5C0", +"-. c #1E1E75", +";. c #A3A3B7", +">. c #242478", +",. c #A8A8BA", +"'. c #141470", +"). c #A5A5B8", +"!. c #252579", +"~. c #A5A5B9", +"{. c #191973", +"]. c #B5B5C1", +"^. c #161671", +"/. c #B7B7C1", +"(. c #A3A3B8", +"_. c #212177", +":. c #B2B2BF", +"<. c #B0B0BE", +"[. c #232378", +"}. c #AEAEBD", +"|. c #B6B6C1", +"1. c #212176", +"2. c #C3C3C8", +"3. c #ABABBB", +"4. c #151570", +"5. c #414186", +"6. c #BBBBC4", +"7. c #B9B9C2", +"8. c #1D1D75", +"9. c #464689", +"0. c #BFBFC6", +"a. c #A7A7B9", +"b. c #28287A", +"c. c #010167", +"d. c #BDBDC5", +"e. c #B9B9C3", +"f. c #454589", +"g. c #BDBDC4", +"h. c #A9A9BB", +"i. c #414187", +"j. c #C0C0C6", +"k. c #27277A", +"l. c #3E3E85", +"m. c #A6A6B9", +"n. c #C3C3C7", +"o. c #151571", +"p. c #030368", +"q. c #0B0B6C", +"r. c #B1B1BF", +"s. c #404086", +"t. c #C7C7C9", +"u. c #0E0E6D", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ : < @ @ @ @ @ @ @ @ @ @ @ @ [ . . . . . . . . . . . . . . . . . . . . . t @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ u . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . . . c w x $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ y z . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . . 0 B $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ C z . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . . h $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ D E . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . F < G $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ y F . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . H I $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ J . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . 7 $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ y K . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . L M N $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 9 / O . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . P I $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ Q . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . M $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ R 6 . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . z S N $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 9 D T . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . F U $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ y . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ & * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * = $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ * * * * * * * * * * * * * * * * * * * * * * * * 2 $ $ $ $ $ $ $ $ $ $ $ $ $ 3 * * * * * * * * * * * * * * * * * * * * * * * 4 | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . ~ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ V O . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . ( 7 G $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ W C X . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . 8 Y $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ Z . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . d $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ R F . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . 7 x $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ` ; . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . 8 & 9 $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ .... . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . 0 a $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ / _ . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . b $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ y ; . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 c d e $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 5 +.. . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ f & $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ D . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ g $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ Z 6 . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 9 @.c . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ R . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ @.#.. . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ > , , , , , , , , , , , , , , , , , , , , , , , , , , , ' . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ x Z $.. . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ @.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ @.%.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 9 V #.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ &.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ @.L . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ *.$.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ =.-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ;.>.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ,.'.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ > [ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ).!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ~.{.. . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ > , , , , , , , , , , , , , , , , , , , , , , , , , , , ' . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ].^.. . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ,.!.. . . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ h $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 2 -.. . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ i j k $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ /.X . . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . l m $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ *.1 . . . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . n $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ (._.. . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . o p $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ :.; . . . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . q r $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ <.[.. . . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . s G $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 2 >.. . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . o x $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ }.K . . . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . n r $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ |.1.. . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . q 2.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ).i . . . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . l $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 3.4.. . . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . 0 5.6.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 7.8.. . . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ( . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . 9.0.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ a.b.. . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . : $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ,.[ . . . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . c.n d.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ e.{.. . . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . f.g.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ h.b.. . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . i.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ a.= . . . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . c.: j.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ r '.. . . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . : r $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ , k.. . . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . . l.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ m.[.. . . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . . . q n.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ |.o.. . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . . . . n e.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ r.i . . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . . . . . s.N $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ m.i . . ", +". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . . . . . . q t.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ r.T . ", +". . + @ @ @ @ @ @ @ @ @ @ @ @ [.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . %.@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ p.. . . . . . . . . . . . . . . . . . . . } @ @ @ @ @ @ @ @ @ @ @ @ @ q.. . . . . . . . . . . . . . . . . . . . . . . . < @ @ @ @ @ @ @ @ @ @ @ @ [ . . . . . . . . . . . . . . . . . . . . . . . s.@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ u.. ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "}; diff --git a/Utilities/FLTK/fluid/CMakeLists.txt b/Utilities/FLTK/fluid/CMakeLists.txt new file mode 100644 index 0000000000..347f258dc5 --- /dev/null +++ b/Utilities/FLTK/fluid/CMakeLists.txt @@ -0,0 +1,30 @@ +SET(CPPFILES + CodeEditor.cxx + Fl_Function_Type.cxx + Fl_Group_Type.cxx + Fl_Menu_Type.cxx + Fl_Type.cxx + Fl_Widget_Type.cxx + Fl_Window_Type.cxx + Fluid_Image.cxx + about_panel.cxx + align_widget.cxx + alignment_panel.cxx + code.cxx + factory.cxx + file.cxx + fluid.cxx + function_panel.cxx + template_panel.cxx + undo.cxx + widget_panel.cxx +) + + +ADD_EXECUTABLE(fluid ${CPPFILES}) +INSTALL_TARGETS(/bin fluid) +TARGET_LINK_LIBRARIES(fluid fltk fltk_images fltk_forms ${FLTK_PLATFORM_DEPENDENT_LIBS}) +IF(OPENGL_FOUND) + TARGET_LINK_LIBRARIES(fluid fltk_gl) +ENDIF(OPENGL_FOUND) + diff --git a/Utilities/FLTK/fluid/CodeEditor.cxx b/Utilities/FLTK/fluid/CodeEditor.cxx new file mode 100644 index 0000000000..af1e0c8acb --- /dev/null +++ b/Utilities/FLTK/fluid/CodeEditor.cxx @@ -0,0 +1,411 @@ +// +// "$Id$" +// +// Code editor widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// +// Include necessary headers... +// + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "CodeEditor.h" + + +Fl_Text_Display::Style_Table_Entry CodeEditor:: + styletable[] = { // Style table + { FL_FOREGROUND_COLOR, FL_COURIER, 11 }, // A - Plain + { FL_DARK_GREEN, FL_COURIER_ITALIC, 11 }, // B - Line comments + { FL_DARK_GREEN, FL_COURIER_ITALIC, 11 }, // C - Block comments + { FL_BLUE, FL_COURIER, 11 }, // D - Strings + { FL_DARK_RED, FL_COURIER, 11 }, // E - Directives + { FL_DARK_RED, FL_COURIER_BOLD, 11 }, // F - Types + { FL_BLUE, FL_COURIER_BOLD, 11 } // G - Keywords + }; +const char * const CodeEditor:: + code_keywords[] = { // Sorted list of C/C++ keywords... + "and", + "and_eq", + "asm", + "bitand", + "bitor", + "break", + "case", + "catch", + "compl", + "continue", + "default", + "delete", + "do", + "else", + "false", + "for", + "goto", + "if", + "new", + "not", + "not_eq", + "operator", + "or", + "or_eq", + "return", + "switch", + "template", + "this", + "throw", + "true", + "try", + "while", + "xor", + "xor_eq" + }; +const char * const CodeEditor:: + code_types[] = { // Sorted list of C/C++ types... + "auto", + "bool", + "char", + "class", + "const", + "const_cast", + "double", + "dynamic_cast", + "enum", + "explicit", + "extern", + "float", + "friend", + "inline", + "int", + "long", + "mutable", + "namespace", + "private", + "protected", + "public", + "register", + "short", + "signed", + "sizeof", + "static", + "static_cast", + "struct", + "template", + "typedef", + "typename", + "union", + "unsigned", + "virtual", + "void", + "volatile" + }; + + +// 'compare_keywords()' - Compare two keywords... +int CodeEditor::compare_keywords(const void *a, const void *b) { + return (strcmp(*((const char **)a), *((const char **)b))); +} + +// 'style_parse()' - Parse text and produce style data. +void CodeEditor::style_parse(const char *text, char *style, int length) { + char current; + int col; + int last; + char buf[255], + *bufptr; + const char *temp; + + // Style letters: + // + // A - Plain + // B - Line comments + // C - Block comments + // D - Strings + // E - Directives + // F - Types + // G - Keywords + + for (current = *style, col = 0, last = 0; length > 0; length --, text ++) { + if (current == 'B' || current == 'F' || current == 'G') current = 'A'; + if (current == 'A') { + // Check for directives, comments, strings, and keywords... + if (col == 0 && *text == '#') { + // Set style to directive + current = 'E'; + } else if (strncmp(text, "//", 2) == 0) { + current = 'B'; + for (; length > 0 && *text != '\n'; length --, text ++) *style++ = 'B'; + + if (length == 0) break; + } else if (strncmp(text, "/*", 2) == 0) { + current = 'C'; + } else if (strncmp(text, "\\\"", 2) == 0) { + // Quoted quote... + *style++ = current; + *style++ = current; + text ++; + length --; + col += 2; + continue; + } else if (*text == '\"') { + current = 'D'; + } else if (!last && (islower(*text) || *text == '_')) { + // Might be a keyword... + for (temp = text, bufptr = buf; + (islower(*temp) || *temp == '_') && bufptr < (buf + sizeof(buf) - 1); + *bufptr++ = *temp++); + + if (!islower(*temp) && *temp != '_') { + *bufptr = '\0'; + + bufptr = buf; + + if (bsearch(&bufptr, code_types, + sizeof(code_types) / sizeof(code_types[0]), + sizeof(code_types[0]), compare_keywords)) { + while (text < temp) { + *style++ = 'F'; + text ++; + length --; + col ++; + } + + text --; + length ++; + last = 1; + continue; + } else if (bsearch(&bufptr, code_keywords, + sizeof(code_keywords) / sizeof(code_keywords[0]), + sizeof(code_keywords[0]), compare_keywords)) { + while (text < temp) { + *style++ = 'G'; + text ++; + length --; + col ++; + } + + text --; + length ++; + last = 1; + continue; + } + } + } + } else if (current == 'C' && strncmp(text, "*/", 2) == 0) { + // Close a C comment... + *style++ = current; + *style++ = current; + text ++; + length --; + current = 'A'; + col += 2; + continue; + } else if (current == 'D') { + // Continuing in string... + if (strncmp(text, "\\\"", 2) == 0) { + // Quoted end quote... + *style++ = current; + *style++ = current; + text ++; + length --; + col += 2; + continue; + } else if (*text == '\"') { + // End quote... + *style++ = current; + col ++; + current = 'A'; + continue; + } + } + + // Copy style info... + if (current == 'A' && (*text == '{' || *text == '}')) *style++ = 'G'; + else *style++ = current; + col ++; + + last = isalnum(*text) || *text == '_' || *text == '.'; + + if (*text == '\n') { + // Reset column and possibly reset the style + col = 0; + if (current == 'B' || current == 'E') current = 'A'; + } + } +} + +// 'style_unfinished_cb()' - Update unfinished styles. +void CodeEditor::style_unfinished_cb(int, void*) { } + +// 'style_update()' - Update the style buffer... +void CodeEditor::style_update(int pos, int nInserted, int nDeleted, + int /*nRestyled*/, const char * /*deletedText*/, + void *cbArg) { + CodeEditor *editor = (CodeEditor *)cbArg; + int start, // Start of text + end; // End of text + char last, // Last style on line + *style, // Style data + *text; // Text data + + + // If this is just a selection change, just unselect the style buffer... + if (nInserted == 0 && nDeleted == 0) { + editor->mStyleBuffer->unselect(); + return; + } + + // Track changes in the text buffer... + if (nInserted > 0) { + // Insert characters into the style buffer... + style = new char[nInserted + 1]; + memset(style, 'A', nInserted); + style[nInserted] = '\0'; + + editor->mStyleBuffer->replace(pos, pos + nDeleted, style); + delete[] style; + } else { + // Just delete characters in the style buffer... + editor->mStyleBuffer->remove(pos, pos + nDeleted); + } + + // Select the area that was just updated to avoid unnecessary + // callbacks... + editor->mStyleBuffer->select(pos, pos + nInserted - nDeleted); + + // Re-parse the changed region; we do this by parsing from the + // beginning of the line of the changed region to the end of + // the line of the changed region... Then we check the last + // style character and keep updating if we have a multi-line + // comment character... + start = editor->mBuffer->line_start(pos); + end = editor->mBuffer->line_end(pos + nInserted); + text = editor->mBuffer->text_range(start, end); + style = editor->mStyleBuffer->text_range(start, end); + if (start==end) + last = 0; + else + last = style[end - start - 1]; + + style_parse(text, style, end - start); + + editor->mStyleBuffer->replace(start, end, style); + editor->redisplay_range(start, end); + + if (start==end || last != style[end - start - 1]) { + // The last character on the line changed styles, so reparse the + // remainder of the buffer... + free(text); + free(style); + + end = editor->mBuffer->length(); + text = editor->mBuffer->text_range(start, end); + style = editor->mStyleBuffer->text_range(start, end); + + style_parse(text, style, end - start); + + editor->mStyleBuffer->replace(start, end, style); + editor->redisplay_range(start, end); + } + + free(text); + free(style); +} + +int CodeEditor::auto_indent(int, CodeEditor* e) { + if (e->buffer()->selected()) { + e->insert_position(e->buffer()->primary_selection()->start()); + e->buffer()->remove_selection(); + } + + int pos = e->insert_position(); + int start = e->line_start(pos); + char *text = e->buffer()->text_range(start, pos); + char *ptr; + + for (ptr = text; isspace(*ptr); ptr ++); + *ptr = '\0'; + if (*text) { + // use only a single 'insert' call to avoid redraw issues + int n = strlen(text); + char *b = (char*)malloc(n+2); + *b = '\n'; + strcpy(b+1, text); + e->insert(b); + free(b); + } else { + e->insert("\n"); + } + e->show_insert_position(); + e->set_changed(); + if (e->when()&FL_WHEN_CHANGED) e->do_callback(); + + free(text); + + return 1; +} + +// Create a CodeEditor widget... +CodeEditor::CodeEditor(int X, int Y, int W, int H, const char *L) : + Fl_Text_Editor(X, Y, W, H, L) { + buffer(new Fl_Text_Buffer); + + char *style = new char[mBuffer->length() + 1]; + char *text = mBuffer->text(); + + memset(style, 'A', mBuffer->length()); + style[mBuffer->length()] = '\0'; + + highlight_data(new Fl_Text_Buffer(mBuffer->length()), styletable, + sizeof(styletable) / sizeof(styletable[0]), + 'A', style_unfinished_cb, this); + + style_parse(text, style, mBuffer->length()); + + mStyleBuffer->text(style); + delete[] style; + free(text); + + mBuffer->add_modify_callback(style_update, this); + add_key_binding(FL_Enter, FL_TEXT_EDITOR_ANY_STATE, + (Fl_Text_Editor::Key_Func)auto_indent); +} + +// Destroy a CodeEditor widget... +CodeEditor::~CodeEditor() { + Fl_Text_Buffer *buf = mStyleBuffer; + mStyleBuffer = 0; + delete buf; + + buf = mBuffer; + buffer(0); + delete buf; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/CodeEditor.h b/Utilities/FLTK/fluid/CodeEditor.h new file mode 100644 index 0000000000..04c51bd095 --- /dev/null +++ b/Utilities/FLTK/fluid/CodeEditor.h @@ -0,0 +1,77 @@ +// +// "$Id$" +// +// Code editor widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef CodeEditor_h +# define CodeEditor_h + +// +// Include necessary headers... +// + +# include <stdio.h> +# include <stdlib.h> +# include <string.h> +# include <ctype.h> +# include <FL/Fl.H> +# include <FL/Fl_Text_Buffer.H> +# include <FL/Fl_Text_Editor.H> + + +class CodeEditor : public Fl_Text_Editor { + static Fl_Text_Display::Style_Table_Entry styletable[]; + static const char * const code_keywords[]; + static const char * const code_types[]; + + + // 'compare_keywords()' - Compare two keywords... + static int compare_keywords(const void *a, const void *b); + + // 'style_parse()' - Parse text and produce style data. + static void style_parse(const char *text, char *style, int length); + + // 'style_unfinished_cb()' - Update unfinished styles. + static void style_unfinished_cb(int, void*); + + // 'style_update()' - Update the style buffer... + static void style_update(int pos, int nInserted, int nDeleted, + int /*nRestyled*/, const char * /*deletedText*/, + void *cbArg); + + static int auto_indent(int, CodeEditor* e); + + public: + + CodeEditor(int X, int Y, int W, int H, const char *L=0); + ~CodeEditor(); + int top_line() { return get_absolute_top_line_number(); } +}; + +#endif // !CodeEditor_h + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/Fl_Function_Type.cxx b/Utilities/FLTK/fluid/Fl_Function_Type.cxx new file mode 100644 index 0000000000..77391abc1c --- /dev/null +++ b/Utilities/FLTK/fluid/Fl_Function_Type.cxx @@ -0,0 +1,1091 @@ +// +// "$Id$" +// +// C function type code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Preferences.H> +#include <FL/Fl_File_Chooser.H> +#include "Fl_Type.h" +#include <FL/fl_show_input.H> +#include "../src/flstring.h" +#include <stdio.h> +#include <stdlib.h> + +extern int i18n_type; +extern const char* i18n_include; +extern const char* i18n_function; +extern const char* i18n_file; +extern const char* i18n_set; +extern char i18n_program[]; + +//////////////////////////////////////////////////////////////// +// quick check of any C code for legality, returns an error message + +static char buffer[128]; // for error messages + +// check a quoted string ending in either " or ' or >: +const char *_q_check(const char * & c, int type) { + for (;;) switch (*c++) { + case '\0': + sprintf(buffer,"missing %c",type); + return buffer; + case '\\': + if (*c) c++; + break; + default: + if (*(c-1) == type) return 0; + } +} + +// check normal code, match braces and parenthesis: +const char *_c_check(const char * & c, int type) { + const char *d; + for (;;) switch (*c++) { + case 0: + if (!type) return 0; + sprintf(buffer, "missing %c", type); + return buffer; + case '/': + // Skip comments as needed... + if (*c == '/') { + while (*c != '\n' && *c) c++; + } else if (*c == '*') { + c++; + while ((*c != '*' || c[1] != '/') && *c) c++; + if (*c == '*') c+=2; + else { + return "missing '*/'"; + } + } + break; + case '#': + // treat cpp directives as a comment: + while (*c != '\n' && *c) c++; + break; + case '{': + if (type==')') goto UNEXPECTED; + d = _c_check(c,'}'); + if (d) return d; + break; + case '(': + d = _c_check(c,')'); + if (d) return d; + break; + case '\"': + d = _q_check(c,'\"'); + if (d) return d; + break; + case '\'': + d = _q_check(c,'\''); + if (d) return d; + break; + case '}': + case ')': + UNEXPECTED: + if (type == *(c-1)) return 0; + sprintf(buffer, "unexpected %c", *(c-1)); + return buffer; + } +} + +const char *c_check(const char *c, int type) { + return _c_check(c,type); +} + +//////////////////////////////////////////////////////////////// + +int Fl_Function_Type::is_public() const {return public_;} + +Fl_Type *Fl_Function_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_decl_block()) p = p->parent; + Fl_Function_Type *o = new Fl_Function_Type(); + o->name("make_window()"); + o->return_type = 0; + o->add(p); + o->factory = this; + o->public_ = 1; + o->cdecl_ = 0; + return o; +} + +void Fl_Function_Type::write_properties() { + Fl_Type::write_properties(); + if (!public_) write_string("private"); + if (cdecl_) write_string("C"); + if (return_type) { + write_string("return_type"); + write_word(return_type); + } +} + +void Fl_Function_Type::read_property(const char *c) { + if (!strcmp(c,"private")) { + public_ = 0; + } else if (!strcmp(c,"C")) { + cdecl_ = 1; + } else if (!strcmp(c,"return_type")) { + storestring(read_word(),return_type); + } else { + Fl_Type::read_property(c); + } +} + +#include "function_panel.h" +#include <FL/fl_ask.H> + +void Fl_Function_Type::open() { + if (!function_panel) make_function_panel(); + f_return_type_input->static_value(return_type); + f_name_input->static_value(name()); + f_public_button->value(public_); + f_c_button->value(cdecl_); + function_panel->show(); + const char* message = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == f_panel_cancel) goto BREAK2; + else if (w == f_panel_ok) break; + else if (!w) Fl::wait(); + } + const char*c = f_name_input->value(); + while (isspace(*c)) c++; + message = c_check(c); if (message) continue; + const char *d = c; + for (; *d != '('; d++) if (isspace(*d) || !*d) break; + if (*c && *d != '(') { + message = "must be name(arguments), try again:"; continue; + } + int mod = 0; + c = f_return_type_input->value(); + message = c_check(c); if (message) continue; + name(f_name_input->value()); + storestring(c, return_type); + if (public_ != f_public_button->value()) { + mod = 1; + public_ = f_public_button->value(); + } + if (cdecl_ != f_c_button->value()) { + mod = 1; + cdecl_ = f_c_button->value(); + } + if (mod) set_modflag(1); + break; + } + BREAK2: + function_panel->hide(); +} + +Fl_Function_Type Fl_Function_type; + +extern const char* subclassname(Fl_Type*); + +void Fl_Function_Type::write_code1() { + constructor=0; + havewidgets = 0; + Fl_Type *child; + for (child = next; child && child->level > level; child = child->next) + if (child->is_widget()) { + havewidgets = 1; + break; + } + write_c("\n"); + if (ismain()) + write_c("int main(int argc, char **argv) {\n"); + else { + const char* rtype = return_type; + const char* star = ""; + // from matt: let the user type "static " at the start of type + // in order to declare a static method; + int is_static = 0; + int is_virtual = 0; + if (rtype) { + if (!strcmp(rtype,"static")) {is_static = 1; rtype = 0;} + else if (!strncmp(rtype, "static ",7)) {is_static = 1; rtype += 7;} + if (!strcmp(rtype, "virtual")) {is_virtual = 1; rtype = 0;} + else if (!strncmp(rtype, "virtual ",8)) {is_virtual = 1; rtype += 8;} + } + if (!rtype) { + if (havewidgets) { + rtype = subclassname(child); + star = "*"; + } else rtype = "void"; + } + + const char* k = class_name(0); + if (k) { + write_public(public_); + if (name()[0] == '~') + constructor = 1; + else { + size_t n = strlen(k); + if (!strncmp(name(), k, n) && name()[n] == '(') constructor = 1; + } + write_h(" "); + if (is_static) write_h("static "); + if (is_virtual) write_h("virtual "); + if (!constructor) { + write_h("%s%s ", rtype, star); + write_c("%s%s ", rtype, star); + } + + // if this is a subclass, only write_h() the part before the ':' + char s[1024], *sptr = s; + char *nptr = (char *)name(); + + while (*nptr) { + if (*nptr == ':') { + if (nptr[1] != ':') break; + // Copy extra ":" for "class::member"... + *sptr++ = *nptr++; + } + *sptr++ = *nptr++; + } + *sptr = '\0'; + + write_h("%s;\n", s); + // skip all function default param. init in body: + int skips=0,skipc=0; + int nc=0,plevel=0; + for (sptr=s,nptr=(char*)name(); *nptr; nc++,nptr++) { + if (!skips && *nptr=='(') plevel++; + else if (!skips && *nptr==')') plevel--; + if ( *nptr=='"' && !(nc && *(nptr-1)=='\\') ) + skips = skips ? 0 : 1; + else if(!skips && *nptr=='\'' && !(nc && *(nptr-1)=='\\')) + skipc = skipc ? 0 : 1; + if(!skips && !skipc && plevel==1 && *nptr =='=' && + !(nc && *(nptr-1)=='\'') ) // ignore '=' case + while(*++nptr && (skips || skipc || (*nptr!=',' && *nptr!=')' || plevel!=1) )) { + if ( *nptr=='"' && *(nptr-1)!='\\' ) + skips = skips ? 0 : 1; + else if(!skips && *nptr=='\'' && *(nptr-1)!='\\') + skipc = skipc ? 0 : 1; + if (!skips && !skipc && *nptr=='(') plevel++; + else if (!skips && *nptr==')') plevel--; + } + + if (sptr < (s + sizeof(s) - 1)) *sptr++ = *nptr; + } + *sptr = '\0'; + + write_c("%s::%s {\n", k, s); + } else { + if (public_) { + if (cdecl_) + write_h("extern \"C\" { %s%s %s; }\n", rtype, star, name()); + else + write_h("%s%s %s;\n", rtype, star, name()); + } + else write_c("static "); + + // write everything but the default parameters (if any) + char s[1024], *sptr; + char *nptr; + int skips=0,skipc=0; + int nc=0,plevel=0; + for (sptr=s,nptr=(char*)name(); *nptr; nc++,nptr++) { + if (!skips && *nptr=='(') plevel++; + else if (!skips && *nptr==')') plevel--; + if ( *nptr=='"' && !(nc && *(nptr-1)=='\\') ) + skips = skips ? 0 : 1; + else if(!skips && *nptr=='\'' && !(nc && *(nptr-1)=='\\')) + skipc = skipc ? 0 : 1; + if(!skips && !skipc && plevel==1 && *nptr =='=' && + !(nc && *(nptr-1)=='\'') ) // ignore '=' case + while(*++nptr && (skips || skipc || (*nptr!=',' && *nptr!=')' || plevel!=1) )) { + if ( *nptr=='"' && *(nptr-1)!='\\' ) + skips = skips ? 0 : 1; + else if(!skips && *nptr=='\'' && *(nptr-1)!='\\') + skipc = skipc ? 0 : 1; + if (!skips && !skipc && *nptr=='(') plevel++; + else if (!skips && *nptr==')') plevel--; + } + + if (sptr < (s + sizeof(s) - 1)) *sptr++ = *nptr; + } + *sptr = '\0'; + + write_c("%s%s %s {\n", rtype, star, s); + } + } + if (havewidgets) write_c(" %s* w;\n",subclassname(child)); + indentation += 2; +} + +void Fl_Function_Type::write_code2() { + if (ismain()) { + if (havewidgets) write_c(" w->show(argc, argv);\n"); + write_c(" return Fl::run();\n"); + } else if (havewidgets && !constructor && !return_type) + write_c(" return w;\n"); + write_c("}\n"); + indentation = 0; +} + +int Fl_Function_Type::has_signature(const char *rtype, const char *sig) const { + if (!return_type) return 0; + if (!name()) return 0; + if ( strcmp(return_type, rtype)==0 + && fl_filename_match(name(), sig)) { + return 1; + } + return 0; +} + +//////////////////////////////////////////////////////////////// + +Fl_Type *Fl_Code_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_code_block()) p = p->parent; + if (!p) { + fl_message("Please select a function"); + return 0; + } + Fl_Code_Type *o = new Fl_Code_Type(); + o->name("printf(\"Hello, World!\\n\");"); + o->add(p); + o->factory = this; + return o; +} + +void Fl_Code_Type::open() { + if (!code_panel) make_code_panel(); + const char *text = name(); + code_input->buffer()->text( text ? text : "" ); + code_panel->show(); + const char* message = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == code_panel_cancel) goto BREAK2; + else if (w == code_panel_ok) break; + else if (!w) Fl::wait(); + } + char*c = code_input->buffer()->text(); + message = c_check(c); if (message) continue; + name(c); + free(c); + break; + } + BREAK2: + code_panel->hide(); +} + +Fl_Code_Type Fl_Code_type; + +void Fl_Code_Type::write_code1() { + const char* c = name(); + if (!c) return; + write_c("%s%s\n", indent(), c); +} + +void Fl_Code_Type::write_code2() {} + +//////////////////////////////////////////////////////////////// + +Fl_Type *Fl_CodeBlock_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_code_block()) p = p->parent; + if (!p) { + fl_message("Please select a function"); + return 0; + } + Fl_CodeBlock_Type *o = new Fl_CodeBlock_Type(); + o->name("if (test())"); + o->after = 0; + o->add(p); + o->factory = this; + return o; +} + +void Fl_CodeBlock_Type::write_properties() { + Fl_Type::write_properties(); + if (after) { + write_string("after"); + write_word(after); + } +} + +void Fl_CodeBlock_Type::read_property(const char *c) { + if (!strcmp(c,"after")) { + storestring(read_word(),after); + } else { + Fl_Type::read_property(c); + } +} + +void Fl_CodeBlock_Type::open() { + if (!codeblock_panel) make_codeblock_panel(); + code_before_input->static_value(name()); + code_after_input->static_value(after); + codeblock_panel->show(); + const char* message = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == codeblock_panel_cancel) goto BREAK2; + else if (w == codeblock_panel_ok) break; + else if (!w) Fl::wait(); + } + const char*c = code_before_input->value(); + message = c_check(c); if (message) continue; + name(c); + c = code_after_input->value(); + message = c_check(c); if (message) continue; + storestring(c, after); + break; + } + BREAK2: + codeblock_panel->hide(); +} + +Fl_CodeBlock_Type Fl_CodeBlock_type; + +void Fl_CodeBlock_Type::write_code1() { + const char* c = name(); + write_c("%s%s {\n", indent(), c ? c : ""); + indentation += 2; +} + +void Fl_CodeBlock_Type::write_code2() { + indentation += 2; + if (after) write_c("%s} %s\n", indent(), after); + else write_c("%s}\n", indent()); +} + +//////////////////////////////////////////////////////////////// + +int Fl_Decl_Type::is_public() const +{ + Fl_Type *p = parent; + while (p && !p->is_decl_block()) p = p->parent; + if(p && p->is_public() && public_) + return public_; + else if(!p) + return public_; + return 0; +} + +Fl_Type *Fl_Decl_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_decl_block()) p = p->parent; + Fl_Decl_Type *o = new Fl_Decl_Type(); + o->public_ = 0; + o->name("int x;"); + o->add(p); + o->factory = this; + return o; +} + +void Fl_Decl_Type::write_properties() { + Fl_Type::write_properties(); + if (public_) write_string("public"); +} + +void Fl_Decl_Type::read_property(const char *c) { + if (!strcmp(c,"public")) { + public_ = 1; + } else { + Fl_Type::read_property(c); + } +} + +void Fl_Decl_Type::open() { + if (!decl_panel) make_decl_panel(); + decl_input->static_value(name()); + decl_public_button->value(public_); + decl_panel->show(); + const char* message = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == decl_panel_cancel) goto BREAK2; + else if (w == decl_panel_ok) break; + else if (!w) Fl::wait(); + } + const char*c = decl_input->value(); + while (isspace(*c)) c++; + message = c_check(c&&c[0]=='#' ? c+1 : c); + if (message) continue; + name(c); + if (public_!=decl_public_button->value()) { + set_modflag(1); + public_ = decl_public_button->value(); + } + break; + } + BREAK2: + decl_panel->hide(); +} + +Fl_Decl_Type Fl_Decl_type; + +void Fl_Decl_Type::write_code1() { + const char* c = name(); + if (!c) return; + // handle putting #include, extern, using or typedef into decl: + if (!isalpha(*c) && *c != '~' + || !strncmp(c,"extern",6) && isspace(c[6]) + || !strncmp(c,"class",5) && isspace(c[5]) + || !strncmp(c,"typedef",7) && isspace(c[7]) + || !strncmp(c,"using",5) && isspace(c[5]) + || !strncmp(c,"FL_EXPORT",9) && isspace(c[9]) +// || !strncmp(c,"struct",6) && isspace(c[6]) + ) { + if (public_) + write_h("%s\n", c); + else + write_c("%s\n", c); + return; + } + // lose all trailing semicolons so I can add one: + const char* e = c+strlen(c); + while (e>c && e[-1]==';') e--; + if (class_name(1)) { + write_public(public_); + write_h(" %.*s;\n", (int)(e-c), c); + } else { + if (public_) { + write_h("extern %.*s;\n", (int)(e-c), c); + write_c("%.*s;\n", (int)(e-c), c); + } else { + write_c("static %.*s;\n", (int)(e-c), c); + } + } +} + +void Fl_Decl_Type::write_code2() {} + +//////////////////////////////////////////////////////////////// + +int Fl_DeclBlock_Type::is_public() const {return public_;} + +Fl_Type *Fl_DeclBlock_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_decl_block()) p = p->parent; + Fl_DeclBlock_Type *o = new Fl_DeclBlock_Type(); + o->name("#if 1"); + o->public_ = 0; + o->after = strdup("#endif"); + o->add(p); + o->factory = this; + return o; +} + +void Fl_DeclBlock_Type::write_properties() { + Fl_Type::write_properties(); + if (public_) write_string("public"); + write_string("after"); + write_word(after); +} + +void Fl_DeclBlock_Type::read_property(const char *c) { + if(!strcmp(c,"public")) { + public_ = 1; + } else if (!strcmp(c,"after")) { + storestring(read_word(),after); + } else { + Fl_Type::read_property(c); + } +} + +void Fl_DeclBlock_Type::open() { + if (!declblock_panel) make_declblock_panel(); + decl_before_input->static_value(name()); + declblock_public_button->value(public_); + decl_after_input->static_value(after); + declblock_panel->show(); + const char* message = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == declblock_panel_cancel) goto BREAK2; + else if (w == declblock_panel_ok) break; + else if (!w) Fl::wait(); + } + const char*c = decl_before_input->value(); + while (isspace(*c)) c++; + message = c_check(c&&c[0]=='#' ? c+1 : c); + if (message) continue; + name(c); + c = decl_after_input->value(); + while (isspace(*c)) c++; + message = c_check(c&&c[0]=='#' ? c+1 : c); + if (message) continue; + storestring(c,after); + if (public_ != declblock_public_button->value()) { + set_modflag(1); + public_ = declblock_public_button->value(); + } + break; + } + BREAK2: + declblock_panel->hide(); +} + +Fl_DeclBlock_Type Fl_DeclBlock_type; + +void Fl_DeclBlock_Type::write_code1() { + const char* c = name(); + if (public_) + write_h("%s\n", c); + write_c("%s\n", c); +} + +void Fl_DeclBlock_Type::write_code2() { + const char* c = after; + if (public_) + write_h("%s\n", c); + write_c("%s\n", c); +} + +//////////////////////////////////////////////////////////////// + +Fl_Type *Fl_Comment_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_code_block()) p = p->parent; + Fl_Comment_Type *o = new Fl_Comment_Type(); + o->in_c_ = 1; + o->in_h_ = 1; + o->style_ = 0; + o->name("my comment"); + o->add(p); + o->factory = this; + o->title_buf[0] = 0; + return o; +} + +void Fl_Comment_Type::write_properties() { + Fl_Type::write_properties(); + if (in_c_) write_string("in_source"); else write_string("not_in_source"); + if (in_h_) write_string("in_header"); else write_string("not_in_header"); +} + +void Fl_Comment_Type::read_property(const char *c) { + if (!strcmp(c,"in_source")) { + in_c_ = 1; + } else if (!strcmp(c,"not_in_source")) { + in_c_ = 0; + } else if (!strcmp(c,"in_header")) { + in_h_ = 1; + } else if (!strcmp(c,"not_in_header")) { + in_h_ = 0; + } else { + Fl_Type::read_property(c); + } +} + +#include "comments.h" + +static void load_comments_preset(Fl_Preferences &menu) { + static const char * const predefined_comment[] = { + "GNU Public License/GPL Header", "GNU Public License/GPL Footer", + "GNU Public License/LGPL Header", "GNU Public License/LGPL Footer", + "FLTK/Header", "FLTK/Footer" }; + int i; + menu.set("n", 6); + Fl_Preferences db(Fl_Preferences::USER, "fltk.org", "fluid_comments"); + for (i=0; i<6; i++) { + menu.set(Fl_Preferences::Name(i), predefined_comment[i]); + db.set(predefined_comment[i], comment_text[i]); + } +} + +void Fl_Comment_Type::open() { + if (!comment_panel) make_comment_panel(); + const char *text = name(); + { + int i=0, n=0; + Fl_Preferences menu(Fl_Preferences::USER, "fltk.org", "fluid_comments_menu"); + comment_predefined->clear(); + comment_predefined->add("_Edit/Add current comment..."); + comment_predefined->add("_Edit/Remove last selection..."); + menu.get("n", n, -1); + if (n==-1) load_comments_preset(menu); + menu.get("n", n, 0); + for (i=0;i<n;i++) { + char *text; + menu.get(Fl_Preferences::Name(i), text, ""); + comment_predefined->add(text); + free(text); + } + } + comment_input->buffer()->text( text ? text : "" ); + comment_in_source->value(in_c_); + comment_in_header->value(in_h_); + comment_panel->show(); + const char* message = 0; + char itempath[256]; itempath[0] = 0; + int last_selected_item = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == comment_panel_cancel) goto BREAK2; + else if (w == comment_panel_ok) break; + else if (w == comment_predefined) { + if (comment_predefined->value()==1) { + // add the current comment to the database + const char *xname = fl_input( + "Please enter a name to reference the current\ncomment in your database.\n\n" + "Use forward slashes '/' to create submenus.", + "My Comment"); + if (xname) { + char *name = strdup(xname); + for (char*s=name;*s;s++) if (*s==':') *s = ';'; + int n; + Fl_Preferences db(Fl_Preferences::USER, "fltk.org", "fluid_comments"); + db.set(name, comment_input->buffer()->text()); + Fl_Preferences menu(Fl_Preferences::USER, "fltk.org", "fluid_comments_menu"); + menu.get("n", n, 0); + menu.set(Fl_Preferences::Name(n), name); + menu.set("n", ++n); + comment_predefined->add(name); + free(name); + } + } else if (comment_predefined->value()==2) { + // remove the last selected comment from the database + if (itempath[0]==0 || last_selected_item==0) { + fl_message("Please select an entry form this menu first."); + } else if (fl_choice("Are you sure that you want to delete the entry\n" + "\"%s\"\nfrom the database?", "Cancel", "Delete", + NULL, itempath)) { + Fl_Preferences db(Fl_Preferences::USER, "fltk.org", "fluid_comments"); + db.deleteEntry(itempath); + comment_predefined->remove(last_selected_item); + Fl_Preferences menu(Fl_Preferences::USER, "fltk.org", "fluid_comments_menu"); + int i, n; + for (i=4, n=0; i<comment_predefined->size(); i++) { + const Fl_Menu_Item *mi = comment_predefined->menu()+i; + if (comment_predefined->item_pathname(itempath, 255, mi)==0) { + if (itempath[0]=='/') memmove(itempath, itempath+1, 255); + if (itempath[0]) menu.set(Fl_Preferences::Name(n++), itempath); + } + } + menu.set("n", n); + } + } else { + // load the selected comment from the database + if (comment_predefined->item_pathname(itempath, 255)==0) { + if (itempath[0]=='/') memmove(itempath, itempath+1, 255); + Fl_Preferences db(Fl_Preferences::USER, "fltk.org", "fluid_comments"); + char *text; + db.get(itempath, text, "(no text found in data base)"); + comment_input->buffer()->text(text); + free(text); + last_selected_item = comment_predefined->value(); + } + } + } + else if (w == comment_load) { + // load a comment from disk + fl_file_chooser_ok_label("Use File"); + const char *fname = fl_file_chooser("Pick a comment", 0L, 0L); + fl_file_chooser_ok_label(NULL); + if (fname) { + if (comment_input->buffer()->loadfile(fname)) { + fl_alert("Error loading file\n%s", fname); + } + } + } + else if (!w) Fl::wait(); + } + char*c = comment_input->buffer()->text(); + name(c); + free(c); + int mod = 0; + if (in_c_ != comment_in_source->value()) { + in_c_ = comment_in_source->value(); + mod = 1; + } + if (in_h_ != comment_in_header->value()) { + in_h_ = comment_in_header->value(); + mod = 1; + } + if (mod) set_modflag(1); + break; + } + BREAK2: + title_buf[0] = 0; + comment_panel->hide(); +} + +const char *Fl_Comment_Type::title() { + const char* n = name(); + if (!n || !*n) return type_name(); + if (title_buf[0]==0) { + const char *s = n; + char *d = title_buf; + int i = 50; + while (--i > 0) { + char n = *s++; + if (n==0) break; + if (n=='\r') { *d++ = '\\'; *d++ = 'r'; i--; } + else if (n=='\n') { *d++ = '\\'; *d++ = 'n'; i--; } + else if (n<32) { *d++ = '^'; *d++ = 'A'+n; i--; } + else *d++ = n; + } + if (i<=0) { *d++ = '.'; *d++ = '.'; *d++ = '.'; } + *d++ = 0; + } + return title_buf; +} + +Fl_Comment_Type Fl_Comment_type; + +void Fl_Comment_Type::write_code1() { + const char* c = name(); + if (!c) return; + if (!in_c_ && !in_h_) return; + // find out if there is already a valid comment: + const char *s = c; + while (isspace(*s)) s++; + // if this seems to be a C style comment, copy the block as is + // (it's up to the user to correctly close the comment) + if (s[0]=='/' && s[1]=='*') { + if (in_h_) write_h("%s\n", c); + if (in_c_) write_c("%s\n", c); + return; + } + // copy the comment line by line, add the double slash if needed + char *txt = strdup(c); + char *b = txt, *e = txt; + for (;;) { + // find the end of the line and set it to NUL + while (*e && *e!='\n') e++; + char eol = *e; + *e = 0; + // check if there is a C++ style comment at the beginning of the line + char *s = b; + while (isspace(*s)) s++; + if (s!=e && ( s[0]!='/' || s[1]!='/') ) { + // if no comment marker was found, we add one ourselves + if (in_h_) write_h("// "); + if (in_c_) write_c("// "); + } + // now copy the rest of the line + if (in_h_) write_h("%s\n", b); + if (in_c_) write_c("%s\n", b); + if (eol==0) break; + *e++ = eol; + b = e; + } +} + +void Fl_Comment_Type::write_code2() {} + +//////////////////////////////////////////////////////////////// + +const char* Fl_Type::class_name(const int need_nest) const { + Fl_Type* p = parent; + while (p) { + if (p->is_class()) { + // see if we are nested in another class, we must fully-qualify name: + // this is lame but works... + const char* q = 0; + if(need_nest) q=p->class_name(need_nest); + if (q) { + static char s[256]; + if (q != s) strlcpy(s, q, sizeof(s)); + strlcat(s, "::", sizeof(s)); + strlcat(s, p->name(), sizeof(s)); + return s; + } + return p->name(); + } + p = p->parent; + } + return 0; +} + +/** + * If this Type resides inside a class, this function returns the class type, or null. + */ +const Fl_Class_Type *Fl_Type::is_in_class() const { + Fl_Type* p = parent; + while (p) { + if (p->is_class()) { + return (Fl_Class_Type*)p; + } + p = p->parent; + } + return 0; +} + +int Fl_Class_Type::is_public() const {return public_;} + +void Fl_Class_Type::prefix(const char*p) { + free((void*) class_prefix); + class_prefix=strdup(p ? p : "" ); +} + +Fl_Type *Fl_Class_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_decl_block()) p = p->parent; + Fl_Class_Type *o = new Fl_Class_Type(); + o->name("UserInterface"); + o->class_prefix=0; + o->subclass_of = 0; + o->public_ = 1; + o->add(p); + o->factory = this; + return o; +} + +void Fl_Class_Type::write_properties() { + Fl_Type::write_properties(); + if (subclass_of) { + write_string(":"); + write_word(subclass_of); + } + if (!public_) write_string("private"); +} + +void Fl_Class_Type::read_property(const char *c) { + if (!strcmp(c,"private")) { + public_ = 0; + } else if (!strcmp(c,":")) { + storestring(read_word(), subclass_of); + } else { + Fl_Type::read_property(c); + } +} + +void Fl_Class_Type::open() { + if (!class_panel) make_class_panel(); + char fullname[1024]=""; + if (prefix() && strlen(prefix())) + sprintf(fullname,"%s %s",prefix(),name()); + else + strcpy(fullname, name()); + c_name_input->static_value(fullname); + c_subclass_input->static_value(subclass_of); + c_public_button->value(public_); + class_panel->show(); + const char* message = 0; + + char *na=0,*pr=0,*p=0; // name and prefix substrings + + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == c_panel_cancel) goto BREAK2; + else if (w == c_panel_ok) break; + else if (!w) Fl::wait(); + } + const char*c = c_name_input->value(); + char *s = strdup(c); + size_t len = strlen(s); + if (!*s) goto OOPS; + p = (char*) (s+len-1); + while (p>=s && isspace(*p)) *(p--)='\0'; + if (p<s) goto OOPS; + while (p>=s && is_id(*p)) p--; + if ( (p<s && !is_id(*(p+1))) || !*(p+1) ) { + OOPS: message = "class name must be C++ identifier"; + free((void*)s); + continue; + } + na=p+1; // now we have the name + if(p>s) *p--='\0'; + while (p>=s && isspace(*p)) *(p--)='\0'; + while (p>=s && is_id(*p)) p--; + if (p<s) p++; + if (is_id(*p) && p<na) pr=p; // prefix detected + c = c_subclass_input->value(); + message = c_check(c); + if (message) { free((void*)s);continue;} + name(na); + prefix(pr); + free((void*)s); + storestring(c, subclass_of); + if (public_ != c_public_button->value()) { + public_ = c_public_button->value(); + set_modflag(1); + } + break; + } + BREAK2: + class_panel->hide(); +} + +Fl_Class_Type Fl_Class_type; + +static Fl_Class_Type *current_class; +extern Fl_Widget_Class_Type *current_widget_class; +extern int varused_test; +void write_public(int state) { + if ((!current_class && !current_widget_class) || varused_test) return; + if (current_class && current_class->write_public_state == state) return; + if (current_widget_class && current_widget_class->write_public_state == state) return; + if (current_class) current_class->write_public_state = state; + if (current_widget_class) current_widget_class->write_public_state = state; + write_h(state ? "public:\n" : "private:\n"); +} + +void Fl_Class_Type::write_code1() { + parent_class = current_class; + current_class = this; + write_public_state = 0; + if (prefix() && strlen(prefix())) + write_h("\nclass %s %s ", prefix(), name()); + else + write_h("\nclass %s ", name()); + if (subclass_of) write_h(": %s ", subclass_of); + write_h("{\n"); +} + +void Fl_Class_Type::write_code2() { + write_h("};\n"); + current_class = parent_class; +} + +/** + * Return 1 if this class contains a function with the given signature. + */ +int Fl_Class_Type::has_function(const char *rtype, const char *sig) const { + Fl_Type *child; + for (child = next; child && child->level > level; child = child->next) { + if (child->level == level+1 && strcmp(child->type_name(), "Function")==0) { + const Fl_Function_Type *fn = (const Fl_Function_Type*)child; + if (fn->has_signature(rtype, sig)) + return 1; + } + } + return 0; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/Fl_Group_Type.cxx b/Utilities/FLTK/fluid/Fl_Group_Type.cxx new file mode 100644 index 0000000000..f80652bfb2 --- /dev/null +++ b/Utilities/FLTK/fluid/Fl_Group_Type.cxx @@ -0,0 +1,307 @@ +// +// "$Id$" +// +// Fl_Group object code for the Fast Light Tool Kit (FLTK). +// +// Object describing an Fl_Group and links to Fl_Window_Type.C and +// the Fl_Tabs widget, with special stuff to select tab items and +// insure that only one is visible. +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + + +#include <FL/Fl.H> +#include <FL/Fl_Group.H> +#include <FL/fl_message.H> +#include "Fl_Widget_Type.h" +#include "../src/flstring.h" + +// Override group's resize behavior to do nothing to children: +void igroup::resize(int X, int Y, int W, int H) { + Fl_Widget::resize(X,Y,W,H); + redraw(); +} + +Fl_Group_Type Fl_Group_type; // the "factory" + +Fl_Type *Fl_Group_Type::make() { + return Fl_Widget_Type::make(); +} + +void fix_group_size(Fl_Type *tt) { + if (!tt || !tt->is_group()) return; + Fl_Group_Type* t = (Fl_Group_Type*)tt; + int X = t->o->x(); + int Y = t->o->y(); + int R = X+t->o->w(); + int B = Y+t->o->h(); + for (Fl_Type *nn = t->next; nn && nn->level > t->level; nn = nn->next) { + if (!nn->is_widget() || nn->is_menu_item()) continue; + Fl_Widget_Type* n = (Fl_Widget_Type*)nn; + int x = n->o->x(); if (x < X) X = x; + int y = n->o->y(); if (y < Y) Y = y; + int r = x+n->o->w();if (r > R) R = r; + int b = y+n->o->h();if (b > B) B = b; + } + t->o->resize(X,Y,R-X,B-Y); +} + +extern int force_parent; + +void group_cb(Fl_Widget *, void *) { + // Find the current widget: + Fl_Type *qq = Fl_Type::current; + while (qq && (!qq->is_widget() || qq->is_menu_item())) qq = qq->parent; + if (!qq || qq->level < 1 || (qq->level == 1 && !strcmp(qq->type_name(), "widget_class"))) { + fl_message("Please select widgets to group"); + return; + } + Fl_Widget_Type* q = (Fl_Widget_Type*)qq; + force_parent = 1; + Fl_Group_Type *n = (Fl_Group_Type*)(Fl_Group_type.make()); + n->move_before(q); + n->o->resize(q->o->x(),q->o->y(),q->o->w(),q->o->h()); + for (Fl_Type *t = Fl_Type::first; t;) { + if (t->level != n->level || t == n || !t->selected) { + t = t->next; continue;} + Fl_Type *nxt = t->remove(); + t->add(n); + t = nxt; + } + fix_group_size(n); +} + +void ungroup_cb(Fl_Widget *, void *) { + // Find the group: + Fl_Type *q = Fl_Type::current; + while (q && (!q->is_widget() || q->is_menu_item())) q = q->parent; + if (q) q = q->parent; + if (!q || q->level < 1 || (q->level == 1 && !strcmp(q->type_name(), "widget_class"))) { + fl_message("Please select widgets in a group"); + return; + } + Fl_Type* n; + for (n = q->next; n && n->level > q->level; n = n->next) { + if (n->level == q->level+1 && !n->selected) { + fl_message("Please select all widgets in group"); + return; + } + } + for (n = q->next; n && n->level > q->level;) { + Fl_Type *nxt = n->remove(); + n->insert(q); + n = nxt; + } + delete q; +} + +//////////////////////////////////////////////////////////////// + +#include <stdio.h> + +void Fl_Group_Type::write_code1() { + Fl_Widget_Type::write_code1(); +} + +void Fl_Group_Type::write_code2() { + write_extra_code(); + write_c("%so->end();\n", indent()); + if (resizable()) write_c("%sFl_Group::current()->resizable(o);\n", indent()); + write_block_close(); +} + +//////////////////////////////////////////////////////////////// + +const char pack_type_name[] = "Fl_Pack"; + +Fl_Menu_Item pack_type_menu[] = { + {"HORIZONTAL", 0, 0, (void*)Fl_Pack::HORIZONTAL}, + {"VERTICAL", 0, 0, (void*)Fl_Pack::VERTICAL}, + {0}}; + +Fl_Pack_Type Fl_Pack_type; // the "factory" + +//////////////////////////////////////////////////////////////// + +const char tabs_type_name[] = "Fl_Tabs"; + +// Override group's resize behavior to do nothing to children: +void itabs::resize(int X, int Y, int W, int H) { + Fl_Widget::resize(X,Y,W,H); + redraw(); +} + +Fl_Tabs_Type Fl_Tabs_type; // the "factory" + +// This is called when user clicks on a widget in the window. See +// if it is a tab title, and adjust visibility and return new selection: +// If none, return o unchanged: + +Fl_Type* Fl_Tabs_Type::click_test(int x, int y) { + Fl_Tabs *t = (Fl_Tabs*)o; + Fl_Widget *a = t->which(x,y); + if (!a) return 0; // didn't click on tab + // okay, run the tabs ui until they let go of mouse: + t->handle(FL_PUSH); + Fl::pushed(t); + while (Fl::pushed()==t) Fl::wait(); + return (Fl_Type*)(t->value()->user_data()); +} + +//////////////////////////////////////////////////////////////// + +const char wizard_type_name[] = "Fl_Wizard"; + +// Override group's resize behavior to do nothing to children: +void iwizard::resize(int X, int Y, int W, int H) { + Fl_Widget::resize(X,Y,W,H); + redraw(); +} + +Fl_Wizard_Type Fl_Wizard_type; // the "factory" + +// This is called when o is created. If it is in the tab group make +// sure it is visible: + +void Fl_Group_Type::add_child(Fl_Type* cc, Fl_Type* before) { + Fl_Widget_Type* c = (Fl_Widget_Type*)cc; + Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; + ((Fl_Group*)o)->insert(*(c->o), b); + o->redraw(); +} + +void Fl_Tabs_Type::add_child(Fl_Type* c, Fl_Type* before) { + Fl_Group_Type::add_child(c, before); +} + +// This is called when o is deleted. If it is in the tab group make +// sure it is not visible: + +void Fl_Group_Type::remove_child(Fl_Type* cc) { + Fl_Widget_Type* c = (Fl_Widget_Type*)cc; + ((Fl_Group*)o)->remove(c->o); + o->redraw(); +} + +void Fl_Tabs_Type::remove_child(Fl_Type* cc) { + Fl_Widget_Type* c = (Fl_Widget_Type*)cc; + Fl_Tabs *t = (Fl_Tabs*)o; + if (t->value() == c->o) t->value(0); + Fl_Group_Type::remove_child(c); +} + +// move, don't change selected value: + +void Fl_Group_Type::move_child(Fl_Type* cc, Fl_Type* before) { + Fl_Widget_Type* c = (Fl_Widget_Type*)cc; + Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; + ((Fl_Group*)o)->remove(c->o); + ((Fl_Group*)o)->insert(*(c->o), b); + o->redraw(); +} + +//////////////////////////////////////////////////////////////// +// live mode support + +Fl_Widget *Fl_Group_Type::enter_live_mode(int top) { + Fl_Group *grp = new Fl_Group(o->x(), o->y(), o->w(), o->h()); + live_widget = grp; + if (live_widget) { + copy_properties(); + Fl_Type *n; + for (n = next; n && n->level > level; n = n->next) { + if (n->level == level+1) + n->enter_live_mode(); + } + grp->end(); + } + return live_widget; +} + +Fl_Widget *Fl_Tabs_Type::enter_live_mode(int top) { + Fl_Tabs *grp = new Fl_Tabs(o->x(), o->y(), o->w(), o->h()); + live_widget = grp; + if (live_widget) { + copy_properties(); + Fl_Type *n; + for (n = next; n && n->level > level; n = n->next) { + if (n->level == level+1) + n->enter_live_mode(); + } + grp->end(); + } + grp->value(((Fl_Tabs*)o)->value()); + return live_widget; +} + +void Fl_Group_Type::leave_live_mode() { +} + +/** + * copy all properties from the edit widget to the live widget + */ +void Fl_Group_Type::copy_properties() { + Fl_Widget_Type::copy_properties(); +} + +//////////////////////////////////////////////////////////////// +// some other group subclasses that fluid does not treat specially: + +#include <FL/Fl_Scroll.H> + +const char scroll_type_name[] = "Fl_Scroll"; + +Fl_Menu_Item scroll_type_menu[] = { + {"BOTH", 0, 0, 0/*(void*)Fl_Scroll::BOTH*/}, + {"HORIZONTAL", 0, 0, (void*)Fl_Scroll::HORIZONTAL}, + {"VERTICAL", 0, 0, (void*)Fl_Scroll::VERTICAL}, + {"HORIZONTAL_ALWAYS", 0, 0, (void*)Fl_Scroll::HORIZONTAL_ALWAYS}, + {"VERTICAL_ALWAYS", 0, 0, (void*)Fl_Scroll::VERTICAL_ALWAYS}, + {"BOTH_ALWAYS", 0, 0, (void*)Fl_Scroll::BOTH_ALWAYS}, + {0}}; + +Fl_Scroll_Type Fl_Scroll_type; // the "factory" + +void Fl_Scroll_Type::copy_properties() { + Fl_Group_Type::copy_properties(); + Fl_Scroll *s = (Fl_Scroll*)o, *d = (Fl_Scroll*)live_widget; + d->position(s->xposition(), s->yposition()); + d->type(s->type()); // TODO: get this flag from Fl_Scroll_Type! + d->scrollbar.align(s->scrollbar.align()); + d->hscrollbar.align(s->hscrollbar.align()); +} + +//////////////////////////////////////////////////////////////// + +const char tile_type_name[] = "Fl_Tile"; + +Fl_Tile_Type Fl_Tile_type; // the "factory" + +void Fl_Tile_Type::copy_properties() { + Fl_Group_Type::copy_properties(); + // no additional properties +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/Fl_Menu_Type.cxx b/Utilities/FLTK/fluid/Fl_Menu_Type.cxx new file mode 100644 index 0000000000..5d32950723 --- /dev/null +++ b/Utilities/FLTK/fluid/Fl_Menu_Type.cxx @@ -0,0 +1,578 @@ +// +// "$Id$" +// +// Menu item code for the Fast Light Tool Kit (FLTK). +// +// Menu items are kludged by making a phony Fl_Box widget so the normal +// widget panel can be used to control them. +// +// This file also contains code to make Fl_Menu_Button, Fl_Menu_Bar, +// etc widgets. +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include "Fl_Widget_Type.h" +#include "alignment_panel.h" +#include <FL/fl_message.H> +#include <FL/Fl_Menu_.H> +#include <FL/Fl_Button.H> +#include "../src/flstring.h" +#include <stdio.h> +#include <stdlib.h> + +Fl_Menu_Item menu_item_type_menu[] = { + {"Normal",0,0,(void*)0}, + {"Toggle",0,0,(void*)FL_MENU_BOX}, + {"Radio",0,0,(void*)FL_MENU_RADIO}, + {0}}; + +extern int reading_file; +extern int force_parent; +extern int i18n_type; +extern const char* i18n_include; +extern const char* i18n_function; +extern const char* i18n_file; +extern const char* i18n_set; + +static char submenuflag; + +void Fl_Input_Choice_Type::build_menu() { + Fl_Input_Choice* w = (Fl_Input_Choice*)o; + // count how many Fl_Menu_Item structures needed: + int n = 0; + Fl_Type* q; + for (q = next; q && q->level > level; q = q->next) { + if (q->is_parent()) n++; // space for null at end of submenu + n++; + } + if (!n) { + if (menusize) delete[] (Fl_Menu_Item*)(w->menu()); + w->menu(0); + menusize = 0; + } else { + n++; // space for null at end of menu + if (menusize<n) { + if (menusize) delete[] (Fl_Menu_Item*)(w->menu()); + menusize = n+10; + w->menu(new Fl_Menu_Item[menusize]); + } + // fill them all in: + Fl_Menu_Item* m = (Fl_Menu_Item*)(w->menu()); + int lvl = level+1; + for (q = next; q && q->level > level; q = q->next) { + Fl_Menu_Item_Type* i = (Fl_Menu_Item_Type*)q; + if (i->o->image()) i->o->image()->label(m); + else { + m->label(i->o->label() ? i->o->label() : "(nolabel)"); + m->labeltype(i->o->labeltype()); + } + m->shortcut(((Fl_Button*)(i->o))->shortcut()); + m->callback(0,(void*)i); + m->flags = i->flags(); + m->labelfont(i->o->labelfont()); + m->labelsize(i->o->labelsize()); + m->labelcolor(i->o->labelcolor()); + if (q->is_parent()) {lvl++; m->flags |= FL_SUBMENU;} + m++; + int l1 = + (q->next && q->next->is_menu_item()) ? q->next->level : level; + while (lvl > l1) {m->label(0); m++; lvl--;} + lvl = l1; + } + } + o->redraw(); +} + + +Fl_Type *Fl_Menu_Item_Type::make() { + // Find the current menu item: + Fl_Type* q = Fl_Type::current; + Fl_Type* p = q; + if (p) { + if (force_parent && q->is_menu_item() || !q->is_parent()) p = p->parent; + } + force_parent = 0; + if (!p || !(p->is_menu_button() || p->is_menu_item() && p->is_parent())) { + fl_message("Please select a menu to add to"); + return 0; + } + if (!o) { + o = new Fl_Button(0,0,100,20); // create template widget + o->labelsize(Fl_Widget_Type::default_size); + } + + Fl_Menu_Item_Type* t = submenuflag ? new Fl_Submenu_Type() : new Fl_Menu_Item_Type(); + t->o = new Fl_Button(0,0,100,20); + t->factory = this; + t->add(p); + if (!reading_file) t->label(submenuflag ? "submenu" : "item"); + return t; +} + +Fl_Type *Fl_Submenu_Type::make() { + submenuflag = 1; + Fl_Type* t = Fl_Menu_Item_Type::make(); + submenuflag = 0; + return t; +} + +Fl_Menu_Item_Type Fl_Menu_Item_type; +Fl_Submenu_Type Fl_Submenu_type; + +//////////////////////////////////////////////////////////////// +// Writing the C code: + +// test functions in Fl_Widget_Type.C: +int is_name(const char *c); +const char *array_name(Fl_Widget_Type *o); +int isdeclare(const char *c); + +// Search backwards to find the parent menu button and return it's name. +// Also put in i the index into the button's menu item array belonging +// to this menu item. +const char* Fl_Menu_Item_Type::menu_name(int& i) { + i = 0; + Fl_Type* t = prev; + while (t && t->is_menu_item()) { + // be sure to count the {0} that ends a submenu: + if (t->level > t->next->level) i += (t->level - t->next->level); + // detect empty submenu: + else if (t->level == t->next->level && t->is_parent()) i++; + t = t->prev; + i++; + } + return unique_id(t, "menu", t->name(), t->label()); +} + +#include "Fluid_Image.h" + +void Fl_Menu_Item_Type::write_static() { + if (callback() && is_name(callback())) + write_declare("extern void %s(Fl_Menu_*, %s);", callback(), + user_data_type() ? user_data_type() : "void*"); + for (int n=0; n < NUM_EXTRA_CODE; n++) { + if (extra_code(n) && isdeclare(extra_code(n))) + write_declare("%s", extra_code(n)); + } + if (callback() && !is_name(callback())) { + // see if 'o' or 'v' used, to prevent unused argument warnings: + int use_o = 0; + int use_v = 0; + const char *d; + for (d = callback(); *d;) { + if (*d == 'o' && !is_id(d[1])) use_o = 1; + if (*d == 'v' && !is_id(d[1])) use_v = 1; + do d++; while (is_id(*d)); + while (*d && !is_id(*d)) d++; + } + const char* cn = callback_name(); + const char* k = class_name(1); + if (k) { + write_c("\nvoid %s::%s_i(Fl_Menu_*", k, cn); + } else { + write_c("\nstatic void %s(Fl_Menu_*", cn); + } + if (use_o) write_c(" o"); + const char* ut = user_data_type() ? user_data_type() : "void*"; + write_c(", %s", ut); + if (use_v) write_c(" v"); + write_c(") {\n %s", callback()); + if (*(d-1) != ';') { + const char *p = strrchr(callback(), '\n'); + if (p) p ++; + else p = callback(); + // Only add trailing semicolon if the last line is not a preprocessor + // statement... + if (*p != '#' && *p) write_c(";"); + } + write_c("\n}\n"); + if (k) { + write_c("void %s::%s(Fl_Menu_* o, %s v) {\n", k, cn, ut); + write_c(" ((%s*)(o->", k); + Fl_Type* t = parent; while (t->is_menu_item()) t = t->parent; + for (t = t->parent; t && t->is_widget() && !is_class(); t = t->parent) write_c("parent()->"); + write_c("user_data()))->%s_i(o,v);\n}\n", cn); + } + } + if (image) { + if (image->written != write_number) { + image->write_static(); + image->written = write_number; + } + } + if (next && next->is_menu_item()) return; + // okay, when we hit last item in the menu we have to write the + // entire array out: + const char* k = class_name(1); + if (k) { + int i; write_c("\nFl_Menu_Item %s::%s[] = {\n", k, menu_name(i)); + } else { + int i; write_c("\nFl_Menu_Item %s[] = {\n", menu_name(i)); + } + Fl_Type* t = prev; while (t && t->is_menu_item()) t = t->prev; + for (Fl_Type* q = t->next; q && q->is_menu_item(); q = q->next) { + ((Fl_Menu_Item_Type*)q)->write_item(); + int thislevel = q->level; if (q->is_parent()) thislevel++; + int nextlevel = + (q->next && q->next->is_menu_item()) ? q->next->level : t->level+1; + while (thislevel > nextlevel) {write_c(" {0,0,0,0,0,0,0,0,0},\n"); thislevel--;} + } + write_c(" {0,0,0,0,0,0,0,0,0}\n};\n"); + + if (k) { + // Write menu item variables... + t = prev; while (t && t->is_menu_item()) t = t->prev; + for (Fl_Type* q = t->next; q && q->is_menu_item(); q = q->next) { + const char *c = array_name((Fl_Menu_Item_Type *)q); + if (c) { + int i; const char* n = ((Fl_Menu_Item_Type *)q)->menu_name(i); + write_c("Fl_Menu_Item* %s::%s = %s::%s + %d;\n", k, c, k, n, i); + } + } + } +} + +int Fl_Menu_Item_Type::flags() { + int i = o->type(); + if (((Fl_Button*)o)->value()) i |= FL_MENU_VALUE; + if (!o->active()) i |= FL_MENU_INACTIVE; + if (!o->visible()) i |= FL_MENU_INVISIBLE; + if (is_parent()) { + if (user_data() == NULL) i |= FL_SUBMENU; + else i |= FL_SUBMENU_POINTER; + } + if (hotspot()) i |= FL_MENU_DIVIDER; + return i; +} + +void Fl_Menu_Item_Type::write_item() { + static const char * const labeltypes[] = { + "FL_NORMAL_LABEL", + "FL_NO_LABEL", + "FL_SHADOW_LABEL", + "FL_ENGRAVED_LABEL", + "FL_EMBOSSED_LABEL", + "FL_MULTI_LABEL", + "FL_ICON_LABEL", + "FL_IMAGE_LABEL" + }; + + write_c(" {"); + if (image) write_c("0"); + else if (label()) { + switch (i18n_type) { + case 0 : /* None */ + write_cstring(label()); + break; + case 1 : /* GNU gettext */ + write_c("%s(", i18n_function); + write_cstring(label()); + write_c(")"); + break; + case 2 : /* POSIX catgets */ + write_c("catgets(%s,%s,%d,", i18n_file[0] ? i18n_file : "_catalog", + i18n_set, msgnum()); + write_cstring(label()); + write_c(")"); + break; + } + } + else write_c("\"\""); + if (((Fl_Button*)o)->shortcut()) + write_c(", 0x%x, ", ((Fl_Button*)o)->shortcut()); + else + write_c(", 0, "); + if (callback()) { + const char* k = is_name(callback()) ? 0 : class_name(1); + if (k) { + write_c(" (Fl_Callback*)%s::%s,", k, callback_name()); + } else { + write_c(" (Fl_Callback*)%s,", callback_name()); + } + } else + write_c(" 0,"); + if (user_data()) + write_c(" (void*)(%s),", user_data()); + else + write_c(" 0,"); + write_c(" %d, %s, %d, %d, %d", flags(), + labeltypes[o->labeltype()], o->labelfont(), o->labelsize(), o->labelcolor()); + write_c("},\n"); +} + +void Fl_Menu_Item_Type::write_code1() { + int i; const char* mname = menu_name(i); + if (!prev->is_menu_item()) { + // for first menu item, declare the array + if (class_name(1)) + write_h(" static Fl_Menu_Item %s[];\n", mname); + else + write_h("extern Fl_Menu_Item %s[];\n", mname); + } + + const char *c = array_name(this); + if (c) { + if (class_name(1)) { + write_public(public_); + write_h(" static Fl_Menu_Item *%s;\n", c); + } else + write_h("#define %s (%s+%d)\n", c, mname, i); + } + + if (callback()) { + if (!is_name(callback()) && class_name(1)) { + const char* cn = callback_name(); + const char* ut = user_data_type() ? user_data_type() : "void*"; + write_public(0); + write_h(" void %s_i(Fl_Menu_*, %s);\n", cn, ut); + write_h(" static void %s(Fl_Menu_*, %s);\n", cn, ut); + } + } + + int init = 0; + if (image) { + write_c(" {Fl_Menu_Item* o = &%s[%d];\n", mname, i); + init = 1; + image->write_code(); + } + for (int n=0; n < NUM_EXTRA_CODE; n++) + if (extra_code(n) && !isdeclare(extra_code(n))) { + if (!init) { + init = 1; + write_c("%s{ Fl_Menu_Item* o = &%s[%d];\n", indent(), mname, i); + } + write_c("%s %s\n", indent(), extra_code(n)); + } + if (init) write_c("%s}\n",indent()); +} + +void Fl_Menu_Item_Type::write_code2() {} + +//////////////////////////////////////////////////////////////// +// This is the base class for widgets that contain a menu (ie +// subclasses of Fl_Menu_. +// This is a parent widget and menu items can be added as +// children. An actual array of Fl_Menu_Items is kept parallel +// with the child objects and updated as they change. + +void Fl_Menu_Type::build_menu() { + Fl_Menu_* w = (Fl_Menu_*)o; + // count how many Fl_Menu_Item structures needed: + int n = 0; + Fl_Type* q; + for (q = next; q && q->level > level; q = q->next) { + if (q->is_parent()) n++; // space for null at end of submenu + n++; + } + if (!n) { + if (menusize) delete[] (Fl_Menu_Item*)(w->menu()); + w->menu(0); + menusize = 0; + } else { + n++; // space for null at end of menu + if (menusize<n) { + if (menusize) delete[] (Fl_Menu_Item*)(w->menu()); + menusize = n+10; + w->menu(new Fl_Menu_Item[menusize]); + } + // fill them all in: + Fl_Menu_Item* m = (Fl_Menu_Item*)(w->menu()); + int lvl = level+1; + for (q = next; q && q->level > level; q = q->next) { + Fl_Menu_Item_Type* i = (Fl_Menu_Item_Type*)q; + if (i->o->image()) i->o->image()->label(m); + else { + m->label(i->o->label() ? i->o->label() : "(nolabel)"); + m->labeltype(i->o->labeltype()); + } + m->shortcut(((Fl_Button*)(i->o))->shortcut()); + m->callback(0,(void*)i); + m->flags = i->flags(); + m->labelfont(i->o->labelfont()); + m->labelsize(i->o->labelsize()); + m->labelcolor(i->o->labelcolor()); + if (q->is_parent()) {lvl++; m->flags |= FL_SUBMENU;} + m++; + int l1 = + (q->next && q->next->is_menu_item()) ? q->next->level : level; + while (lvl > l1) {m->label(0); m++; lvl--;} + lvl = l1; + } + } + o->redraw(); +} + +Fl_Type* Fl_Menu_Type::click_test(int, int) { + if (selected) return 0; // let user move the widget + Fl_Menu_* w = (Fl_Menu_*)o; + if (!menusize) return 0; + const Fl_Menu_Item* save = w->mvalue(); + w->value((Fl_Menu_Item*)0); + Fl::pushed(w); + w->handle(FL_PUSH); + const Fl_Menu_Item* m = w->mvalue(); + if (m) { + // restore the settings of toggles & radio items: + if (m->flags & (FL_MENU_RADIO | FL_MENU_TOGGLE)) build_menu(); + return (Fl_Type*)(m->user_data()); + } + w->value(save); + return this; +} + +void Fl_Menu_Type::write_code2() { + if (next && next->is_menu_item()) + write_c("%so->menu(%s);\n", indent(), + unique_id(this, "menu", name(), label())); + Fl_Widget_Type::write_code2(); +} + +void Fl_Menu_Type::copy_properties() { + Fl_Widget_Type::copy_properties(); + Fl_Menu_ *s = (Fl_Menu_*)o, *d = (Fl_Menu_*)live_widget; + d->menu(s->menu()); + d->down_box(s->down_box()); + d->textcolor(s->textcolor()); + d->textfont(s->textfont()); + d->textsize(s->textsize()); +} + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Menu_Button.H> +Fl_Menu_Item button_type_menu[] = { + {"normal",0,0,(void*)0}, + {"popup1",0,0,(void*)Fl_Menu_Button::POPUP1}, + {"popup2",0,0,(void*)Fl_Menu_Button::POPUP2}, + {"popup3",0,0,(void*)Fl_Menu_Button::POPUP3}, + {"popup12",0,0,(void*)Fl_Menu_Button::POPUP12}, + {"popup23",0,0,(void*)Fl_Menu_Button::POPUP23}, + {"popup13",0,0,(void*)Fl_Menu_Button::POPUP13}, + {"popup123",0,0,(void*)Fl_Menu_Button::POPUP123}, + {0}}; + +Fl_Menu_Button_Type Fl_Menu_Button_type; + +//////////////////////////////////////////////////////////////// + +Fl_Menu_Item dummymenu[] = {{"CHOICE"},{0}}; + +Fl_Choice_Type Fl_Choice_type; + +Fl_Input_Choice_Type Fl_Input_Choice_type; + +void Fl_Input_Choice_Type::copy_properties() { + Fl_Widget_Type::copy_properties(); + Fl_Input_Choice *s = (Fl_Input_Choice*)o, *d = (Fl_Input_Choice*)live_widget; + d->menu(s->menu()); + d->down_box(s->down_box()); + d->textcolor(s->textcolor()); + d->textfont(s->textfont()); + d->textsize(s->textsize()); +} + +Fl_Type* Fl_Input_Choice_Type::click_test(int, int) { + if (selected) return 0; // let user move the widget + Fl_Menu_* w = ((Fl_Input_Choice*)o)->menubutton(); + if (!menusize) return 0; + const Fl_Menu_Item* save = w->mvalue(); + w->value((Fl_Menu_Item*)0); + Fl::pushed(w); + w->handle(FL_PUSH); + const Fl_Menu_Item* m = w->mvalue(); + if (m) { + // restore the settings of toggles & radio items: + if (m->flags & (FL_MENU_RADIO | FL_MENU_TOGGLE)) build_menu(); + return (Fl_Type*)(m->user_data()); + } + w->value(save); + return this; +} + +//////////////////////////////////////////////////////////////// + +Fl_Menu_Bar_Type Fl_Menu_Bar_type; + +//////////////////////////////////////////////////////////////// +// Shortcut entry item in panel: + +#include <FL/Fl_Output.H> +#include "Shortcut_Button.h" +#include <FL/fl_draw.H> + +void Shortcut_Button::draw() { + if (value()) draw_box(FL_DOWN_BOX, (Fl_Color)9); + else draw_box(FL_UP_BOX, FL_WHITE); + fl_font(FL_HELVETICA,14); fl_color(FL_FOREGROUND_COLOR); + fl_draw(fl_shortcut_label(svalue),x()+6,y(),w(),h(),FL_ALIGN_LEFT); +} + +int Shortcut_Button::handle(int e) { + when(0); type(FL_TOGGLE_BUTTON); + if (e == FL_KEYBOARD) { + if (!value()) return 0; + int v = Fl::event_text()[0]; + if (v > 32 && v < 0x7f || v > 0xa0 && v <= 0xff) { + if (isupper(v)) { + v = tolower(v); + v |= FL_SHIFT; + } + v = v | Fl::event_state()&(FL_META|FL_ALT|FL_CTRL); + } else { + v = Fl::event_state()&(FL_META|FL_ALT|FL_CTRL|FL_SHIFT) | Fl::event_key(); + if (v == FL_BackSpace && svalue) v = 0; + } + if (v != svalue) {svalue = v; set_changed(); redraw(); do_callback(); } + return 1; + } else if (e == FL_UNFOCUS) { + int c = changed(); value(0); if (c) set_changed(); + return 1; + } else if (e == FL_FOCUS) { + return value(); + } else { + int r = Fl_Button::handle(e); + if (e == FL_RELEASE && value() && Fl::focus() != this) take_focus(); + return r; + } +} + +void shortcut_in_cb(Shortcut_Button* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_button()) {i->hide(); return;} + i->show(); + i->svalue = ((Fl_Button*)(current_widget->o))->shortcut(); + i->redraw(); + } else { + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_button()) { + Fl_Button* b = (Fl_Button*)(((Fl_Widget_Type*)o)->o); + b->shortcut(i->svalue); + if (o->is_menu_item()) ((Fl_Widget_Type*)o)->redraw(); + } + } +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/Fl_Type.cxx b/Utilities/FLTK/fluid/Fl_Type.cxx new file mode 100644 index 0000000000..92e1c807cc --- /dev/null +++ b/Utilities/FLTK/fluid/Fl_Type.cxx @@ -0,0 +1,866 @@ +// +// "$Id$" +// +// Widget type code for the Fast Light Tool Kit (FLTK). +// +// Each object described by Fluid is one of these objects. They +// are all stored in a double-linked list. +// +// They "type" of the object is covered by the virtual functions. +// There will probably be a lot of these virtual functions. +// +// The type browser is also a list of these objects, but they +// are "factory" instances, not "real" ones. These objects exist +// only so the "make" method can be called on them. They are +// not in the linked list and are not written to files or +// copied or otherwise examined. +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Browser_.H> +#include <FL/fl_draw.H> +#include <stdlib.h> +#include "../src/flstring.h" +#include <stdio.h> + +#include "Fl_Type.h" +#include "undo.h" + +#include <FL/Fl_Pixmap.H> +#include "pixmaps/lock.xpm" +//#include "pixmaps/unlock.xpm" + +static Fl_Pixmap lock_pixmap(lock_xpm); +//static Fl_Pixmap unlock_pixmap(unlock_xpm); + +#include "pixmaps/flWindow.xpm" +#include "pixmaps/flButton.xpm" +#include "pixmaps/flCheckButton.xpm" +#include "pixmaps/flRoundButton.xpm" +#include "pixmaps/flBox.xpm" +#include "pixmaps/flGroup.xpm" +#include "pixmaps/flFunction.xpm" +#include "pixmaps/flCode.xpm" +#include "pixmaps/flCodeBlock.xpm" +#include "pixmaps/flComment.xpm" +#include "pixmaps/flDeclaration.xpm" +#include "pixmaps/flDeclarationBlock.xpm" +#include "pixmaps/flClass.xpm" +#include "pixmaps/flTabs.xpm" +#include "pixmaps/flInput.xpm" +#include "pixmaps/flChoice.xpm" +#include "pixmaps/flMenuitem.xpm" +#include "pixmaps/flMenubar.xpm" +#include "pixmaps/flSubmenu.xpm" +#include "pixmaps/flScroll.xpm" +#include "pixmaps/flTile.xpm" +#include "pixmaps/flWizard.xpm" +#include "pixmaps/flPack.xpm" +#include "pixmaps/flReturnButton.xpm" +#include "pixmaps/flLightButton.xpm" +#include "pixmaps/flRepeatButton.xpm" +#include "pixmaps/flMenuButton.xpm" +#include "pixmaps/flOutput.xpm" +#include "pixmaps/flTextDisplay.xpm" +#include "pixmaps/flTextEdit.xpm" +#include "pixmaps/flFileInput.xpm" +#include "pixmaps/flBrowser.xpm" +#include "pixmaps/flCheckBrowser.xpm" +#include "pixmaps/flFileBrowser.xpm" +#include "pixmaps/flClock.xpm" +#include "pixmaps/flHelp.xpm" +#include "pixmaps/flProgress.xpm" +#include "pixmaps/flSlider.xpm" +#include "pixmaps/flScrollBar.xpm" +#include "pixmaps/flValueSlider.xpm" +#include "pixmaps/flAdjuster.xpm" +#include "pixmaps/flCounter.xpm" +#include "pixmaps/flDial.xpm" +#include "pixmaps/flRoller.xpm" +#include "pixmaps/flValueInput.xpm" +#include "pixmaps/flValueOutput.xpm" +#include "pixmaps/flSpinner.xpm" +#include "pixmaps/flWidgetClass.xpm" + +static Fl_Pixmap window_pixmap(flWindow_xpm); +static Fl_Pixmap button_pixmap(flButton_xpm); +static Fl_Pixmap checkbutton_pixmap(flCheckButton_xpm); +static Fl_Pixmap roundbutton_pixmap(flRoundButton_xpm); +static Fl_Pixmap box_pixmap(flBox_xpm); +static Fl_Pixmap group_pixmap(flGroup_xpm); +static Fl_Pixmap function_pixmap(flFunction_xpm); +static Fl_Pixmap code_pixmap(flCode_xpm); +static Fl_Pixmap codeblock_pixmap(flCodeBlock_xpm); +static Fl_Pixmap comment_pixmap(flComment_xpm); +static Fl_Pixmap declaration_pixmap(flDeclaration_xpm); +static Fl_Pixmap declarationblock_pixmap(flDeclarationBlock_xpm); +static Fl_Pixmap class_pixmap(flClass_xpm); +static Fl_Pixmap tabs_pixmap(flTabs_xpm); +static Fl_Pixmap input_pixmap(flInput_xpm); +static Fl_Pixmap choice_pixmap(flChoice_xpm); +static Fl_Pixmap menuitem_pixmap(flMenuitem_xpm); +static Fl_Pixmap menubar_pixmap(flMenubar_xpm); +static Fl_Pixmap submenu_pixmap(flSubmenu_xpm); +static Fl_Pixmap scroll_pixmap(flScroll_xpm); +static Fl_Pixmap tile_pixmap(flTile_xpm); +static Fl_Pixmap wizard_pixmap(flWizard_xpm); +static Fl_Pixmap pack_pixmap(flPack_xpm); +static Fl_Pixmap returnbutton_pixmap(flReturnButton_xpm); +static Fl_Pixmap lightbutton_pixmap(flLightButton_xpm); +static Fl_Pixmap repeatbutton_pixmap(flRepeatButton_xpm); +static Fl_Pixmap menubutton_pixmap(flMenuButton_xpm); +static Fl_Pixmap output_pixmap(flOutput_xpm); +static Fl_Pixmap textdisplay_pixmap(flTextDisplay_xpm); +static Fl_Pixmap textedit_pixmap(flTextEdit_xpm); +static Fl_Pixmap fileinput_pixmap(flFileInput_xpm); +static Fl_Pixmap browser_pixmap(flBrowser_xpm); +static Fl_Pixmap checkbrowser_pixmap(flCheckBrowser_xpm); +static Fl_Pixmap filebrowser_pixmap(flFileBrowser_xpm); +static Fl_Pixmap clock_pixmap(flClock_xpm); +static Fl_Pixmap help_pixmap(flHelp_xpm); +static Fl_Pixmap progress_pixmap(flProgress_xpm); +static Fl_Pixmap slider_pixmap(flSlider_xpm); +static Fl_Pixmap scrollbar_pixmap(flScrollBar_xpm); +static Fl_Pixmap valueslider_pixmap(flValueSlider_xpm); +static Fl_Pixmap adjuster_pixmap(flAdjuster_xpm); +static Fl_Pixmap counter_pixmap(flCounter_xpm); +static Fl_Pixmap dial_pixmap(flDial_xpm); +static Fl_Pixmap roller_pixmap(flRoller_xpm); +static Fl_Pixmap valueinput_pixmap(flValueInput_xpm); +static Fl_Pixmap valueoutput_pixmap(flValueOutput_xpm); +static Fl_Pixmap spinner_pixmap(flSpinner_xpm); +static Fl_Pixmap widgetclass_pixmap(flWidgetClass_xpm); + +Fl_Pixmap *pixmap[] = { 0, &window_pixmap, &button_pixmap, &checkbutton_pixmap, &roundbutton_pixmap, /* 0..4 */ + &box_pixmap, &group_pixmap, &function_pixmap, &code_pixmap, &codeblock_pixmap, &declaration_pixmap, /* 5..10 */ + &declarationblock_pixmap, &class_pixmap, &tabs_pixmap, &input_pixmap, &choice_pixmap, /* 11..15 */ + &menuitem_pixmap, &menubar_pixmap, &submenu_pixmap, &scroll_pixmap, &tile_pixmap, &wizard_pixmap, /* 16..21 */ + &pack_pixmap, &returnbutton_pixmap, &lightbutton_pixmap, &repeatbutton_pixmap, &menubutton_pixmap, /* 22..26 */ + &output_pixmap, &textdisplay_pixmap, &textedit_pixmap, &fileinput_pixmap, &browser_pixmap, /* 27..32 */ + &checkbrowser_pixmap, &filebrowser_pixmap, &clock_pixmap, &help_pixmap, &progress_pixmap, /* 33..36 */ + &slider_pixmap, &scrollbar_pixmap, &valueslider_pixmap, &adjuster_pixmap, &counter_pixmap, /* 37..41 */ + &dial_pixmap, &roller_pixmap, &valueinput_pixmap, &valueoutput_pixmap, &comment_pixmap, /* 42..46 */ + &spinner_pixmap, &widgetclass_pixmap /* 47..48 */ }; + +//////////////////////////////////////////////////////////////// + +class Widget_Browser : public Fl_Browser_ { + friend class Fl_Type; + + // required routines for Fl_Browser_ subclass: + void *item_first() const ; + void *item_next(void *) const ; + void *item_prev(void *) const ; + int item_selected(void *) const ; + void item_select(void *,int); + int item_width(void *) const ; + int item_height(void *) const ; + void item_draw(void *,int,int,int,int) const ; + int incr_height() const ; + +public: + + int handle(int); + void callback(); + Widget_Browser(int,int,int,int,const char * =0); +}; + +static Widget_Browser *widget_browser; +Fl_Widget *make_widget_browser(int x,int y,int w,int h) { + return (widget_browser = new Widget_Browser(x,y,w,h)); +} + +void select(Fl_Type *o, int v) { + widget_browser->select(o,v,1); + // Fl_Type::current = o; +} + +void select_only(Fl_Type *o) { + widget_browser->select_only(o,1); +} + +void deselect() { + widget_browser->deselect(); + //Fl_Type::current = 0; // this breaks the paste & merge functions +} + +Fl_Type *Fl_Type::first; +Fl_Type *Fl_Type::last; + +static void Widget_Browser_callback(Fl_Widget *o,void *) { + ((Widget_Browser *)o)->callback(); +} + +Widget_Browser::Widget_Browser(int X,int Y,int W,int H,const char*l) +: Fl_Browser_(X,Y,W,H,l) { + type(FL_MULTI_BROWSER); + Fl_Widget::callback(Widget_Browser_callback); + when(FL_WHEN_RELEASE); +} + +void *Widget_Browser::item_first() const {return Fl_Type::first;} + +void *Widget_Browser::item_next(void *l) const {return ((Fl_Type*)l)->next;} + +void *Widget_Browser::item_prev(void *l) const {return ((Fl_Type*)l)->prev;} + +int Widget_Browser::item_selected(void *l) const {return ((Fl_Type*)l)->new_selected;} + +void Widget_Browser::item_select(void *l,int v) {((Fl_Type*)l)->new_selected = v;} + +int Widget_Browser::item_height(void *l) const { + return ((Fl_Type *)l)->visible ? textsize()+2 : 0; +} + +int Widget_Browser::incr_height() const {return textsize()+2;} + +static Fl_Type* pushedtitle; + +// Generate a descriptive text for this item, to put in browser & window titles +const char* Fl_Type::title() { + const char* c = name(); if (c) return c; + return type_name(); +} + +extern const char* subclassname(Fl_Type*); + +void Widget_Browser::item_draw(void *v, int X, int Y, int, int) const { + Fl_Type *l = (Fl_Type *)v; + X += 3 + 18 + l->level * 12; + if (l->new_selected) fl_color(fl_contrast(FL_FOREGROUND_COLOR,FL_SELECTION_COLOR)); + else fl_color(FL_FOREGROUND_COLOR); + Fl_Pixmap *pm = pixmap[l->pixmapID()]; + if (pm) pm->draw(X-18, Y); + if (l->is_public() == 0) lock_pixmap.draw(X - 17, Y); + else if (l->is_public() > 0) ; //unlock_pixmap.draw(X - 17, Y); + if (l->is_parent()) { + if (!l->next || l->next->level <= l->level) { + if (l->open_!=(l==pushedtitle)) { + fl_loop(X,Y+7,X+5,Y+12,X+10,Y+7); + } else { + fl_loop(X+2,Y+2,X+7,Y+7,X+2,Y+12); + } + } else { + if (l->open_!=(l==pushedtitle)) { + fl_polygon(X,Y+7,X+5,Y+12,X+10,Y+7); + } else { + fl_polygon(X+2,Y+2,X+7,Y+7,X+2,Y+12); + } + } + X += 10; + } + if (l->is_widget() || l->is_class()) { + const char* c = subclassname(l); + if (!strncmp(c,"Fl_",3)) c += 3; + fl_font(textfont(), textsize()); + fl_draw(c, X, Y+13); + X += int(fl_width(c)+fl_width('n')); + c = l->name(); + if (c) { + fl_font(textfont()|FL_BOLD, textsize()); + fl_draw(c, X, Y+13); + } else if ((c=l->label())) { + char buf[50]; char* p = buf; + *p++ = '"'; + for (int i = 20; i--;) { + if (! (*c & -32)) break; + *p++ = *c++; + } + if (*c) {strcpy(p,"..."); p+=3;} + *p++ = '"'; + *p = 0; + fl_draw(buf, X, Y+13); + } + } else { + const char* c = l->title(); + char buf[60]; char* p = buf; + for (int i = 55; i--;) { + if (! (*c & -32)) break; + *p++ = *c++; + } + if (*c) {strcpy(p,"..."); p+=3;} + *p = 0; + fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize()); + fl_draw(buf, X, Y+13); + } +} + +int Widget_Browser::item_width(void *v) const { + Fl_Type *l = (Fl_Type *)v; + + if (!l->visible) return 0; + + int W = 3 + 16 + 18 + l->level*10; + if (l->is_parent()) W += 10; + + if (l->is_widget() || l->is_class()) { + const char* c = l->type_name(); + if (!strncmp(c,"Fl_",3)) c += 3; + fl_font(textfont(), textsize()); + W += int(fl_width(c) + fl_width('n')); + c = l->name(); + if (c) { + fl_font(textfont()|FL_BOLD, textsize()); + W += int(fl_width(c)); + } else if ((c=l->label())) { + char buf[50]; char* p = buf; + *p++ = '"'; + for (int i = 20; i--;) { + if (! (*c & -32)) break; + *p++ = *c++; + } + if (*c) {strcpy(p,"..."); p+=3;} + *p++ = '"'; + *p = 0; + W += int(fl_width(buf)); + } + } else { + const char* c = l->title(); + char buf[60]; char* p = buf; + for (int i = 55; i--;) { + if (! (*c & -32)) break; + *p++ = *c++; + } + if (*c) {strcpy(p,"..."); p+=3;} + *p = 0; + fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize()); + W += int(fl_width(buf)); + } + + return W; +} + +void redraw_browser() { + widget_browser->redraw(); +} + +void Widget_Browser::callback() { + selection_changed((Fl_Type*)selection()); +} + +int Widget_Browser::handle(int e) { + static Fl_Type *title; + Fl_Type *l; + int X,Y,W,H; bbox(X,Y,W,H); + switch (e) { + case FL_PUSH: + if (!Fl::event_inside(X,Y,W,H)) break; + l = (Fl_Type*)find_item(Fl::event_y()); + if (l) { + X += 12*l->level + 18 - hposition(); + if (l->is_parent() && Fl::event_x()>X && Fl::event_x()<X+13) { + title = pushedtitle = l; + redraw_line(l); + return 1; + } + } + break; + case FL_DRAG: + if (!title) break; + l = (Fl_Type*)find_item(Fl::event_y()); + if (l) { + X += 12*l->level + 18 - hposition(); + if (l->is_parent() && Fl::event_x()>X && Fl::event_x()<X+13) ; + else l = 0; + } + if (l != pushedtitle) { + if (pushedtitle) redraw_line(pushedtitle); + if (l) redraw_line(l); + pushedtitle = l; + } + return 1; + case FL_RELEASE: + if (!title) { + l = (Fl_Type*)find_item(Fl::event_y()); + if (l && l->new_selected && (Fl::event_clicks() || Fl::event_state(FL_CTRL))) + l->open(); + break; + } + l = pushedtitle; + title = pushedtitle = 0; + if (l) { + if (l->open_) { + l->open_ = 0; + for (Fl_Type*k = l->next; k&&k->level>l->level; k = k->next) + k->visible = 0; + } else { + l->open_ = 1; + for (Fl_Type*k=l->next; k&&k->level>l->level;) { + k->visible = 1; + if (k->is_parent() && !k->open_) { + Fl_Type *j; + for (j = k->next; j && j->level>k->level; j = j->next); + k = j; + } else + k = k->next; + } + } + redraw(); + } + return 1; + } + return Fl_Browser_::handle(e); +} + +Fl_Type::Fl_Type() { + factory = 0; + parent = 0; + next = prev = 0; + selected = new_selected = 0; + visible = 0; + name_ = 0; + label_ = 0; + user_data_ = 0; + user_data_type_ = 0; + callback_ = 0; + rtti = 0; + level = 0; + code_line = header_line = -1; + code_line_end = header_line_end = -1; +} + +static void fixvisible(Fl_Type *p) { + Fl_Type *t = p; + for (;;) { + if (t->parent) t->visible = t->parent->visible && t->parent->open_; + else t->visible = 1; + t = t->next; + if (!t || t->level <= p->level) break; + } +} + +// turn a click at x,y on this into the actual picked object: +Fl_Type* Fl_Type::click_test(int,int) {return 0;} +void Fl_Type::add_child(Fl_Type*, Fl_Type*) {} +void Fl_Type::move_child(Fl_Type*, Fl_Type*) {} +void Fl_Type::remove_child(Fl_Type*) {} + +// add a list of widgets as a new child of p: +void Fl_Type::add(Fl_Type *p) { + if (p && parent == p) return; + undo_checkpoint(); + parent = p; + Fl_Type *end = this; + while (end->next) end = end->next; + Fl_Type *q; + int newlevel; + if (p) { + for (q = p->next; q && q->level > p->level; q = q->next); + newlevel = p->level+1; + } else { + q = 0; + newlevel = 0; + } + for (Fl_Type *t = this->next; t; t = t->next) t->level += (newlevel-level); + level = newlevel; + if (q) { + prev = q->prev; + prev->next = this; + q->prev = end; + end->next = q; + } else if (first) { + prev = last; + prev->next = this; + end->next = 0; + last = end; + } else { + first = this; + last = end; + prev = end->next = 0; + } + if (p) p->add_child(this,0); + open_ = 1; + fixvisible(this); + set_modflag(1); + widget_browser->redraw(); +} + +// add to a parent before another widget: +void Fl_Type::insert(Fl_Type *g) { + Fl_Type *end = this; + while (end->next) end = end->next; + parent = g->parent; + int newlevel = g->level; + visible = g->visible; + for (Fl_Type *t = this->next; t; t = t->next) t->level += newlevel-level; + level = newlevel; + prev = g->prev; + if (prev) prev->next = this; else first = this; + end->next = g; + g->prev = end; + fixvisible(this); + if (parent) parent->add_child(this, g); + widget_browser->redraw(); +} + +// Return message number for I18N... +int +Fl_Type::msgnum() { + int count; + Fl_Type *p; + + for (count = 0, p = this; p;) { + if (p->label()) count ++; + if (p != this && p->is_widget() && ((Fl_Widget_Type *)p)->tooltip()) count ++; + + if (p->prev) p = p->prev; + else p = p->parent; + } + + return count; +} + + +// delete from parent: +Fl_Type *Fl_Type::remove() { + Fl_Type *end = this; + for (;;) { + if (!end->next || end->next->level <= level) break; + end = end->next; + } + if (prev) prev->next = end->next; + else first = end->next; + if (end->next) end->next->prev = prev; + else last = prev; + Fl_Type *r = end->next; + prev = end->next = 0; + if (parent) parent->remove_child(this); + parent = 0; + widget_browser->redraw(); + selection_changed(0); + return r; +} + +// update a string member: +int storestring(const char *n, const char * & p, int nostrip) { + if (n == p) return 0; + undo_checkpoint(); + int length = 0; + if (n) { // see if blank, strip leading & trailing blanks + if (!nostrip) while (isspace(*n)) n++; + const char *e = n + strlen(n); + if (!nostrip) while (e > n && isspace(*(e-1))) e--; + length = e-n; + if (!length) n = 0; + } + if (n == p) return 0; + if (n && p && !strncmp(n,p,length) && !p[length]) return 0; + if (p) free((void *)p); + if (!n || !*n) { + p = 0; + } else { + char *q = (char *)malloc(length+1); + strlcpy(q,n,length+1); + p = q; + } + set_modflag(1); + return 1; +} + +void Fl_Type::name(const char *n) { + int nostrip = is_comment(); + if (storestring(n,name_,nostrip)) { + if (visible) widget_browser->redraw(); + } +} + +void Fl_Type::label(const char *n) { + if (storestring(n,label_,1)) { + setlabel(label_); + if (visible && !name_) widget_browser->redraw(); + } +} + +void Fl_Type::callback(const char *n) { + storestring(n,callback_); +} + +void Fl_Type::user_data(const char *n) { + storestring(n,user_data_); +} + +void Fl_Type::user_data_type(const char *n) { + storestring(n,user_data_type_); +} + +void Fl_Type::open() { + printf("Open of '%s' is not yet implemented\n",type_name()); +} + +void Fl_Type::setlabel(const char *) {} + +Fl_Type::~Fl_Type() { + // warning: destructor only works for widgets that have been add()ed. + if (widget_browser) widget_browser->deleting(this); + if (prev) prev->next = next; else first = next; + if (next) next->prev = prev; else last = prev; + if (current == this) current = 0; + if (parent) parent->remove_child(this); +} + +int Fl_Type::is_parent() const {return 0;} +int Fl_Type::is_widget() const {return 0;} +int Fl_Type::is_valuator() const {return 0;} +int Fl_Type::is_button() const {return 0;} +int Fl_Type::is_menu_item() const {return 0;} +int Fl_Type::is_menu_button() const {return 0;} +int Fl_Type::is_group() const {return 0;} +int Fl_Type::is_window() const {return 0;} +int Fl_Type::is_code_block() const {return 0;} +int Fl_Type::is_decl_block() const {return 0;} +int Fl_Type::is_comment() const {return 0;} +int Fl_Type::is_class() const {return 0;} +int Fl_Type::is_public() const {return 1;} + +int Fl_Code_Type::is_public()const { return -1; } +int Fl_CodeBlock_Type::is_public()const { return -1; } + + +//////////////////////////////////////////////////////////////// + +Fl_Type *in_this_only; // set if menu popped-up in window + +void select_all_cb(Fl_Widget *,void *) { + Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0; + if (in_this_only) { + Fl_Type *t = p; + for (; t && t != in_this_only; t = t->parent); + if (t != in_this_only) p = in_this_only; + } + for (;;) { + if (p) { + int foundany = 0; + for (Fl_Type *t = p->next; t && t->level>p->level; t = t->next) { + if (!t->new_selected) {widget_browser->select(t,1,0); foundany = 1;} + } + if (foundany) break; + p = p->parent; + } else { + for (Fl_Type *t = Fl_Type::first; t; t = t->next) + widget_browser->select(t,1,0); + break; + } + } + selection_changed(p); +} + +void select_none_cb(Fl_Widget *,void *) { + Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0; + if (in_this_only) { + Fl_Type *t = p; + for (; t && t != in_this_only; t = t->parent); + if (t != in_this_only) p = in_this_only; + } + for (;;) { + if (p) { + int foundany = 0; + for (Fl_Type *t = p->next; t && t->level>p->level; t = t->next) { + if (t->new_selected) {widget_browser->select(t,0,0); foundany = 1;} + } + if (foundany) break; + p = p->parent; + } else { + for (Fl_Type *t = Fl_Type::first; t; t = t->next) + widget_browser->select(t,0,0); + break; + } + } + selection_changed(p); +} + +static void delete_children(Fl_Type *p) { + Fl_Type *f; + for (f = p; f && f->next && f->next->level > p->level; f = f->next); + for (; f != p; ) { + Fl_Type *g = f->prev; + delete f; + f = g; + } +} + +void delete_all(int selected_only) { + for (Fl_Type *f = Fl_Type::first; f;) { + if (f->selected || !selected_only) { + delete_children(f); + Fl_Type *g = f->next; + delete f; + f = g; + } else f = f->next; + } + if(!selected_only) include_H_from_C=1; + + selection_changed(0); +} + +// move f (and it's children) into list before g: +// returns pointer to whatever is after f & children +void Fl_Type::move_before(Fl_Type* g) { + if (level != g->level) printf("move_before levels don't match! %d %d\n", + level, g->level); + Fl_Type* n; + for (n = next; n && n->level > level; n = n->next); + if (n == g) return; + Fl_Type *l = n ? n->prev : Fl_Type::last; + prev->next = n; + if (n) n->prev = prev; else Fl_Type::last = prev; + prev = g->prev; + l->next = g; + if (prev) prev->next = this; else Fl_Type::first = this; + g->prev = l; + if (parent && is_widget()) parent->move_child(this,g); + widget_browser->redraw(); +} + +// move selected widgets in their parent's list: +void earlier_cb(Fl_Widget*,void*) { + Fl_Type *f; + int mod = 0; + for (f = Fl_Type::first; f; ) { + Fl_Type* nxt = f->next; + if (f->selected) { + Fl_Type* g; + for (g = f->prev; g && g->level > f->level; g = g->prev); + if (g && g->level == f->level && !g->selected) { + f->move_before(g); + mod = 1; + } + } + f = nxt; + } + if (mod) set_modflag(1); +} + +void later_cb(Fl_Widget*,void*) { + Fl_Type *f; + int mod = 0; + for (f = Fl_Type::last; f; ) { + Fl_Type* prv = f->prev; + if (f->selected) { + Fl_Type* g; + for (g = f->next; g && g->level > f->level; g = g->next); + if (g && g->level == f->level && !g->selected) { + g->move_before(f); + mod = 1; + } + } + f = prv; + } + if (mod) set_modflag(1); +} + +//////////////////////////////////////////////////////////////// + +// write a widget and all it's children: +void Fl_Type::write() { + write_indent(level); + write_word(type_name()); + + if (is_class()) { + const char * p = ((Fl_Class_Type*)this)->prefix(); + if (p && strlen(p)) + write_word(p); + } + + write_word(name()); + write_open(level); + write_properties(); + write_close(level); + if (!is_parent()) return; + // now do children: + write_open(level); + Fl_Type *child; + for (child = next; child && child->level > level; child = child->next) + if (child->level == level+1) child->write(); + write_close(level); +} + +void Fl_Type::write_properties() { + // repeat this for each attribute: + if (label()) { + write_indent(level+1); + write_word("label"); + write_word(label()); + } + if (user_data()) { + write_indent(level+1); + write_word("user_data"); + write_word(user_data()); + } + if (user_data_type()) { + write_word("user_data_type"); + write_word(user_data_type()); + } + if (callback()) { + write_indent(level+1); + write_word("callback"); + write_word(callback()); + } + if (is_parent() && open_) write_word("open"); + if (selected) write_word("selected"); +} + +void Fl_Type::read_property(const char *c) { + if (!strcmp(c,"label")) + label(read_word()); + else if (!strcmp(c,"user_data")) + user_data(read_word()); + else if (!strcmp(c,"user_data_type")) + user_data_type(read_word()); + else if (!strcmp(c,"callback")) + callback(read_word()); + else if (!strcmp(c,"open")) + open_ = 1; + else if (!strcmp(c,"selected")) + select(this,1); + else + read_error("Unknown property \"%s\"", c); +} + +int Fl_Type::read_fdesign(const char*, const char*) {return 0;} + +/** + * Build widgets and dataset needed in live mode. + * \return a widget pointer that the live mode initiator can 'show()' + * \see leave_live_mode() + */ +Fl_Widget *Fl_Type::enter_live_mode(int top) { + return 0L; +} + +/** + * Release all resources created when enetring live mode. + * \see enter_live_mode() + */ +void Fl_Type::leave_live_mode() { +} + +/** + * Copy all needed properties for this tye into the live object. + */ +void Fl_Type::copy_properties() { +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/Fl_Type.h b/Utilities/FLTK/fluid/Fl_Type.h new file mode 100644 index 0000000000..fe9d65351b --- /dev/null +++ b/Utilities/FLTK/fluid/Fl_Type.h @@ -0,0 +1,764 @@ +// +// "$Id$" +// +// Widget type header file for the Fast Light Tool Kit (FLTK). +// +// Each object described by Fluid is one of these objects. They +// are all stored in a double-linked list. +// +// There is also a single "factory" instance of each type of this. +// The method "make()" is called on this factory to create a new +// instance of this object. It could also have a "copy()" function, +// but it was easier to implement this by using the file read/write +// that is needed to save the setup anyways. +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl_Widget.H> +#include <FL/Fl_Menu.H> +#include "Fluid_Image.h" +#include <FL/fl_draw.H> + +void set_modflag(int mf); + +class Fl_Type { + + friend class Widget_Browser; + friend Fl_Widget *make_type_browser(int,int,int,int,const char *l=0); + friend class Fl_Window_Type; + virtual void setlabel(const char *); // virtual part of label(char*) + +protected: + + Fl_Type(); + + const char *name_; + const char *label_; + const char *callback_; + const char *user_data_; + const char *user_data_type_; + +public: // things that should not be public: + + Fl_Type *parent; // parent, which is previous in list + char new_selected; // browser highlight + char selected; // copied here by selection_changed() + char open_; // state of triangle in browser + char visible; // true if all parents are open + char rtti; // hack because I have no rtti, this is 0 for base class + int level; // number of parents over this + static Fl_Type *first, *last; // linked list of all objects + Fl_Type *next, *prev; // linked list of all objects + + Fl_Type *factory; + const char *callback_name(); + + int code_line, header_line; + int code_line_end, header_line_end; + +public: + + virtual ~Fl_Type(); + virtual Fl_Type *make() = 0; + + void add(Fl_Type *parent); // add as new child + void insert(Fl_Type *n); // insert into list before n + Fl_Type* remove(); // remove from list + void move_before(Fl_Type*); // move before a sibling + + virtual const char *title(); // string for browser + virtual const char *type_name() = 0; // type for code output + + const char *name() const {return name_;} + void name(const char *); + const char *label() const {return label_;} + void label(const char *); + const char *callback() const {return callback_;} + void callback(const char *); + const char *user_data() const {return user_data_;} + void user_data(const char *); + const char *user_data_type() const {return user_data_type_;} + void user_data_type(const char *); + + virtual Fl_Type* click_test(int,int); + virtual void add_child(Fl_Type*, Fl_Type* beforethis); + virtual void move_child(Fl_Type*, Fl_Type* beforethis); + virtual void remove_child(Fl_Type*); + + static Fl_Type *current; // most recently picked object + virtual void open(); // what happens when you double-click + + // read and write data to a saved file: + void write(); + virtual void write_properties(); + virtual void read_property(const char *); + virtual int read_fdesign(const char*, const char*); + + // write code, these are called in order: + virtual void write_static(); // write static stuff to .c file + virtual void write_code1(); // code and .h before children + virtual void write_code2(); // code and .h after children + + // live mode + virtual Fl_Widget *enter_live_mode(int top=0); // build wdgets needed for live mode + virtual void leave_live_mode(); // free allocated resources + virtual void copy_properties(); // copy properties from this type into a potetial live object + + // get message number for I18N + int msgnum(); + + // fake rtti: + virtual int is_parent() const; + virtual int is_widget() const; + virtual int is_button() const; + virtual int is_valuator() const; + virtual int is_menu_item() const; + virtual int is_menu_button() const; + virtual int is_group() const; + virtual int is_window() const; + virtual int is_code_block() const; + virtual int is_decl_block() const; + virtual int is_comment() const; + virtual int is_class() const; + virtual int is_public() const; + + virtual int pixmapID() { return 0; } + + const char* class_name(const int need_nest) const; + const class Fl_Class_Type* is_in_class() const; +}; + +class Fl_Function_Type : public Fl_Type { + const char* return_type; + char public_, cdecl_, constructor, havewidgets; +public: + Fl_Type *make(); + void write_code1(); + void write_code2(); + void open(); + int ismain() {return name_ == 0;} + virtual const char *type_name() {return "Function";} + virtual const char *title() { + return name() ? name() : "main()"; + } + int is_parent() const {return 1;} + int is_code_block() const {return 1;} + virtual int is_public() const; + int pixmapID() { return 7; } + void write_properties(); + void read_property(const char *); + int has_signature(const char *, const char*) const; +}; + +class Fl_Code_Type : public Fl_Type { +public: + Fl_Type *make(); + void write_code1(); + void write_code2(); + void open(); + virtual const char *type_name() {return "code";} + int is_code_block() const {return 0;} + int pixmapID() { return 8; } + virtual int is_public() const; +}; + +class Fl_CodeBlock_Type : public Fl_Type { + const char* after; +public: + Fl_Type *make(); + void write_code1(); + void write_code2(); + void open(); + virtual const char *type_name() {return "codeblock";} + int is_code_block() const {return 1;} + int is_parent() const {return 1;} + virtual int is_public() const; + int pixmapID() { return 9; } + void write_properties(); + void read_property(const char *); +}; + +class Fl_Decl_Type : public Fl_Type { + char public_; +public: + Fl_Type *make(); + void write_code1(); + void write_code2(); + void open(); + virtual const char *type_name() {return "decl";} + void write_properties(); + void read_property(const char *); + virtual int is_public() const; + int pixmapID() { return 10; } +}; + +class Fl_DeclBlock_Type : public Fl_Type { + const char* after; + char public_; +public: + Fl_Type *make(); + void write_code1(); + void write_code2(); + void open(); + virtual const char *type_name() {return "declblock";} + void write_properties(); + void read_property(const char *); + int is_parent() const {return 1;} + int is_decl_block() const {return 1;} + virtual int is_public() const; + int pixmapID() { return 11; } +}; + +class Fl_Comment_Type : public Fl_Type { + char in_c_, in_h_, style_; + char title_buf[64]; +public: + Fl_Type *make(); + void write_code1(); + void write_code2(); + void open(); + virtual const char *type_name() {return "comment";} + virtual const char *title(); // string for browser + void write_properties(); + void read_property(const char *); + virtual int is_public() const { return 1; } + virtual int is_comment() const { return 1; } + int pixmapID() { return 46; } +}; + +class Fl_Class_Type : public Fl_Type { + const char* subclass_of; + char public_; +public: + // state variables for output: + char write_public_state; // true when public: has been printed + Fl_Class_Type* parent_class; // save class if nested +// + Fl_Type *make(); + void write_code1(); + void write_code2(); + void open(); + virtual const char *type_name() {return "class";} + int is_parent() const {return 1;} + int is_decl_block() const {return 1;} + int is_class() const {return 1;} + virtual int is_public() const; + int pixmapID() { return 12; } + void write_properties(); + void read_property(const char *); + + // class prefix attribute access + void prefix(const char* p); + const char* prefix() const {return class_prefix;} + int has_function(const char*, const char*) const; +private: + const char* class_prefix; +}; + +#define NUM_EXTRA_CODE 4 + +class Fl_Widget_Type : public Fl_Type { + virtual Fl_Widget *widget(int,int,int,int) = 0; + virtual Fl_Widget_Type *_make() = 0; // virtual constructor + virtual void setlabel(const char *); + + const char *extra_code_[NUM_EXTRA_CODE]; + const char *subclass_; + const char *tooltip_; + const char *image_name_; + const char *inactive_name_; + uchar hotspot_; + +protected: + + void write_static(); + void write_code1(); + void write_widget_code(); + void write_extra_code(); + void write_block_close(); + void write_code2(); + void write_color(const char*, Fl_Color); + Fl_Widget *live_widget; + +public: + static int default_size; + + const char *xclass; // junk string, used for shortcut + Fl_Widget *o; + int public_; + + Fluid_Image *image; + void setimage(Fluid_Image *); + Fluid_Image *inactive; + void setinactive(Fluid_Image *); + + Fl_Widget_Type(); + Fl_Type *make(); + void open(); + + const char *extra_code(int n) const {return extra_code_[n];} + void extra_code(int n,const char *); + const char *subclass() const {return subclass_;} + void subclass(const char *); + const char *tooltip() const {return tooltip_;} + void tooltip(const char *); + const char *image_name() const {return image_name_;} + void image_name(const char *); + const char *inactive_name() const {return inactive_name_;} + void inactive_name(const char *); + uchar hotspot() const {return hotspot_;} + void hotspot(uchar v) {hotspot_ = v;} + uchar resizable() const; + void resizable(uchar v); + + virtual int textstuff(int what, Fl_Font &, int &, Fl_Color &); + virtual Fl_Menu_Item *subtypes(); + + virtual int is_widget() const; + virtual int is_public() const; + + virtual void write_properties(); + virtual void read_property(const char *); + virtual int read_fdesign(const char*, const char*); + + virtual Fl_Widget *enter_live_mode(int top=0); + virtual void leave_live_mode(); + virtual void copy_properties(); + + virtual void ideal_size(int &w, int &h); + virtual void ideal_spacing(int &x, int &y); + + ~Fl_Widget_Type(); + void redraw(); +}; + +#include <FL/Fl_Tabs.H> +#include <FL/Fl_Pack.H> +#include <FL/Fl_Wizard.H> + +class igroup : public Fl_Group { +public: + void resize(int,int,int,int); + void full_resize(int X, int Y, int W, int H) { Fl_Group::resize(X, Y, W, H); } + igroup(int X,int Y,int W,int H) : Fl_Group(X,Y,W,H) {Fl_Group::current(0);} +}; + +class itabs : public Fl_Tabs { +public: + void resize(int,int,int,int); + void full_resize(int X, int Y, int W, int H) { Fl_Group::resize(X, Y, W, H); } + itabs(int X,int Y,int W,int H) : Fl_Tabs(X,Y,W,H) {} +}; + +class iwizard : public Fl_Wizard { +public: + void resize(int,int,int,int); + void full_resize(int X, int Y, int W, int H) { Fl_Group::resize(X, Y, W, H); } + iwizard(int X,int Y,int W,int H) : Fl_Wizard(X,Y,W,H) {} +}; + +class Fl_Group_Type : public Fl_Widget_Type { +public: + virtual const char *type_name() {return "Fl_Group";} + Fl_Widget *widget(int X,int Y,int W,int H) { + igroup *g = new igroup(X,Y,W,H); Fl_Group::current(0); return g;} + Fl_Widget_Type *_make() {return new Fl_Group_Type();} + Fl_Type *make(); + void write_code1(); + void write_code2(); + void add_child(Fl_Type*, Fl_Type*); + void move_child(Fl_Type*, Fl_Type*); + void remove_child(Fl_Type*); + int is_parent() const {return 1;} + int is_group() const {return 1;} + int pixmapID() { return 6; } + + virtual Fl_Widget *enter_live_mode(int top=0); + virtual void leave_live_mode(); + virtual void copy_properties(); +}; + +extern const char pack_type_name[]; +extern Fl_Menu_Item pack_type_menu[]; + +class Fl_Pack_Type : public Fl_Group_Type { + Fl_Menu_Item *subtypes() {return pack_type_menu;} +public: + virtual const char *type_name() {return pack_type_name;} + Fl_Widget_Type *_make() {return new Fl_Pack_Type();} + int pixmapID() { return 22; } + void copy_properties(); +}; + +extern const char tabs_type_name[]; + +class Fl_Tabs_Type : public Fl_Group_Type { +public: + virtual void ideal_spacing(int &x, int &y) { + x = 10; + fl_font(o->labelfont(), o->labelsize()); + y = fl_height() + o->labelsize() - 6; + } + virtual const char *type_name() {return tabs_type_name;} + Fl_Widget *widget(int X,int Y,int W,int H) { + itabs *g = new itabs(X,Y,W,H); Fl_Group::current(0); return g;} + Fl_Widget_Type *_make() {return new Fl_Tabs_Type();} + Fl_Type* click_test(int,int); + void add_child(Fl_Type*, Fl_Type*); + void remove_child(Fl_Type*); + int pixmapID() { return 13; } + Fl_Widget *enter_live_mode(int top=0); +}; + +extern const char scroll_type_name[]; +extern Fl_Menu_Item scroll_type_menu[]; + +class Fl_Scroll_Type : public Fl_Group_Type { + Fl_Menu_Item *subtypes() {return scroll_type_menu;} +public: + virtual const char *type_name() {return scroll_type_name;} + Fl_Widget_Type *_make() {return new Fl_Scroll_Type();} + int pixmapID() { return 19; } + void copy_properties(); +}; + +extern const char tile_type_name[]; + +class Fl_Tile_Type : public Fl_Group_Type { +public: + virtual const char *type_name() {return tile_type_name;} + Fl_Widget_Type *_make() {return new Fl_Tile_Type();} + int pixmapID() { return 20; } + void copy_properties(); +}; + +extern const char wizard_type_name[]; + +class Fl_Wizard_Type : public Fl_Group_Type { +public: + virtual const char *type_name() {return wizard_type_name;} + Fl_Widget *widget(int X,int Y,int W,int H) { + iwizard *g = new iwizard(X,Y,W,H); Fl_Group::current(0); return g;} + Fl_Widget_Type *_make() {return new Fl_Wizard_Type();} + int pixmapID() { return 21; } +}; + +extern Fl_Menu_Item window_type_menu[]; + +class Fl_Window_Type : public Fl_Widget_Type { +protected: + + Fl_Menu_Item* subtypes() {return window_type_menu;} + + friend class Overlay_Window; + int mx,my; // mouse position during dragging + int x1,y1; // initial position of selection box + int bx,by,br,bt; // bounding box of selection before snapping + int sx,sy,sr,st; // bounding box of selection after snapping to guides + int dx,dy; + int drag; // which parts of bbox are being moved + int numselected; // number of children selected + enum {LEFT=1,RIGHT=2,BOTTOM=4,TOP=8,DRAG=16,BOX=32}; + void draw_overlay(); + void newdx(); + void newposition(Fl_Widget_Type *,int &x,int &y,int &w,int &h); + int handle(int); + virtual void setlabel(const char *); + void write_code1(); + void write_code2(); + Fl_Widget_Type *_make() {return 0;} // we don't call this + Fl_Widget *widget(int,int,int,int) {return 0;} + int recalc; // set by fix_overlay() + void moveallchildren(); + int pixmapID() { return 1; } + +public: + + Fl_Window_Type() { drag = dx = dy = 0; sr_min_w = sr_min_h = sr_max_w = sr_max_h = 0; } + uchar modal, non_modal; + + Fl_Type *make(); + virtual const char *type_name() {return "Fl_Window";} + + void open(); + + void fix_overlay(); // Update the bounding box, etc + uchar *read_image(int &ww, int &hh); // Read an image of the window + + virtual void write_properties(); + virtual void read_property(const char *); + virtual int read_fdesign(const char*, const char*); + + void add_child(Fl_Type*, Fl_Type*); + void move_child(Fl_Type*, Fl_Type*); + void remove_child(Fl_Type*); + + int is_parent() const {return 1;} + int is_group() const {return 1;} + int is_window() const {return 1;} + + Fl_Widget *enter_live_mode(int top=0); + void leave_live_mode(); + void copy_properties(); + + int sr_min_w, sr_min_h, sr_max_w, sr_max_h; +}; + +class Fl_Widget_Class_Type : private Fl_Window_Type { +public: + Fl_Widget_Class_Type() { + write_public_state = 0; + wc_relative = 0; + } + // state variables for output: + char write_public_state; // true when public: has been printed + char wc_relative; // if true, reposition all child widgets in an Fl_Group + + virtual void write_properties(); + virtual void read_property(const char *); + + void write_code1(); + void write_code2(); + Fl_Type *make(); + virtual const char *type_name() {return "widget_class";} + int pixmapID() { return 48; } + int is_parent() const {return 1;} + int is_decl_block() const {return 1;} + int is_class() const {return 1;} +}; + + +extern Fl_Menu_Item menu_item_type_menu[]; + +class Fl_Menu_Item_Type : public Fl_Widget_Type { +public: + Fl_Menu_Item* subtypes() {return menu_item_type_menu;} + const char* type_name() {return "MenuItem";} + Fl_Type* make(); + int is_menu_item() const {return 1;} + int is_button() const {return 1;} // this gets shortcut to work + Fl_Widget* widget(int,int,int,int) {return 0;} + Fl_Widget_Type* _make() {return 0;} + const char* menu_name(int& i); + int flags(); + void write_static(); + void write_item(); + void write_code1(); + void write_code2(); + int pixmapID() { return 16; } +}; + +class Fl_Submenu_Type : public Fl_Menu_Item_Type { +public: + Fl_Menu_Item* subtypes() {return 0;} + const char* type_name() {return "Submenu";} + int is_parent() const {return 1;} + int is_button() const {return 0;} // disable shortcut + Fl_Type* make(); + // changes to submenu must propagate up so build_menu is called + // on the parent Fl_Menu_Type: + void add_child(Fl_Type*a, Fl_Type*b) {parent->add_child(a,b);} + void move_child(Fl_Type*a, Fl_Type*b) {parent->move_child(a,b);} + void remove_child(Fl_Type*a) {parent->remove_child(a);} + int pixmapID() { return 18; } +}; + + +#include <FL/Fl_Menu_.H> +class Fl_Menu_Type : public Fl_Widget_Type { + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Menu_ *myo = (Fl_Menu_*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o); + switch (w) { + case 4: + case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; + case 1: myo->textfont(f); break; + case 2: myo->textsize(s); break; + case 3: myo->textcolor(c); break; + } + return 1; + } +public: + int is_menu_button() const {return 1;} + int is_parent() const {return 1;} + int menusize; + virtual void build_menu(); + Fl_Menu_Type() : Fl_Widget_Type() {menusize = 0;} + ~Fl_Menu_Type() { + if (menusize) delete[] (Fl_Menu_Item*)(((Fl_Menu_*)o)->menu()); + } + void add_child(Fl_Type*, Fl_Type*) {build_menu();} + void move_child(Fl_Type*, Fl_Type*) {build_menu();} + void remove_child(Fl_Type*) {build_menu();} + Fl_Type* click_test(int x, int y); + void write_code2(); + void copy_properties(); +}; + +extern Fl_Menu_Item button_type_menu[]; + +#include <FL/Fl_Menu_Button.H> +class Fl_Menu_Button_Type : public Fl_Menu_Type { + Fl_Menu_Item *subtypes() {return button_type_menu;} +public: + virtual void ideal_size(int &w, int &h) { + Fl_Widget_Type::ideal_size(w, h); + w += 2 * ((o->labelsize() - 3) & ~1) + o->labelsize() - 4; + h = (h / 5) * 5; + if (h < 15) h = 15; + if (w < (15 + h)) w = 15 + h; + } + virtual const char *type_name() {return "Fl_Menu_Button";} + Fl_Widget *widget(int X,int Y,int W,int H) { + return new Fl_Menu_Button(X,Y,W,H,"menu");} + Fl_Widget_Type *_make() {return new Fl_Menu_Button_Type();} + int pixmapID() { return 26; } +}; + +extern Fl_Menu_Item dummymenu[]; + +#include <FL/Fl_Choice.H> +class Fl_Choice_Type : public Fl_Menu_Type { +public: + virtual void ideal_size(int &w, int &h) { + Fl_Widget_Type::ideal_size(w, h); + int w1 = o->h() - Fl::box_dh(o->box()); + if (w1 > 20) w1 = 20; + w1 = (w1 - 4) / 3; + if (w1 < 1) w1 = 1; + w += 2 * w1 + o->labelsize() - 4; + h = (h / 5) * 5; + if (h < 15) h = 15; + if (w < (15 + h)) w = 15 + h; + } + virtual const char *type_name() {return "Fl_Choice";} + Fl_Widget *widget(int X,int Y,int W,int H) { + Fl_Choice *myo = new Fl_Choice(X,Y,W,H,"choice:"); + myo->menu(dummymenu); + return myo; + } + Fl_Widget_Type *_make() {return new Fl_Choice_Type();} + int pixmapID() { return 15; } +}; + +#include <FL/Fl_Input_Choice.H> +class Fl_Input_Choice_Type : public Fl_Menu_Type { + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Input_Choice *myo = (Fl_Input_Choice*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o); + switch (w) { + case 4: + case 0: f = (Fl_Font)myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; + case 1: myo->textfont(f); break; + case 2: myo->textsize(s); break; + case 3: myo->textcolor(c); break; + } + return 1; + } +public: + virtual void ideal_size(int &w, int &h) { + Fl_Input_Choice *myo = (Fl_Input_Choice *)o; + fl_font(myo->textfont(), myo->textsize()); + h = fl_height() + myo->textsize() - 6; + w = o->w() - 20 - Fl::box_dw(o->box()); + int ww = (int)fl_width('m'); + w = ((w + ww - 1) / ww) * ww + 20 + Fl::box_dw(o->box()); + if (h < 15) h = 15; + if (w < (15 + h)) w = 15 + h; + } + virtual const char *type_name() {return "Fl_Input_Choice";} + virtual Fl_Type* click_test(int,int); + Fl_Widget *widget(int X,int Y,int W,int H) { + Fl_Input_Choice *myo = new Fl_Input_Choice(X,Y,W,H,"input choice:"); + myo->menu(dummymenu); + myo->value("input"); + return myo; + } + Fl_Widget_Type *_make() {return new Fl_Input_Choice_Type();} + virtual void build_menu(); + int pixmapID() { return 15; } + void copy_properties(); +}; + +#include <FL/Fl_Window.H> +#include <FL/Fl_Menu_Bar.H> +class Fl_Menu_Bar_Type : public Fl_Menu_Type { +public: + virtual void ideal_size(int &w, int &h) { + w = o->window()->w(); + h = ((o->labelsize() + Fl::box_dh(o->box()) + 4) / 5) * 5; + if (h < 15) h = 15; + } + virtual const char *type_name() {return "Fl_Menu_Bar";} + Fl_Widget *widget(int X,int Y,int W,int H) {return new Fl_Menu_Bar(X,Y,W,H);} + Fl_Widget_Type *_make() {return new Fl_Menu_Bar_Type();} + int pixmapID() { return 17; } +}; +// object list operations: +Fl_Widget *make_widget_browser(int X,int Y,int W,int H); +extern int modflag; +void delete_all(int selected_only=0); +void selection_changed(Fl_Type* new_current); + +// file operations: +# ifdef __GNUC__ +# define __fl_attr(x) __attribute__ (x) +# else +# define __fl_attr(x) +# endif // __GNUC__ + +void write_word(const char *); +void write_string(const char *,...) __fl_attr((__format__ (__printf__, 1, 2))); +int write_file(const char *, int selected_only = 0); +int write_code(const char *cfile, const char *hfile); +int write_strings(const char *sfile); + +int write_declare(const char *, ...) __fl_attr((__format__ (__printf__, 1, 2))); +int is_id(char); +const char* unique_id(void* o, const char*, const char*, const char*); +void write_c(const char*, ...) __fl_attr((__format__ (__printf__, 1, 2))); +void write_h(const char*, ...) __fl_attr((__format__ (__printf__, 1, 2))); +void write_cstring(const char *); +void write_cstring(const char *,int length); +void write_cdata(const char *,int length); +void write_indent(int n); +void write_open(int); +void write_close(int n); +extern int write_number; +extern int write_sourceview; +void write_public(int state); // writes pubic:/private: as needed +extern int indentation; +extern const char* indent(); + +int read_file(const char *, int merge); +const char *read_word(int wantbrace = 0); +void read_error(const char *format, ...); + +// check legality of c code (sort of) and return error: +const char *c_check(const char *c, int type = 0); + +// replace a string pointer with new value, strips leading/trailing blanks: +int storestring(const char *n, const char * & p, int nostrip=0); + +extern int include_H_from_C; + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/Fl_Widget_Type.cxx b/Utilities/FLTK/fluid/Fl_Widget_Type.cxx new file mode 100644 index 0000000000..3cd8e1a342 --- /dev/null +++ b/Utilities/FLTK/fluid/Fl_Widget_Type.cxx @@ -0,0 +1,2537 @@ +// +// "$Id$" +// +// Widget type code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Group.H> +#include <FL/Fl_Input.H> +#include "Fl_Widget_Type.h" +#include "alignment_panel.h" +#include <FL/fl_message.H> +#include <FL/Fl_Slider.H> +#include <FL/Fl_Window.H> +#include "../src/flstring.h" +#include <stdio.h> +#include <stdlib.h> + +// Make an Fl_Widget_Type subclass instance. +// It figures out the automatic size and parent of the new widget, +// creates the Fl_Widget (by calling the virtual function _make), +// adds it to the Fl_Widget hierarchy, creates a new Fl_Type +// instance, sets the widget pointers, and makes all the display +// update correctly... + +extern int reading_file; +int force_parent; +extern int gridx; +extern int gridy; +extern int i18n_type; +extern const char* i18n_include; +extern const char* i18n_function; +extern const char* i18n_file; +extern const char* i18n_set; + +int Fl_Widget_Type::default_size = FL_NORMAL_SIZE; + +int Fl_Widget_Type::is_widget() const {return 1;} +int Fl_Widget_Type::is_public() const {return public_;} + +const char* subclassname(Fl_Type* l) { + if (l->is_widget()) { + Fl_Widget_Type* p = (Fl_Widget_Type*)l; + const char* c = p->subclass(); + if (c) return c; + if (l->is_class()) return "Fl_Group"; + if (p->o->type() == FL_WINDOW+1) return "Fl_Double_Window"; + } + return l->type_name(); +} + +// Return the ideal widget size... +void +Fl_Widget_Type::ideal_size(int &w, int &h) { + h = o->labelsize(); + o->measure_label(w, h); + + w += Fl::box_dw(o->box()); + h += Fl::box_dh(o->box()); + + if (w < 15) w = 15; + if (h < 15) h = 15; +} + +// Return the ideal widget spacing... +void +Fl_Widget_Type::ideal_spacing(int &x, int &y) { + if (o->labelsize() < 10) + x = y = 0; + else if (o->labelsize() < 14) + x = y = 5; + else + x = y = 10; +} + +Fl_Type *Fl_Widget_Type::make() { + // Find the current widget, or widget to copy: + Fl_Type *qq = Fl_Type::current; + while (qq && (!qq->is_widget() || qq->is_menu_item())) qq = qq->parent; + if (!qq) { + fl_message("Please select a widget"); + return 0; + } + Fl_Widget_Type* q = (Fl_Widget_Type*)qq; + // find the parent widget: + Fl_Widget_Type* p = q; + if ((force_parent || !p->is_group()) && p->parent->is_widget()) + p = (Fl_Widget_Type*)(p->parent); + force_parent = 0; + + // Figure out a border between widget and window: + int B = p->o->w()/2; if (p->o->h()/2 < B) B = p->o->h()/2; if (B>25) B = 25; + + int ULX,ULY; // parent's origin in window + if (!p->is_window()) { // if it is a group, add corner + ULX = p->o->x(); ULY = p->o->y(); + } else { + ULX = ULY = 0; + } + + // Figure out a position and size for the widget + int X,Y,W,H; + if (is_group()) { // fill the parent with the widget + X = ULX+B; + W = p->o->w()-B; + Y = ULY+B; + H = p->o->h()-B; + } else if (q != p) { // copy position and size of current widget + W = q->o->w(); + H = q->o->h(); + X = q->o->x()+W; + Y = q->o->y(); + if (X+W > ULX+p->o->w()) { + X = q->o->x(); + Y = q->o->y()+H; + if (Y+H > ULY+p->o->h()) Y = ULY+B; + } + } else { // just make it small and square... + X = ULX+B; + Y = ULY+B; + W = H = B; + } + + // satisfy the grid requirements (otherwise it edits really strangely): + if (gridx>1) { + X = (X/gridx)*gridx; + W = ((W-1)/gridx+1)*gridx; + } + if (gridy>1) { + Y = (Y/gridy)*gridy; + H = ((H-1)/gridy+1)*gridy; + } + + // Construct the Fl_Type: + Fl_Widget_Type *t = _make(); + if (!o) o = widget(0,0,100,100); // create template widget + t->factory = this; + // Construct the Fl_Widget: + t->o = widget(X,Y,W,H); + if (reading_file) t->o->label(0); + else if (t->o->label()) t->label(t->o->label()); // allow editing + t->o->user_data((void*)t); + // Put it in the parent: + // ((Fl_Group *)(p->o))->add(t->o); (done by Fl_Type::add()) + // add to browser: + t->add(p); + t->redraw(); + return t; +} + +#include "Fluid_Image.h" + +void Fl_Widget_Type::setimage(Fluid_Image *i) { + if (i == image || is_window()) return; + if (image) image->decrement(); + if (i) i->increment(); + image = i; + if (i) i->image(o); + else o->image(0); + redraw(); +} + +void Fl_Widget_Type::setinactive(Fluid_Image *i) { + if (i == inactive || is_window()) return; + if (inactive) inactive->decrement(); + if (i) i->increment(); + inactive = i; + if (i) i->deimage(o); + else o->deimage(0); + redraw(); +} + +void Fl_Widget_Type::setlabel(const char *n) { + o->label(n); + redraw(); +} + +Fl_Widget_Type::Fl_Widget_Type() { + for (int n=0; n<NUM_EXTRA_CODE; n++) {extra_code_[n] = 0; subclass_ = 0;} + hotspot_ = 0; + tooltip_ = 0; + image_name_ = 0; + inactive_name_ = 0; + image = 0; + inactive = 0; + xclass = 0; + o = 0; + public_ = 1; +} + +Fl_Widget_Type::~Fl_Widget_Type() { + if (o) { + o->hide(); + if (o->parent()) ((Fl_Group*)o->parent())->remove(*o); + delete o; + } +} + +void Fl_Widget_Type::extra_code(int m,const char *n) { + storestring(n,extra_code_[m]); +} + +extern void redraw_browser(); +void Fl_Widget_Type::subclass(const char *n) { + if (storestring(n,subclass_) && visible) + redraw_browser(); +} + +void Fl_Widget_Type::tooltip(const char *n) { + storestring(n,tooltip_); + o->tooltip(n); +} + +void Fl_Widget_Type::image_name(const char *n) { + setimage(Fluid_Image::find(n)); + storestring(n,image_name_); +} + +void Fl_Widget_Type::inactive_name(const char *n) { + setinactive(Fluid_Image::find(n)); + storestring(n,inactive_name_); +} + +void Fl_Widget_Type::redraw() { + Fl_Type *t = this; + if (is_menu_item()) { + // find the menu button that parents this menu: + do t = t->parent; while (t && t->is_menu_item()); + // kludge to cause build_menu to be called again: + t->add_child(0,0); + } else { + while (t->parent && t->parent->is_widget()) t = t->parent; + ((Fl_Widget_Type*)t)->o->redraw(); + } +} + +// the recursive part sorts all children, returns pointer to next: +Fl_Type *sort(Fl_Type *parent) { + Fl_Type *f,*n=0; + for (f = parent ? parent->next : Fl_Type::first; ; f = n) { + if (!f || parent && f->level <= parent->level) return f; + n = sort(f); + if (!f->selected || (!f->is_widget() || f->is_menu_item())) continue; + Fl_Widget* fw = ((Fl_Widget_Type*)f)->o; + Fl_Type *g; // we will insert before this + for (g = parent->next; g != f; g = g->next) { + if (!g->selected || g->level > f->level) continue; + Fl_Widget* gw = ((Fl_Widget_Type*)g)->o; + if (gw->y() > fw->y()) break; + if (gw->y() == fw->y() && gw->x() > fw->x()) break; + } + if (g != f) f->move_before(g); + } +} + +//////////////////////////////////////////////////////////////// +// The control panels! + +#include "widget_panel.h" +#include <FL/fl_show_colormap.H> + +static Fl_Window *the_panel; + +// All the callbacks use the argument to indicate whether to load or store. +// This avoids the need for pointers to all the widgets, and keeps the +// code localized in the callbacks. +// A value of LOAD means to load. The hope is that this will not collide +// with any actual useful values for the argument. I also use this to +// initialized parts of the widget that are nyi by fluid. + +Fl_Widget_Type *current_widget; // one of the selected ones +static int numselected; // number selected +static int haderror; + +void name_cb(Fl_Input* o, void *v) { + if (v == LOAD) { + static char buf[1024]; + if (numselected != 1) { + snprintf(buf, sizeof(buf), "Widget Properties (%d widgets)", numselected); + o->hide(); + } else { + o->static_value(current_widget->name()); + o->show(); + snprintf(buf, sizeof(buf), "%s Properties", current_widget->title()); + } + + the_panel->label(buf); + } else { + if (numselected == 1) { + current_widget->name(o->value()); + // I don't update window title, as it probably is being closed + // and wm2 (a window manager) barfs if you retitle and then + // hide a window: + // ((Fl_Window*)(o->parent()->parent()->parent()))->label(current_widget->title()); + } + } +} + +void name_public_cb(Fl_Light_Button* i, void* v) { + if (v == LOAD) { + i->value(current_widget->public_); + } else { + int mod = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + ((Fl_Widget_Type*)o)->public_ = i->value(); + mod = 1; + } + } + if (mod) { + set_modflag(1); + redraw_browser(); + } + } +} + +static char* oldlabel; +static unsigned oldlabellen; + +void label_cb(Fl_Input* i, void *v) { + if (v == LOAD) { + i->static_value(current_widget->label()); + if (strlen(i->value()) >= oldlabellen) { + oldlabellen = strlen(i->value())+128; + oldlabel = (char*)realloc(oldlabel,oldlabellen); + } + strcpy(oldlabel,i->value()); + } else { + int mod = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + o->label(i->value()); + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +static Fl_Input *image_input; + +void image_cb(Fl_Input* i, void *v) { + if (v == LOAD) { + image_input = i; + if (current_widget->is_widget() && !current_widget->is_window()) { + i->activate(); + i->static_value(((Fl_Widget_Type*)current_widget)->image_name()); + } else i->deactivate(); + } else { + int mod = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + ((Fl_Widget_Type*)o)->image_name(i->value()); + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +void image_browse_cb(Fl_Button* b, void *v) { + if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_window()) + b->activate(); + else + b->deactivate(); + } else { + int mod = 0; + if (ui_find_image(image_input->value())) { + image_input->value(ui_find_image_name); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + ((Fl_Widget_Type*)o)->image_name(ui_find_image_name); + mod = 1; + } + } + if (mod) set_modflag(1); + } + } +} + +static Fl_Input *inactive_input; + +void inactive_cb(Fl_Input* i, void *v) { + if (v == LOAD) { + inactive_input = i; + if (current_widget->is_widget() && !current_widget->is_window()) { + i->activate(); + i->static_value(((Fl_Widget_Type*)current_widget)->inactive_name()); + } else i->deactivate(); + } else { + int mod = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + ((Fl_Widget_Type*)o)->inactive_name(i->value()); + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +void inactive_browse_cb(Fl_Button* b, void *v) { + if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_window()) + b->activate(); + else + b->deactivate(); + } else { + int mod = 0; + if (ui_find_image(inactive_input->value())) { + inactive_input->value(ui_find_image_name); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + ((Fl_Widget_Type*)o)->inactive_name(ui_find_image_name); + mod = 1; + } + } + if (mod) set_modflag(1); + } + } +} + +void tooltip_cb(Fl_Input* i, void *v) { + if (v == LOAD) { + if (current_widget->is_widget()) { + i->activate(); + i->static_value(((Fl_Widget_Type*)current_widget)->tooltip()); + } else i->deactivate(); + } else { + int mod = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + ((Fl_Widget_Type*)o)->tooltip(i->value()); + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +Fl_Value_Input *x_input, *y_input, *w_input, *h_input; + +void x_cb(Fl_Value_Input *i, void *v) { + if (v == LOAD) { + x_input = i; + if (current_widget->is_widget()) { + i->value(((Fl_Widget_Type *)current_widget)->o->x()); + x_input->activate(); + } else x_input->deactivate(); + } else { + int mod = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + w->resize((int)i->value(), w->y(), w->w(), w->h()); + if (w->window()) w->window()->redraw(); + if (o->is_window()) { + ((Fl_Window *)w)->size_range(gridx, gridy, Fl::w(), Fl::h(), + gridx, gridy, 0); + } + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +void y_cb(Fl_Value_Input *i, void *v) { + if (v == LOAD) { + y_input = i; + if (current_widget->is_widget()) { + i->value(((Fl_Widget_Type *)current_widget)->o->y()); + y_input->activate(); + } else y_input->deactivate(); + } else { + int mod = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + w->resize(w->x(), (int)i->value(), w->w(), w->h()); + if (w->window()) w->window()->redraw(); + if (o->is_window()) { + ((Fl_Window *)w)->size_range(gridx, gridy, Fl::w(), Fl::h(), + gridx, gridy, 0); + } + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +void w_cb(Fl_Value_Input *i, void *v) { + if (v == LOAD) { + w_input = i; + if (current_widget->is_widget()) { + i->value(((Fl_Widget_Type *)current_widget)->o->w()); + w_input->activate(); + } else w_input->deactivate(); + } else { + int mod = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + w->resize(w->x(), w->y(), (int)i->value(), w->h()); + if (w->window()) w->window()->redraw(); + if (o->is_window()) { + ((Fl_Window *)w)->size_range(gridx, gridy, Fl::w(), Fl::h(), + gridx, gridy, 0); + } + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +void h_cb(Fl_Value_Input *i, void *v) { + if (v == LOAD) { + h_input = i; + if (current_widget->is_widget()) { + i->value(((Fl_Widget_Type *)current_widget)->o->h()); + h_input->activate(); + } else h_input->deactivate(); + } else { + int mod = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + w->resize(w->x(), w->y(), w->w(), (int)i->value()); + if (w->window()) w->window()->redraw(); + if (o->is_window()) { + ((Fl_Window *)w)->size_range(gridx, gridy, Fl::w(), Fl::h(), + gridx, gridy, 0); + } + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +void wc_relative_cb(Fl_Light_Button *i, void *v) { + if (v == LOAD) { + if (!strcmp(current_widget->type_name(), "widget_class")) { + i->show(); + i->value(((Fl_Widget_Class_Type *)current_widget)->wc_relative); + } else { + i->hide(); + } + } else { + int mod = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && !strcmp(current_widget->type_name(), "widget_class")) { + Fl_Widget_Class_Type *t = (Fl_Widget_Class_Type *)o; + t->wc_relative = i->value(); + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +//////////////////////////////////////////////////////////////// + +// turn number to string or string to number for saving to file: +// does not work for hierarchial menus! + +const char *item_name(Fl_Menu_Item* m, int i) { + if (m) { + while (m->label()) { + if (m->argument() == i) return m->label(); + m++; + } + } + static char buffer[20]; + sprintf(buffer, "%d", i); + return buffer; +} +int item_number(Fl_Menu_Item* m, const char* i) { + if (m && i) { + if (i[0]=='F' && i[1]=='L' && i[2]=='_') i += 3; + while (m->label()) { + if (!strcmp(m->label(), i)) return int(m->argument()); + m++; + } + } + return atoi(i); +} + +#define ZERO_ENTRY 1000 + +Fl_Menu_Item boxmenu[] = { +{"NO_BOX",0,0,(void *)ZERO_ENTRY}, +{"boxes",0,0,0,FL_SUBMENU}, +{"UP_BOX",0,0,(void *)FL_UP_BOX}, +{"DOWN_BOX",0,0,(void *)FL_DOWN_BOX}, +{"FLAT_BOX",0,0,(void *)FL_FLAT_BOX}, +{"BORDER_BOX",0,0,(void *)FL_BORDER_BOX}, +{"THIN_UP_BOX",0,0,(void *)FL_THIN_UP_BOX}, +{"THIN_DOWN_BOX",0,0,(void *)FL_THIN_DOWN_BOX}, +{"ENGRAVED_BOX",0,0,(void *)FL_ENGRAVED_BOX}, +{"EMBOSSED_BOX",0,0,(void *)FL_EMBOSSED_BOX}, +{"ROUND_UP_BOX",0,0,(void *)FL_ROUND_UP_BOX}, +{"ROUND_DOWN_BOX",0,0,(void *)FL_ROUND_DOWN_BOX}, +{"DIAMOND_UP_BOX",0,0,(void *)FL_DIAMOND_UP_BOX}, +{"DIAMOND_DOWN_BOX",0,0,(void *)FL_DIAMOND_DOWN_BOX}, +{"SHADOW_BOX",0,0,(void *)FL_SHADOW_BOX}, +{"ROUNDED_BOX",0,0,(void *)FL_ROUNDED_BOX}, +{"RSHADOW_BOX",0,0,(void *)FL_RSHADOW_BOX}, +{"RFLAT_BOX",0,0,(void *)FL_RFLAT_BOX}, +{"OVAL_BOX",0,0,(void *)FL_OVAL_BOX}, +{"OSHADOW_BOX",0,0,(void *)FL_OSHADOW_BOX}, +{"OFLAT_BOX",0,0,(void *)FL_OFLAT_BOX}, +{"PLASTIC_UP_BOX",0,0,(void *)FL_PLASTIC_UP_BOX}, +{"PLASTIC_DOWN_BOX",0,0,(void *)FL_PLASTIC_DOWN_BOX}, +{"PLASTIC_THIN_UP_BOX",0,0,(void *)FL_PLASTIC_THIN_UP_BOX}, +{"PLASTIC_THIN_DOWN_BOX",0,0,(void *)FL_PLASTIC_THIN_DOWN_BOX}, +{0}, +{"frames",0,0,0,FL_SUBMENU}, +{"UP_FRAME",0,0,(void *)FL_UP_FRAME}, +{"DOWN_FRAME",0,0,(void *)FL_DOWN_FRAME}, +{"THIN_UP_FRAME",0,0,(void *)FL_THIN_UP_FRAME}, +{"THIN_DOWN_FRAME",0,0,(void *)FL_THIN_DOWN_FRAME}, +{"ENGRAVED_FRAME",0,0,(void *)FL_ENGRAVED_FRAME}, +{"EMBOSSED_FRAME",0,0,(void *)FL_EMBOSSED_FRAME}, +{"BORDER_FRAME",0,0,(void *)FL_BORDER_FRAME}, +{"SHADOW_FRAME",0,0,(void *)FL_SHADOW_FRAME}, +{"ROUNDED_FRAME",0,0,(void *)FL_ROUNDED_FRAME}, +{"OVAL_FRAME",0,0,(void *)FL_OVAL_FRAME}, +{"PLASTIC_UP_FRAME",0,0,(void *)FL_PLASTIC_UP_FRAME}, +{"PLASTIC_DOWN_FRAME",0,0,(void *)FL_PLASTIC_DOWN_FRAME}, +{0}, +{0}}; + +const char *boxname(int i) { + if (!i) i = ZERO_ENTRY; + for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) + if (boxmenu[j].argument() == i) return boxmenu[j].label(); + return 0; +} + +int boxnumber(const char *i) { + if (i[0]=='F' && i[1]=='L' && i[2]=='_') i += 3; + for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) + if (boxmenu[j].label() && !strcmp(boxmenu[j].label(), i)) { + return int(boxmenu[j].argument()); + } + return 0; +} + +void box_cb(Fl_Choice* i, void *v) { + if (v == LOAD) { + if (current_widget->is_menu_item()) {i->deactivate(); return;} else i->activate(); + int n = current_widget->o->box(); if (!n) n = ZERO_ENTRY; + for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) + if (boxmenu[j].argument() == n) {i->value(j); break;} + } else { + int mod = 0; + int m = i->value(); + int n = int(boxmenu[m].argument()); + if (!n) return; // should not happen + if (n == ZERO_ENTRY) n = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->o->box((Fl_Boxtype)n); + q->redraw(); + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +void down_box_cb(Fl_Choice* i, void *v) { + if (v == LOAD) { + int n; + if (current_widget->is_button() && !current_widget->is_menu_item()) + n = ((Fl_Button*)(current_widget->o))->down_box(); + else if (!strcmp(current_widget->type_name(), "Fl_Input_Choice")) + n = ((Fl_Input_Choice*)(current_widget->o))->down_box(); + else if (current_widget->is_menu_button()) + n = ((Fl_Menu_*)(current_widget->o))->down_box(); + else { + i->deactivate(); return; + } + i->activate(); + if (!n) n = ZERO_ENTRY; + for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) + if (boxmenu[j].argument() == n) {i->value(j); break;} + } else { + int mod = 0; + int m = i->value(); + int n = int(boxmenu[m].argument()); + if (!n) return; // should not happen + if (n == ZERO_ENTRY) n = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected) { + if (o->is_button() && !o->is_menu_item()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + ((Fl_Button*)(q->o))->down_box((Fl_Boxtype)n); + if (((Fl_Button*)(q->o))->value()) q->redraw(); + } else if (!strcmp(o->type_name(), "Fl_Input_Choice")) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + ((Fl_Input_Choice*)(q->o))->down_box((Fl_Boxtype)n); + } else if (o->is_menu_button()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + ((Fl_Menu_*)(q->o))->down_box((Fl_Boxtype)n); + } + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +//////////////////////////////////////////////////////////////// + +Fl_Menu_Item whenmenu[] = { + {"Never",0,0,(void*)ZERO_ENTRY}, + {"Release",0,0,(void*)FL_WHEN_RELEASE}, + {"Changed",0,0,(void*)FL_WHEN_CHANGED}, + {"Enter key",0,0,(void*)FL_WHEN_ENTER_KEY}, + //{"Release or Enter",0,0,(void*)(FL_WHEN_ENTER_KEY|FL_WHEN_RELEASE)}, + {0}}; + +static Fl_Menu_Item whensymbolmenu[] = { + {"FL_WHEN_NEVER",0,0,(void*)(FL_WHEN_NEVER)}, + {"FL_WHEN_CHANGED",0,0,(void*)(FL_WHEN_CHANGED)}, + {"FL_WHEN_RELEASE",0,0,(void*)(FL_WHEN_RELEASE)}, + {"FL_WHEN_RELEASE_ALWAYS",0,0,(void*)(FL_WHEN_RELEASE_ALWAYS)}, + {"FL_WHEN_ENTER_KEY",0,0,(void*)(FL_WHEN_ENTER_KEY)}, + {"FL_WHEN_ENTER_KEY_ALWAYS",0,0,(void*)(FL_WHEN_ENTER_KEY_ALWAYS)}, + {0}}; + +void when_cb(Fl_Choice* i, void *v) { + if (v == LOAD) { + if (current_widget->is_menu_item()) {i->deactivate(); return;} else i->activate(); + int n = current_widget->o->when() & (~FL_WHEN_NOT_CHANGED); + if (!n) n = ZERO_ENTRY; + for (int j = 0; j < int(sizeof(whenmenu)/sizeof(*whenmenu)); j++) + if (whenmenu[j].argument() == n) {i->value(j); break;} + } else { + int mod = 0; + int m = i->value(); + int n = int(whenmenu[m].argument()); + if (!n) return; // should not happen + if (n == ZERO_ENTRY) n = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->o->when(n|(q->o->when()&FL_WHEN_NOT_CHANGED)); + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +void when_button_cb(Fl_Light_Button* i, void *v) { + if (v == LOAD) { + if (current_widget->is_menu_item()) {i->deactivate(); return;} else i->activate(); + i->value(current_widget->o->when()&FL_WHEN_NOT_CHANGED); + } else { + int mod = 0; + int n = i->value() ? FL_WHEN_NOT_CHANGED : 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->o->when(n|(q->o->when()&~FL_WHEN_NOT_CHANGED)); + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +uchar Fl_Widget_Type::resizable() const { + if (is_window()) return ((Fl_Window*)o)->resizable() != 0; + Fl_Group* p = (Fl_Group*)o->parent(); + if (p) return p->resizable() == o; + else return 0; +} + +void Fl_Widget_Type::resizable(uchar v) { + if (v) { + if (resizable()) return; + if (is_window()) ((Fl_Window*)o)->resizable(o); + else { + Fl_Group* p = (Fl_Group*)o->parent(); + if (p) p->resizable(o); + } + } else { + if (!resizable()) return; + if (is_window()) { + ((Fl_Window*)o)->resizable(0); + } else { + Fl_Group* p = (Fl_Group*)o->parent(); + if (p) p->resizable(0); + } + } +} + +void resizable_cb(Fl_Light_Button* i,void* v) { + if (v == LOAD) { + if (current_widget->is_menu_item()) {i->deactivate(); return;} + if (numselected > 1) {i->deactivate(); return;} + i->activate(); + i->value(current_widget->resizable()); + } else { + current_widget->resizable(i->value()); + set_modflag(1); + } +} + +void hotspot_cb(Fl_Light_Button* i,void* v) { + if (v == LOAD) { + if (numselected > 1) {i->deactivate(); return;} + if (current_widget->is_menu_item()) i->label("divider"); + else i->label("hotspot"); + i->activate(); + i->value(current_widget->hotspot()); + } else { + current_widget->hotspot(i->value()); + if (current_widget->is_menu_item()) {current_widget->redraw(); return;} + if (i->value()) { + Fl_Type *p = current_widget->parent; + if (!p || !p->is_widget()) return; + while (!p->is_window()) p = p->parent; + for (Fl_Type *o = p->next; o && o->level > p->level; o = o->next) { + if (o->is_widget() && o != current_widget) + ((Fl_Widget_Type*)o)->hotspot(0); + } + } + set_modflag(1); + } +} + +void visible_cb(Fl_Light_Button* i, void* v) { + if (v == LOAD) { + i->value(current_widget->o->visible()); + if (current_widget->is_window()) i->deactivate(); + else i->activate(); + } else { + int mod = 0; + int n = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + n ? q->o->show() : q->o->hide(); + q->redraw(); + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +void active_cb(Fl_Light_Button* i, void* v) { + if (v == LOAD) { + i->value(current_widget->o->active()); + if (current_widget->is_window()) i->deactivate(); + else i->activate(); + } else { + int mod = 0; + int n = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + n ? q->o->activate() : q->o->deactivate(); + q->redraw(); + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +//////////////////////////////////////////////////////////////// + +Fl_Menu_Item fontmenu[] = { +{"Helvetica"}, +{"Helvetica bold"}, +{"Helvetica italic"}, +{"Helvetica bold italic"}, +{"Courier"}, +{"Courier bold"}, +{"Courier italic"}, +{"Courier bold italic"}, +{"Times"}, +{"Times bold"}, +{"Times italic"}, +{"Times bold italic"}, +{"Symbol"}, +{"Terminal"}, +{"Terminal Bold"}, +{"Zapf Dingbats"}, +{0}}; + +void labelfont_cb(Fl_Choice* i, void *v) { + if (v == LOAD) { + int n = current_widget->o->labelfont(); + if (n > 15) n = 0; + i->value(n); + } else { + int mod = 0; + int n = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->o->labelfont(n); + q->redraw(); + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +void labelsize_cb(Fl_Value_Input* i, void *v) { + int n; + if (v == LOAD) { + n = current_widget->o->labelsize(); + } else { + int mod = 0; + n = int(i->value()); + if (n <= 0) n = Fl_Widget_Type::default_size; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->o->labelsize(n); + q->redraw(); + mod = 1; + } + } + if (mod) set_modflag(1); + } + i->value(n); +} + +extern const char *ui_find_image_name; + +Fl_Menu_Item labeltypemenu[] = { + {"NORMAL_LABEL",0,0,(void*)0}, + {"SHADOW_LABEL",0,0,(void*)FL_SHADOW_LABEL}, + {"ENGRAVED_LABEL",0,0,(void*)FL_ENGRAVED_LABEL}, + {"EMBOSSED_LABEL",0,0,(void*)FL_EMBOSSED_LABEL}, + {"NO_LABEL",0,0,(void*)(FL_NO_LABEL)}, +{0}}; + +void labeltype_cb(Fl_Choice* i, void *v) { + if (v == LOAD) { + int n; + n = current_widget->o->labeltype(); + i->when(FL_WHEN_RELEASE); + for (int j = 0; j < int(sizeof(labeltypemenu)/sizeof(*labeltypemenu)); j++) + if (labeltypemenu[j].argument() == n) {i->value(j); break;} + } else { + int mod = 0; + int m = i->value(); + int n = int(labeltypemenu[m].argument()); + if (n<0) return; // should not happen + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* p = (Fl_Widget_Type*)o; + p->o->labeltype((Fl_Labeltype)n); + p->redraw(); + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +//////////////////////////////////////////////////////////////// + +void color_cb(Fl_Button* i, void *v) { + Fl_Color c = current_widget->o->color(); + if (v == LOAD) { + if (current_widget->is_menu_item()) {i->deactivate(); return;} else i->activate(); + } else { + int mod = 0; + Fl_Color d = fl_show_colormap(c); + if (d == c) return; + c = d; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->o->color(c); q->o->redraw(); + if (q->parent && q->parent->type_name() == tabs_type_name) { + if (q->o->parent()) q->o->parent()->redraw(); + } + mod = 1; + } + } + if (mod) set_modflag(1); + } + i->color(c); i->labelcolor(fl_contrast(FL_BLACK,c)); i->redraw(); +} + +void color2_cb(Fl_Button* i, void *v) { + Fl_Color c = current_widget->o->selection_color(); + if (v == LOAD) { + if (current_widget->is_menu_item()) {i->deactivate(); return;} else i->activate(); + } else { + int mod = 0; + Fl_Color d = fl_show_colormap(c); + if (d == c) return; + c = d; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->o->selection_color(c); q->o->redraw(); + mod = 1; + } + } + if (mod) set_modflag(1); + } + i->color(c); i->labelcolor(fl_contrast(FL_BLACK,c)); i->redraw(); +} + +void labelcolor_cb(Fl_Button* i, void *v) { + Fl_Color c = current_widget->o->labelcolor(); + if (v != LOAD) { + int mod = 0; + Fl_Color d = fl_show_colormap(c); + if (d == c) return; + c = d; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->o->labelcolor(c); q->redraw(); + mod = 1; + } + } + if (mod) set_modflag(1); + } + i->color(c); i->labelcolor(fl_contrast(FL_BLACK,c)); i->redraw(); +} + +static Fl_Button* relative(Fl_Widget* o, int i) { + Fl_Group* g = (Fl_Group*)(o->parent()); + return (Fl_Button*)(g->child(g->find(*o)+i)); +} + +static Fl_Menu_Item alignmenu[] = { + {"FL_ALIGN_CENTER",0,0,(void*)(FL_ALIGN_CENTER)}, + {"FL_ALIGN_TOP",0,0,(void*)(FL_ALIGN_TOP)}, + {"FL_ALIGN_BOTTOM",0,0,(void*)(FL_ALIGN_BOTTOM)}, + {"FL_ALIGN_LEFT",0,0,(void*)(FL_ALIGN_LEFT)}, + {"FL_ALIGN_RIGHT",0,0,(void*)(FL_ALIGN_RIGHT)}, + {"FL_ALIGN_INSIDE",0,0,(void*)(FL_ALIGN_INSIDE)}, + {"FL_ALIGN_CLIP",0,0,(void*)(FL_ALIGN_CLIP)}, + {"FL_ALIGN_WRAP",0,0,(void*)(FL_ALIGN_WRAP)}, + {"FL_ALIGN_TEXT_OVER_IMAGE",0,0,(void*)(FL_ALIGN_TEXT_OVER_IMAGE)}, + {"FL_ALIGN_TOP_LEFT",0,0,(void*)(FL_ALIGN_TOP_LEFT)}, + {"FL_ALIGN_TOP_RIGHT",0,0,(void*)(FL_ALIGN_TOP_RIGHT)}, + {"FL_ALIGN_BOTTOM_LEFT",0,0,(void*)(FL_ALIGN_BOTTOM_LEFT)}, + {"FL_ALIGN_BOTTOM_RIGHT",0,0,(void*)(FL_ALIGN_BOTTOM_RIGHT)}, + {"FL_ALIGN_LEFT_TOP",0,0,(void*)(FL_ALIGN_LEFT_TOP)}, + {"FL_ALIGN_RIGHT_TOP",0,0,(void*)(FL_ALIGN_RIGHT_TOP)}, + {"FL_ALIGN_LEFT_BOTTOM",0,0,(void*)(FL_ALIGN_LEFT_BOTTOM)}, + {"FL_ALIGN_RIGHT_BOTTOM",0,0,(void*)(FL_ALIGN_RIGHT_BOTTOM)}, +{0}}; + +void align_cb(Fl_Button* i, void *v) { + int b = int(long(i->user_data())); + if (v == LOAD) { + if (current_widget->is_menu_item()) {i->deactivate(); return;} else i->activate(); + i->value(current_widget->o->align() & b); + } else { + int mod = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + int x = q->o->align(); + int y; + if (i->value()) { + y = x | b; + if (b == FL_ALIGN_LEFT || b == FL_ALIGN_TOP) { + Fl_Button *b1 = relative(i,+1); + b1->clear(); + y = y & ~(b1->argument()); + } + if (b == FL_ALIGN_RIGHT || b == FL_ALIGN_BOTTOM) { + Fl_Button *b1 = relative(i,-1); + b1->clear(); + y = y & ~(b1->argument()); + } + } else { + y = x & ~b; + } + if (x != y) { + q->o->align(y); + q->redraw(); + mod = 1; + } + } + } + if (mod) set_modflag(1); + } +} + +//////////////////////////////////////////////////////////////// + +void callback_cb(CodeEditor* i, void *v) { + if (v == LOAD) { + const char *cbtext = current_widget->callback(); + i->buffer()->text( cbtext ? cbtext : "" ); + } else { + int mod = 0; + char *c = i->buffer()->text(); + const char *d = c_check(c); + if (d) { + fl_message("Error in callback: %s",d); + if (i->window()) i->window()->make_current(); + haderror = 1; + } + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected) { + o->callback(c); + mod = 1; + } + } + if (mod) set_modflag(1); + free(c); + } +} + +void user_data_cb(Fl_Input *i, void *v) { + if (v == LOAD) { + i->static_value(current_widget->user_data()); + } else { + int mod = 0; + const char *c = i->value(); + const char *d = c_check(c); + if (d) {fl_message("Error in user_data: %s",d); haderror = 1; return;} + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected) { + o->user_data(c); + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +void user_data_type_cb(Fl_Input *i, void *v) { + static const char *dflt = "void*"; + if (v == LOAD) { + const char *c = current_widget->user_data_type(); + if (!c) c = dflt; + i->static_value(c); + } else { + int mod = 0; + const char *c = i->value(); + const char *d = c_check(c); + if (!*c) i->value(dflt); + else if (!strcmp(c,dflt)) c = 0; + if (!d) { + if (c && *c && c[strlen(c)-1] != '*' && strcmp(c,"long")) + d = "must be pointer or long"; + } + if (d) {fl_message("Error in type: %s",d); haderror = 1; return;} + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected) { + o->user_data_type(c); + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +// "v_attributes" let user type in random code for attribute settings: + +void v_input_cb(Fl_Input* i, void* v) { + int n = int(long(i->user_data())); + if (v == LOAD) { + i->static_value(current_widget->extra_code(n)); + } else { + int mod = 0; + const char *c = i->value(); + const char *d = c_check(c&&c[0]=='#' ? c+1 : c); + if (d) {fl_message("Error in %s: %s",i->label(),d); haderror = 1; return;} + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type *t = (Fl_Widget_Type*)o; + t->extra_code(n,c); + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +void subclass_cb(Fl_Input* i, void* v) { + if (v == LOAD) { + if (current_widget->is_menu_item()) {i->deactivate(); return;} else i->activate(); + i->static_value(current_widget->subclass()); + } else { + int mod = 0; + const char *c = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type *t = (Fl_Widget_Type*)o; + t->subclass(c); + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +//////////////////////////////////////////////////////////////// + +// textstuff: set textfont, textsize, textcolor attributes: + +// default widget returns 0 to indicate not-implemented: +int Fl_Widget_Type::textstuff(int, Fl_Font&, int&, Fl_Color&) {return 0;} + +void textfont_cb(Fl_Choice* i, void* v) { + Fl_Font n; int s; Fl_Color c; + if (v == LOAD) { + if (!current_widget->textstuff(0,n,s,c)) {i->deactivate(); return;} + i->activate(); + if (n > 15) n = FL_HELVETICA; + i->value(n); + } else { + int mod = 0; + n = (Fl_Font)i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->textstuff(1,n,s,c); + q->o->redraw(); + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +void textsize_cb(Fl_Value_Input* i, void* v) { + Fl_Font n; int s; Fl_Color c; + if (v == LOAD) { + if (!current_widget->textstuff(0,n,s,c)) {i->deactivate(); return;} + i->activate(); + } else { + int mod = 0; + s = int(i->value()); + if (s <= 0) s = Fl_Widget_Type::default_size; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->textstuff(2,n,s,c); + q->o->redraw(); + mod = 1; + } + } + if (mod) set_modflag(1); + } + i->value(s); +} + +void textcolor_cb(Fl_Button* i, void* v) { + Fl_Font n; int s; Fl_Color c; + if (v == LOAD) { + if (!current_widget->textstuff(0,n,s,c)) {i->deactivate(); return;} + i->activate(); + } else { + int mod = 0; + c = i->color(); + Fl_Color d = fl_show_colormap(c); + if (d == c) return; + c = d; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->textstuff(3,n,s,c); q->o->redraw(); + mod = 1; + } + } + if (mod) set_modflag(1); + } + i->color(c); i->labelcolor(fl_contrast(FL_BLACK,c)); i->redraw(); +} + +//////////////////////////////////////////////////////////////// +// Kludges to the panel for subclasses: + +void min_w_cb(Fl_Value_Input* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_window()) {i->parent()->hide(); return;} + i->parent()->show(); + i->value(((Fl_Window_Type*)current_widget)->sr_min_w); + } else { + int mod = 0; + int n = (int)i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_window()) { + ((Fl_Window_Type*)current_widget)->sr_min_w = n; + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +void min_h_cb(Fl_Value_Input* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_window()) return; + i->value(((Fl_Window_Type*)current_widget)->sr_min_h); + } else { + int mod = 0; + int n = (int)i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_window()) { + ((Fl_Window_Type*)current_widget)->sr_min_h = n; + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +void max_w_cb(Fl_Value_Input* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_window()) return; + i->value(((Fl_Window_Type*)current_widget)->sr_max_w); + } else { + int mod = 0; + int n = (int)i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_window()) { + ((Fl_Window_Type*)current_widget)->sr_max_w = n; + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +void max_h_cb(Fl_Value_Input* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_window()) return; + i->value(((Fl_Window_Type*)current_widget)->sr_max_h); + } else { + int mod = 0; + int n = (int)i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_window()) { + ((Fl_Window_Type*)current_widget)->sr_max_h = n; + mod = 1; + } + } + if (mod) set_modflag(1); + } +} + +void set_min_size_cb(Fl_Button*, void* v) { + if (v == LOAD) { + } else { + int mod = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_window()) { + Fl_Window_Type *win = (Fl_Window_Type*)current_widget; + win->sr_min_w = win->o->w(); + win->sr_min_h = win->o->h(); + mod = 1; + } + } + propagate_load(the_panel, LOAD); + if (mod) set_modflag(1); + } +} + +void set_max_size_cb(Fl_Button*, void* v) { + if (v == LOAD) { + } else { + int mod = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_window()) { + Fl_Window_Type *win = (Fl_Window_Type*)current_widget; + win->sr_max_w = win->o->w(); + win->sr_max_h = win->o->h(); + mod = 1; + } + } + propagate_load(the_panel, LOAD); + if (mod) set_modflag(1); + } +} + +void slider_size_cb(Fl_Value_Input* i, void* v) { + if (v == LOAD) { + if (current_widget->is_window()) + i->parent()->hide(); + else + i->parent()->show(); + if (current_widget->is_valuator()!=2) {i->deactivate(); return;} + i->activate(); + i->value(((Fl_Slider*)(current_widget->o))->slider_size()); + } else { + int mod = 0; + double n = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + if (q->is_valuator()==2) { + ((Fl_Slider*)(q->o))->slider_size(n); + q->o->redraw(); + mod = 1; + } + } + } + if (mod) set_modflag(1); + } +} + +void min_cb(Fl_Value_Input* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_valuator()) {i->deactivate(); return;} + i->activate(); + i->value(((Fl_Valuator*)(current_widget->o))->minimum()); + } else { + int mod = 0; + double n = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + if (q->is_valuator()) { + ((Fl_Valuator*)(q->o))->minimum(n); + q->o->redraw(); + mod = 1; + } + } + } + if (mod) set_modflag(1); + } +} + +void max_cb(Fl_Value_Input* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_valuator()) {i->deactivate(); return;} + i->activate(); + i->value(((Fl_Valuator*)(current_widget->o))->maximum()); + } else { + int mod = 0; + double n = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + if (q->is_valuator()) { + ((Fl_Valuator*)(q->o))->maximum(n); + q->o->redraw(); + mod = 1; + } + } + } + if (mod) set_modflag(1); + } +} + +void step_cb(Fl_Value_Input* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_valuator()) {i->deactivate(); return;} + i->activate(); + i->value(((Fl_Valuator*)(current_widget->o))->step()); + } else { + int mod = 0; + double n = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + if (q->is_valuator()) { + ((Fl_Valuator*)(q->o))->step(n); + q->o->redraw(); + mod = 1; + } + } + } + if (mod) set_modflag(1); + } +} + +void value_cb(Fl_Value_Input* i, void* v) { + if (v == LOAD) { + if (current_widget->is_valuator()) { + i->activate(); + i->value(((Fl_Valuator*)(current_widget->o))->value()); + } else if (current_widget->is_button()) { + i->activate(); + i->value(((Fl_Button*)(current_widget->o))->value()); + } else + i->deactivate(); + } else { + int mod = 0; + double n = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + if (q->is_valuator()) { + ((Fl_Valuator*)(q->o))->value(n); + mod = 1; + } else if (q->is_button()) { + ((Fl_Button*)(q->o))->value(n != 0); + if (q->is_menu_item()) q->redraw(); + mod = 1; + } + } + } + if (mod) set_modflag(1); + } +} + +//////////////////////////////////////////////////////////////// + +// subtypes: + +Fl_Menu_Item *Fl_Widget_Type::subtypes() {return 0;} + +void subtype_cb(Fl_Choice* i, void* v) { + if (v == LOAD) { + Fl_Menu_Item* m = current_widget->subtypes(); + if (!m) {i->deactivate(); return;} + i->menu(m); + int j; + for (j = 0;; j++) { + if (!m[j].text) {j = 0; break;} + if (m[j].argument() == current_widget->o->type()) break; + } + i->value(j); + i->activate(); + i->redraw(); + } else { + int mod = 0; + int n = int(i->mvalue()->argument()); + Fl_Menu_Item* m = current_widget->subtypes(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + if (q->subtypes()==m) { + q->o->type(n); + q->redraw(); + mod = 1; + } + } + } + if (mod) set_modflag(1); + } +} + +//////////////////////////////////////////////////////////////// + +void propagate_load(Fl_Group* g, void* v) { + if (v == LOAD) { + Fl_Widget*const* a = g->array(); + for (int i=g->children(); i--;) { + Fl_Widget* o = *a++; + o->do_callback(o,LOAD); + } + } +} + +void set_cb(Fl_Button*, void*) { + haderror = 0; + Fl_Widget*const* a = the_panel->array(); + for (int i=the_panel->children(); i--;) { + Fl_Widget* o = *a++; + if (o->changed()) { + o->do_callback(); + if (haderror) return; + o->clear_changed(); + } + } +} + +void ok_cb(Fl_Return_Button* o, void* v) { + set_cb(o,v); + if (!haderror) the_panel->hide(); +} + +void revert_cb(Fl_Button*, void*) { + // We have to revert all dynamically changing fields: + // but for now only the first label works... + if (numselected == 1) current_widget->label(oldlabel); + propagate_load(the_panel, LOAD); +} + +void cancel_cb(Fl_Button* o, void* v) { + revert_cb(o,v); + the_panel->hide(); +} + +void toggle_overlays(Fl_Widget *,void *); // in Fl_Window_Type.cxx +void overlay_cb(Fl_Button*o,void *v) { + toggle_overlays(o,v); +} + +void leave_live_mode_cb(Fl_Widget*, void*); + +void live_mode_cb(Fl_Button*o,void *v) { + /// \todo live mode should end gracefully when the application quits + /// or when the user closes the live widget + static Fl_Type *live_type = 0L; + static Fl_Widget *live_widget = 0L; + static Fl_Window *live_window = 0L; + // if 'o' is 0, we must quit live mode + if (!o) { + o = wLiveMode; + o->value(0); + } + if (o->value()) { + if (numselected == 1) { + live_widget = current_widget->enter_live_mode(1); + if (live_widget) { + live_type = current_widget; + Fl_Group::current(0); + int w = live_widget->w(); + int h = live_widget->h(); + live_window = new Fl_Double_Window(w+20, h+55, "Fluid Live Mode Widget"); + live_window->box(FL_FLAT_BOX); + live_window->color(FL_GREEN); + Fl_Group *rsz = new Fl_Group(0, h+20, 130, 35); + rsz->box(FL_NO_BOX); + Fl_Box *rsz_dummy = new Fl_Box(110, h+20, 1, 25); + rsz_dummy->box(FL_NO_BOX); + rsz->resizable(rsz_dummy); + Fl_Button *btn = new Fl_Button(10, h+20, 100, 25, "Exit Live Mode"); + btn->labelsize(12); + btn->callback(leave_live_mode_cb); + live_widget->position(10, 10); + live_window->add(live_widget); + live_window->resizable(live_widget); + live_window->set_modal(); // block all other UI + live_window->callback(leave_live_mode_cb); + if (current_widget->is_window()) { + Fl_Window_Type *w = (Fl_Window_Type*)current_widget; + int mw = w->sr_min_w; if (mw>0) mw += 20; + int mh = w->sr_min_h; if (mh>0) mh += 55; + int MW = w->sr_max_w; if (MW>0) MW += 20; + int MH = w->sr_max_h; if (MH>2) MH += 55; + if (mw || mh || MW || MH) + live_window->size_range(mw, mh, MW, MH); + } + live_window->show(); + } else o->value(0); + } else o->value(0); + } else { + if (live_type) + live_type->leave_live_mode(); + if (live_window) { + live_window->hide(); + Fl::delete_widget(live_window); + } + live_type = 0L; + live_widget = 0L; + live_window = 0L; + } +} + +// update the panel according to current widget set: +static void load_panel() { + if (!the_panel) return; + + // find all the Fl_Widget subclasses currently selected: + numselected = 0; + current_widget = 0; + if (Fl_Type::current) { + if (Fl_Type::current->is_widget()) + current_widget=(Fl_Widget_Type*)Fl_Type::current; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->is_widget() && o->selected) { + numselected++; + if (!current_widget) current_widget = (Fl_Widget_Type*)o; + } + } + } + if (numselected) + propagate_load(the_panel, LOAD); + else + the_panel->hide(); +} + +// This is called when user double-clicks an item, open or update the panel: +void Fl_Widget_Type::open() { + if (!the_panel) the_panel = make_widget_panel(); + load_panel(); + if (numselected) the_panel->show(); +} + +Fl_Type *Fl_Type::current; + +extern void redraw_overlays(); +extern void redraw_browser(); +extern void update_sourceview_position(); + +// Called when ui changes what objects are selected: +// p is selected object, null for all deletions (we must throw away +// old panel in that case, as the object may no longer exist) +void selection_changed(Fl_Type *p) { + // store all changes to the current selected objects: + if (p && the_panel && the_panel->visible()) { + set_cb(0,0); + // if there was an error, we try to leave the selected set unchanged: + if (haderror) { + Fl_Type *q = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + o->new_selected = o->selected; + if (!q && o->selected) q = o; + } + if (!p || !p->selected) p = q; + Fl_Type::current = p; + redraw_browser(); + return; + } + } + // update the selected flags to new set: + Fl_Type *q = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + o->selected = o->new_selected; + if (!q && o->selected) q = o; + } + if (!p || !p->selected) p = q; + Fl_Type::current = p; + redraw_overlays(); + // load the panel with the new settings: + load_panel(); + // update the source viewer to show the code for the selected object + update_sourceview_position(); +} + +//////////////////////////////////////////////////////////////// +// Writing the C code: + +// test to see if user named a function, or typed in code: +int is_name(const char *c) { + for (; *c; c++) if (ispunct(*c) && *c!='_' && *c!=':') return 0; + return 1; +} + +// Test to see if name() is an array entry. If so, and this is the +// highest number, return name[num+1]. Return null if not the highest +// number or a field or function. Return name() if not an array entry. +const char *array_name(Fl_Widget_Type *o) { + const char *c = o->name(); + if (!c) return 0; + const char *d; + for (d = c; *d != '['; d++) { + if (!*d) return c; + if (ispunct(*d) && *d!='_') return 0; + } + int num = atoi(d+1); + int sawthis = 0; + Fl_Type *t = o->prev; + Fl_Type *tp = o; + const char *cn = o->class_name(1); + for (; t && t->class_name(1) == cn; tp = t, t = t->prev); + for (t = tp; t && t->class_name(1) == cn; t = t->next) { + if (t == o) {sawthis=1; continue;} + const char *e = t->name(); + if (!e) continue; + if (strncmp(c,e,d-c)) continue; + int n1 = atoi(e+(d-c)+1); + if (n1 > num || n1==num && sawthis) return 0; + } + static char buffer[128]; + // MRS: we want strncpy() here... + strncpy(buffer,c,d-c+1); + snprintf(buffer+(d-c+1),sizeof(buffer) - (d-c+1), "%d]",num+1); + return buffer; +} + +// Test to see if extra code is a declaration: +int isdeclare(const char *c) { + while (isspace(*c)) c++; + if (*c == '#') return 1; + if (!strncmp(c,"extern",6)) return 1; + if (!strncmp(c,"typedef",7)) return 1; + if (!strncmp(c,"using",5)) return 1; + return 0; +} + +void Fl_Widget_Type::write_static() { + const char* t = subclassname(this); + if (!subclass() || is_class()) write_declare("#include <FL/%s.H>", t); + for (int n=0; n < NUM_EXTRA_CODE; n++) { + if (extra_code(n) && isdeclare(extra_code(n))) + write_declare("%s", extra_code(n)); + } + if (callback() && is_name(callback())) { + int write_extern_declaration = 1; + const Fl_Class_Type *cc = is_in_class(); + if (cc) { + char buf[1024]; snprintf(buf, 1023, "%s(*)", callback()); + if (cc->has_function("static void", buf)) + write_extern_declaration = 0; + } + if (write_extern_declaration) + write_declare("extern void %s(%s*, %s);", callback(), t, + user_data_type() ? user_data_type() : "void*"); + } + const char* k = class_name(1); + const char* c = array_name(this); + if (c && !k && !is_class()) { + write_c("\n"); + if (!public_) write_c("static "); + else write_h("extern %s *%s;\n", t, c); + if (strchr(c, '[') == NULL) write_c("%s *%s=(%s *)0;\n", t, c, t); + else write_c("%s *%s={(%s *)0};\n", t, c, t); + } + if (callback() && !is_name(callback())) { + // see if 'o' or 'v' used, to prevent unused argument warnings: + int use_o = 0; + int use_v = 0; + const char *d; + for (d = callback(); *d;) { + if (*d == 'o' && !is_id(d[1])) use_o = 1; + if (*d == 'v' && !is_id(d[1])) use_v = 1; + do d++; while (is_id(*d)); + while (*d && !is_id(*d)) d++; + } + const char* cn = callback_name(); + if (k) { + write_c("\nvoid %s::%s_i(%s*", k, cn, t); + } else { + write_c("\nstatic void %s(%s*", cn, t); + } + if (use_o) write_c(" o"); + const char* ut = user_data_type() ? user_data_type() : "void*"; + write_c(", %s", ut); + if (use_v) write_c(" v"); + write_c(") {\n %s", callback()); + if (*(d-1) != ';') { + const char *p = strrchr(callback(), '\n'); + if (p) p ++; + else p = callback(); + // Only add trailing semicolon if the last line is not a preprocessor + // statement... + if (*p != '#' && *p) write_c(";"); + } + write_c("\n}\n"); + if (k) { + write_c("void %s::%s(%s* o, %s v) {\n", k, cn, t, ut); + write_c(" ((%s*)(o", k); + Fl_Type *q = 0; + for (Fl_Type* p = parent; p && p->is_widget(); q = p, p = p->parent) + write_c("->parent()"); + if (!q || strcmp(q->type_name(), "widget_class")) + write_c("->user_data()"); + write_c("))->%s_i(o,v);\n}\n", cn); + } + } + if (image) { + if (image->written != write_number) { + image->write_static(); + image->written = write_number; + } + } + if (inactive) { + if (inactive->written != write_number) { + inactive->write_static(); + inactive->written = write_number; + } + } +} + +const char *Fl_Type::callback_name() { + if (is_name(callback())) return callback(); + return unique_id(this, "cb", name(), label()); +} + +extern int varused_test, varused; + +void Fl_Widget_Type::write_code1() { + const char* t = subclassname(this); + const char *c = array_name(this); + if (c) { + if (class_name(1)) { + write_public(public_); + write_h(" %s *%s;\n", t, c); + } + } + if (class_name(1) && callback() && !is_name(callback())) { + const char* cn = callback_name(); + const char* ut = user_data_type() ? user_data_type() : "void*"; + write_public(0); + write_h(" void %s_i(%s*, %s);\n", cn, t, ut); + write_h(" static void %s(%s*, %s);\n", cn, t, ut); + } + // figure out if local variable will be used (prevent compiler warnings): + if (is_parent()) + varused = 1; + else { + varused_test = 1; varused = 0; + write_widget_code(); + varused_test = 0; + for (int n=0; n < NUM_EXTRA_CODE; n++) + if (extra_code(n) && !isdeclare(extra_code(n))) varused = 1; + } + write_c(indent()); + if (varused) write_c("{ %s* o = ", t); + if (name()) write_c("%s = ", name()); + if (is_window()) { + // Handle special case where user is faking a Fl_Group type as a window, + // there is no 2-argument constructor in that case: + if (!strstr(t, "Window")) + write_c("new %s(0, 0, %d, %d", t, o->w(), o->h()); + else + write_c("new %s(%d, %d", t, o->w(), o->h()); + } else { + write_c("new %s(%d, %d, %d, %d", t, o->x(), o->y(), o->w(), o->h()); + } + if (label() && *label()) { + write_c(", "); + switch (i18n_type) { + case 0 : /* None */ + write_cstring(label()); + break; + case 1 : /* GNU gettext */ + write_c("%s(", i18n_function); + write_cstring(label()); + write_c(")"); + break; + case 2 : /* POSIX catgets */ + write_c("catgets(%s,%s,%d,", i18n_file[0] ? i18n_file : "_catalog", + i18n_set, msgnum()); + write_cstring(label()); + write_c(")"); + break; + } + } + write_c(");\n"); + indentation += 2; + + if (is_window()) write_c("%sw = o;\n",indent()); + if (varused) write_widget_code(); +} + +void Fl_Widget_Type::write_color(const char* field, Fl_Color color) { + const char* color_name = 0; + switch (color) { + case FL_FOREGROUND_COLOR: color_name = "FL_FOREGROUND_COLOR"; break; + case FL_BACKGROUND2_COLOR: color_name = "FL_BACKGROUND2_COLOR"; break; + case FL_INACTIVE_COLOR: color_name = "FL_INACTIVE_COLOR"; break; + case FL_SELECTION_COLOR: color_name = "FL_SELECTION_COLOR"; break; + case FL_GRAY0: color_name = "FL_GRAY0"; break; + case FL_DARK3: color_name = "FL_DARK3"; break; + case FL_DARK2: color_name = "FL_DARK2"; break; + case FL_DARK1: color_name = "FL_DARK1"; break; + case FL_BACKGROUND_COLOR: color_name = "FL_BACKGROUND_COLOR"; break; + case FL_LIGHT1: color_name = "FL_LIGHT1"; break; + case FL_LIGHT2: color_name = "FL_LIGHT2"; break; + case FL_LIGHT3: color_name = "FL_LIGHT3"; break; + case FL_BLACK: color_name = "FL_BLACK"; break; + case FL_RED: color_name = "FL_RED"; break; + case FL_GREEN: color_name = "FL_GREEN"; break; + case FL_YELLOW: color_name = "FL_YELLOW"; break; + case FL_BLUE: color_name = "FL_BLUE"; break; + case FL_MAGENTA: color_name = "FL_MAGENTA"; break; + case FL_CYAN: color_name = "FL_CYAN"; break; + case FL_DARK_RED: color_name = "FL_DARK_RED"; break; + case FL_DARK_GREEN: color_name = "FL_DARK_GREEN"; break; + case FL_DARK_YELLOW: color_name = "FL_DARK_YELLOW"; break; + case FL_DARK_BLUE: color_name = "FL_DARK_BLUE"; break; + case FL_DARK_MAGENTA: color_name = "FL_DARK_MAGENTA"; break; + case FL_DARK_CYAN: color_name = "FL_DARK_CYAN"; break; + case FL_WHITE: color_name = "FL_WHITE"; break; + } + if (color_name) { + write_c("%so->%s(%s);\n", indent(), field, color_name); + } else { + write_c("%so->%s((Fl_Color)%d);\n", indent(), field, color); + } +} + +// this is split from write_code1() for Fl_Window_Type: +void Fl_Widget_Type::write_widget_code() { + Fl_Widget* tplate = ((Fl_Widget_Type*)factory)->o; + if (tooltip() && *tooltip()) { + write_c("%so->tooltip(",indent()); + switch (i18n_type) { + case 0 : /* None */ + write_cstring(tooltip()); + break; + case 1 : /* GNU gettext */ + write_c("%s(", i18n_function); + write_cstring(tooltip()); + write_c(")"); + break; + case 2 : /* POSIX catgets */ + write_c("catgets(%s,%s,%d,", i18n_file[0] ? i18n_file : "_catalog", + i18n_set, msgnum() + 1); + write_cstring(tooltip()); + write_c(")"); + break; + } + write_c(");\n"); + } + + if (o->type() != tplate->type() && !is_window()) + write_c("%so->type(%d);\n", indent(), o->type()); + if (o->box() != tplate->box() || subclass()) + write_c("%so->box(FL_%s);\n", indent(), boxname(o->box())); + if (is_button()) { + Fl_Button* b = (Fl_Button*)o; + if (b->down_box()) write_c("%so->down_box(FL_%s);\n", indent(), + boxname(b->down_box())); + if (b->value()) write_c("%so->value(1);\n", indent()); + if (b->shortcut()) + write_c("%so->shortcut(0x%x);\n", indent(), b->shortcut()); + } else if (!strcmp(type_name(), "Fl_Input_Choice")) { + Fl_Input_Choice* b = (Fl_Input_Choice*)o; + if (b->down_box()) write_c("%so->down_box(FL_%s);\n", indent(), + boxname(b->down_box())); + } else if (is_menu_button()) { + Fl_Menu_* b = (Fl_Menu_*)o; + if (b->down_box()) write_c("%so->down_box(FL_%s);\n", indent(), + boxname(b->down_box())); + } + if (o->color() != tplate->color() || subclass()) + write_color("color", o->color()); + if (o->selection_color() != tplate->selection_color() || subclass()) + write_color("selection_color", o->selection_color()); + if (image) image->write_code(); + if (inactive) inactive->write_code(1); + if (o->labeltype() != tplate->labeltype() || subclass()) + write_c("%so->labeltype(FL_%s);\n", indent(), + item_name(labeltypemenu, o->labeltype())); + if (o->labelfont() != tplate->labelfont() || subclass()) + write_c("%so->labelfont(%d);\n", indent(), o->labelfont()); + if (o->labelsize() != tplate->labelsize() || subclass()) + write_c("%so->labelsize(%d);\n", indent(), o->labelsize()); + if (o->labelcolor() != tplate->labelcolor() || subclass()) + write_color("labelcolor", o->labelcolor()); + if (is_valuator()) { + Fl_Valuator* v = (Fl_Valuator*)o; + Fl_Valuator* f = (Fl_Valuator*)(tplate); + if (v->minimum()!=f->minimum()) + write_c("%so->minimum(%g);\n", indent(), v->minimum()); + if (v->maximum()!=f->maximum()) + write_c("%so->maximum(%g);\n", indent(), v->maximum()); + if (v->step()!=f->step()) + write_c("%so->step(%g);\n", indent(), v->step()); + if (v->value()) + write_c("%so->value(%g);\n", indent(), v->value()); + if (is_valuator()==2) { + double x = ((Fl_Slider*)v)->slider_size(); + double y = ((Fl_Slider*)f)->slider_size(); + if (x != y) write_c("%so->slider_size(%g);\n", indent(), x); + } + } + {Fl_Font ff; int fs; Fl_Color fc; if (textstuff(4,ff,fs,fc)) { + Fl_Font f; int s; Fl_Color c; textstuff(0,f,s,c); + if (f != ff) write_c("%so->textfont(%d);\n", indent(), f); + if (s != fs) write_c("%so->textsize(%d);\n", indent(), s); + if (c != fc) write_c("%so->textcolor(%d);\n",indent(), c); + }} + const char* ud = user_data(); + if (class_name(1) && !parent->is_widget()) ud = "this"; + if (callback()) { + write_c("%so->callback((Fl_Callback*)%s", indent(), callback_name()); + if (ud) + write_c(", (void*)(%s));\n", ud); + else + write_c(");\n"); + } else if (ud) { + write_c("%so->user_data((void*)(%s));\n", indent(), ud); + } + if (o->align() != tplate->align() || subclass()) { + int i = o->align(); + write_c("%so->align(%s", indent(), + item_name(alignmenu, i & ~FL_ALIGN_INSIDE)); + if (i & FL_ALIGN_INSIDE) write_c("|FL_ALIGN_INSIDE"); + write_c(");\n"); + } + if (o->when() != tplate->when() || subclass()) + write_c("%so->when(%s);\n", indent(),item_name(whensymbolmenu, o->when())); + if (!o->visible() && o->parent()) + write_c("%so->hide();\n", indent()); + if (!o->active()) + write_c("%so->deactivate();\n", indent()); + if (!is_group() && resizable()) + write_c("%sFl_Group::current()->resizable(o);\n",indent()); + if (hotspot()) + write_c("%sw->hotspot(o);\n", indent()); +} + +void Fl_Widget_Type::write_extra_code() { + for (int n=0; n < NUM_EXTRA_CODE; n++) + if (extra_code(n) && !isdeclare(extra_code(n))) + write_c("%s%s\n", indent(), extra_code(n)); +} + +void Fl_Widget_Type::write_block_close() { + indentation -= 2; + if (is_parent() || varused) write_c("%s}\n", indent()); +} + +void Fl_Widget_Type::write_code2() { + write_extra_code(); + write_block_close(); +} + +//////////////////////////////////////////////////////////////// + +void Fl_Widget_Type::write_properties() { + Fl_Type::write_properties(); + write_indent(level+1); + if (!public_) write_string("private"); + if (tooltip() && *tooltip()) { + write_string("tooltip"); + write_word(tooltip()); + } + if (image_name() && *image_name()) { + write_string("image"); + write_word(image_name()); + } + if (inactive_name() && *inactive_name()) { + write_string("deimage"); + write_word(inactive_name()); + } + write_string("xywh {%d %d %d %d}", o->x(), o->y(), o->w(), o->h()); + Fl_Widget* tplate = ((Fl_Widget_Type*)factory)->o; + if (o->type() != tplate->type() || is_window()) { + write_string("type"); + write_word(item_name(subtypes(), o->type())); + } + if (o->box() != tplate->box()) { + write_string("box"); write_word(boxname(o->box()));} + if (is_button()) { + Fl_Button* b = (Fl_Button*)o; + if (b->down_box()) { + write_string("down_box"); write_word(boxname(b->down_box()));} + if (b->shortcut()) write_string("shortcut 0x%x", b->shortcut()); + if (b->value()) write_string("value 1"); + } else if (!strcmp(type_name(), "Fl_Input_Choice")) { + Fl_Input_Choice* b = (Fl_Input_Choice*)o; + if (b->down_box()) { + write_string("down_box"); write_word(boxname(b->down_box()));} + } else if (is_menu_button()) { + Fl_Menu_* b = (Fl_Menu_*)o; + if (b->down_box()) { + write_string("down_box"); write_word(boxname(b->down_box()));} + } + if (o->color()!=tplate->color()) + write_string("color %d", o->color()); + if (o->selection_color()!=tplate->selection_color()) + write_string("selection_color %d", o->selection_color()); + if (o->labeltype()!=tplate->labeltype()) { + write_string("labeltype"); + write_word(item_name(labeltypemenu, o->labeltype())); + } + if (o->labelfont()!=tplate->labelfont()) + write_string("labelfont %d", o->labelfont()); + if (o->labelsize()!=tplate->labelsize()) + write_string("labelsize %d", o->labelsize()); + if (o->labelcolor()!=tplate->labelcolor()) + write_string("labelcolor %d", o->labelcolor()); + if (o->align()!=tplate->align()) + write_string("align %d", o->align()); + if (o->when() != tplate->when()) + write_string("when %d", o->when()); + if (is_valuator()) { + Fl_Valuator* v = (Fl_Valuator*)o; + Fl_Valuator* f = (Fl_Valuator*)(tplate); + if (v->minimum()!=f->minimum()) write_string("minimum %g",v->minimum()); + if (v->maximum()!=f->maximum()) write_string("maximum %g",v->maximum()); + if (v->step()!=f->step()) write_string("step %g",v->step()); + if (v->value()!=0.0) write_string("value %g",v->value()); + if (is_valuator()==2) { + double x = ((Fl_Slider*)v)->slider_size(); + double y = ((Fl_Slider*)f)->slider_size(); + if (x != y) write_string("slider_size %g", x); + } + } + {Fl_Font ff; int fs; Fl_Color fc; if (textstuff(4,ff,fs,fc)) { + Fl_Font f; int s; Fl_Color c; textstuff(0,f,s,c); + if (f != ff) write_string("textfont %d", f); + if (s != fs) write_string("textsize %d", s); + if (c != fc) write_string("textcolor %d", c); + }} + if (!o->visible()) write_string("hide"); + if (!o->active()) write_string("deactivate"); + if (resizable()) write_string("resizable"); + if (hotspot()) write_string(is_menu_item() ? "divider" : "hotspot"); + for (int n=0; n < NUM_EXTRA_CODE; n++) if (extra_code(n)) { + write_indent(level+1); + write_string("code%d",n); + write_word(extra_code(n)); + } + if (subclass()) { + write_indent(level+1); + write_string("class"); + write_word(subclass()); + } +} + +int pasteoffset; + +void Fl_Widget_Type::read_property(const char *c) { + int x,y,w,h; Fl_Font f; int s; Fl_Color cc; + if (!strcmp(c,"private")) { + public_ = 0; + } else if (!strcmp(c,"xywh")) { + if (sscanf(read_word(),"%d %d %d %d",&x,&y,&w,&h) == 4) { + x += pasteoffset; + y += pasteoffset; + o->resize(x,y,w,h); + } + } else if (!strcmp(c,"tooltip")) { + tooltip(read_word()); + } else if (!strcmp(c,"image")) { + image_name(read_word()); + } else if (!strcmp(c,"deimage")) { + inactive_name(read_word()); + } else if (!strcmp(c,"type")) { + o->type(item_number(subtypes(), read_word())); + } else if (!strcmp(c,"box")) { + const char* value = read_word(); + if ((x = boxnumber(value))) { + if (x == ZERO_ENTRY) x = 0; + o->box((Fl_Boxtype)x); + } else if (sscanf(value,"%d",&x) == 1) o->box((Fl_Boxtype)x); + } else if (is_button() && !strcmp(c,"down_box")) { + const char* value = read_word(); + if ((x = boxnumber(value))) { + if (x == ZERO_ENTRY) x = 0; + ((Fl_Button*)o)->down_box((Fl_Boxtype)x); + } + } else if (!strcmp(type_name(), "Fl_Input_Choice") && !strcmp(c,"down_box")) { + const char* value = read_word(); + if ((x = boxnumber(value))) { + if (x == ZERO_ENTRY) x = 0; + ((Fl_Input_Choice*)o)->down_box((Fl_Boxtype)x); + } + } else if (is_menu_button() && !strcmp(c,"down_box")) { + const char* value = read_word(); + if ((x = boxnumber(value))) { + if (x == ZERO_ENTRY) x = 0; + ((Fl_Menu_*)o)->down_box((Fl_Boxtype)x); + } + } else if (is_button() && !strcmp(c,"value")) { + const char* value = read_word(); + ((Fl_Button*)o)->value(atoi(value)); + } else if (!strcmp(c,"color")) { + int n = sscanf(read_word(),"%d %d",&x,&y); + if (n == 2) { // back compatability... + if (x != 47) o->color(x); + o->selection_color(y); + } else { + o->color(x); + } + } else if (!strcmp(c,"selection_color")) { + if (sscanf(read_word(),"%d",&x)) o->selection_color(x); + } else if (!strcmp(c,"labeltype")) { + c = read_word(); + if (!strcmp(c,"image")) { + Fluid_Image *i = Fluid_Image::find(label()); + if (!i) read_error("Image file '%s' not found", label()); + else setimage(i); + image_name(label()); + label(""); + } else { + o->labeltype((Fl_Labeltype)item_number(labeltypemenu,c)); + } + } else if (!strcmp(c,"labelfont")) { + if (sscanf(read_word(),"%d",&x) == 1) o->labelfont(x); + } else if (!strcmp(c,"labelsize")) { + if (sscanf(read_word(),"%d",&x) == 1) o->labelsize(x); + } else if (!strcmp(c,"labelcolor")) { + if (sscanf(read_word(),"%d",&x) == 1) o->labelcolor(x); + } else if (!strcmp(c,"align")) { + if (sscanf(read_word(),"%d",&x) == 1) o->align(x); + } else if (!strcmp(c,"when")) { + if (sscanf(read_word(),"%d",&x) == 1) o->when(x); + } else if (!strcmp(c,"minimum") && is_valuator()) { + ((Fl_Valuator*)o)->minimum(strtod(read_word(),0)); + } else if (!strcmp(c,"maximum") && is_valuator()) { + ((Fl_Valuator*)o)->maximum(strtod(read_word(),0)); + } else if (!strcmp(c,"step") && is_valuator()) { + ((Fl_Valuator*)o)->step(strtod(read_word(),0)); + } else if (!strcmp(c,"value") && is_valuator()) { + ((Fl_Valuator*)o)->value(strtod(read_word(),0)); + } else if ((!strcmp(c,"slider_size")||!strcmp(c,"size"))&&is_valuator()==2) { + ((Fl_Slider*)o)->slider_size(strtod(read_word(),0)); + } else if (!strcmp(c,"textfont")) { + if (sscanf(read_word(),"%d",&x) == 1) {f=(Fl_Font)x; textstuff(1,f,s,cc);} + } else if (!strcmp(c,"textsize")) { + if (sscanf(read_word(),"%d",&x) == 1) {s=x; textstuff(2,f,s,cc);} + } else if (!strcmp(c,"textcolor")) { + if (sscanf(read_word(),"%d",&x) == 1) {cc=(Fl_Color)x;textstuff(3,f,s,cc);} + } else if (!strcmp(c,"hide")) { + o->hide(); + } else if (!strcmp(c,"deactivate")) { + o->deactivate(); + } else if (!strcmp(c,"resizable")) { + resizable(1); + } else if (!strcmp(c,"hotspot") || !strcmp(c, "divider")) { + hotspot(1); + } else if (!strcmp(c,"class")) { + subclass(read_word()); + } else if (is_button() && !strcmp(c,"shortcut")) { + ((Fl_Button*)o)->shortcut(strtol(read_word(),0,0)); + } else { + if (!strncmp(c,"code",4)) { + int n = atoi(c+4); + if (n >= 0 && n <= NUM_EXTRA_CODE) { + extra_code(n,read_word()); + return; + } + } + Fl_Type::read_property(c); + } +} + +Fl_Menu_Item boxmenu1[] = { + // these extra ones are for looking up fdesign saved strings: + {"NO_FRAME", 0,0,(void *)FL_NO_BOX}, + {"ROUNDED3D_UPBOX", 0,0,(void *)_FL_ROUND_UP_BOX}, + {"ROUNDED3D_DOWNBOX", 0,0,(void *)_FL_ROUND_DOWN_BOX}, + {"OVAL3D_UPBOX", 0,0,(void *)_FL_ROUND_UP_BOX}, + {"OVAL3D_DOWNBOX", 0,0,(void *)_FL_ROUND_DOWN_BOX}, + {"0", 0,0,(void *)ZERO_ENTRY}, + {"1", 0,0,(void *)FL_UP_BOX}, + {"2", 0,0,(void *)FL_DOWN_BOX}, + {"3", 0,0,(void *)FL_FLAT_BOX}, + {"4", 0,0,(void *)FL_BORDER_BOX}, + {"5", 0,0,(void *)FL_SHADOW_BOX}, + {"6", 0,0,(void *)FL_FRAME_BOX}, + {"7", 0,0,(void *)FL_ROUNDED_BOX}, + {"8", 0,0,(void *)FL_RFLAT_BOX}, + {"9", 0,0,(void *)FL_RSHADOW_BOX}, + {"10", 0,0,(void *)FL_UP_FRAME}, + {"11", 0,0,(void *)FL_DOWN_FRAME}, +{0}}; + +extern int fdesign_flip; +int lookup_symbol(const char *, int &, int numberok = 0); + +int Fl_Widget_Type::read_fdesign(const char* propname, const char* value) { + int v; + if (!strcmp(propname,"box")) { + float x,y,w,h; + if (sscanf(value,"%f %f %f %f",&x,&y,&w,&h) == 4) { + if (fdesign_flip) { + Fl_Type *p; + for (p = parent; p && !p->is_window(); p = p->parent); + if (p && p->is_widget()) y = ((Fl_Widget_Type*)p)->o->h()-(y+h); + } + x += pasteoffset; + y += pasteoffset; + o->resize(int(x),int(y),int(w),int(h)); + } + } else if (!strcmp(propname,"label")) { + label(value); + } else if (!strcmp(propname,"name")) { + this->name(value); + } else if (!strcmp(propname,"callback")) { + callback(value); user_data_type("long"); + } else if (!strcmp(propname,"argument")) { + user_data(value); + } else if (!strcmp(propname,"shortcut")) { + if (value[0]) { + char buf[128]; sprintf(buf,"o->shortcut(\"%s\");",value); + extra_code(0,buf); + } + } else if (!strcmp(propname,"style")) { + if (!strncmp(value,"FL_NORMAL",9)) return 1; + if (!lookup_symbol(value,v,1)) return 0; + o->labelfont(v); o->labeltype((Fl_Labeltype)(v>>8)); + } else if (!strcmp(propname,"size")) { + if (!lookup_symbol(value,v,1)) return 0; + o->labelsize(v); + } else if (!strcmp(propname,"type")) { + if (!strncmp(value,"NORMAL",6)) return 1; + if (lookup_symbol(value,v,1)) {o->type(v); return 1;} + if (!strcmp(value+strlen(value)-5,"FRAME")) goto TRY_BOXTYPE; + if (!strcmp(value+strlen(value)-3,"BOX")) goto TRY_BOXTYPE; + return 0; + } else if (!strcmp(propname,"lcol")) { + if (!lookup_symbol(value,v,1)) return 0; + o->labelcolor(v); + } else if (!strcmp(propname,"return")) { + if (!lookup_symbol(value,v,0)) return 0; + o->when(v|FL_WHEN_RELEASE); + } else if (!strcmp(propname,"alignment")) { + if (!lookup_symbol(value,v)) { + // convert old numeric values: + int v1 = atoi(value); if (v1 <= 0 && strcmp(value,"0")) return 0; + v = 0; + if (v1 >= 5) {v = FL_ALIGN_INSIDE; v1 -= 5;} + switch (v1) { + case 0: v += FL_ALIGN_TOP; break; + case 1: v += FL_ALIGN_BOTTOM; break; + case 2: v += FL_ALIGN_LEFT; break; + case 3: v += FL_ALIGN_RIGHT; break; + case 4: v += FL_ALIGN_CENTER; break; + default: return 0; + } + } + o->align(v); + } else if (!strcmp(propname,"resizebox")) { + resizable(1); + } else if (!strcmp(propname,"colors")) { + char* p = (char*)value; + while (*p != ' ') {if (!*p) return 0; p++;} + *p = 0; + int v1; + if (!lookup_symbol(value,v,1) || !lookup_symbol(p+1,v1,1)) { + *p=' '; return 0;} + o->color(v,v1); + } else if (!strcmp(propname,"resize")) { + return !strcmp(value,"FL_RESIZE_ALL"); + } else if (!strcmp(propname,"gravity")) { + return !strcmp(value,"FL_NoGravity FL_NoGravity"); + } else if (!strcmp(propname,"boxtype")) { + TRY_BOXTYPE: + int x = boxnumber(value); + if (!x) {x = item_number(boxmenu1, value); if (x < 0) return 0;} + if (x == ZERO_ENTRY) { + x = 0; + if (o->box() != ((Fl_Widget_Type*)factory)->o->box()) return 1; // kludge for frame + } + o->box((Fl_Boxtype)x); + } else { + return 0; + } + return 1; +} + +void leave_live_mode_cb(Fl_Widget*, void*) { + live_mode_cb(0, 0); +} + +Fl_Widget *Fl_Widget_Type::enter_live_mode(int top) { + live_widget = widget(o->x(), o->y(), o->w(), o->h()); + if (live_widget) + copy_properties(); + return live_widget; +} + +void Fl_Widget_Type::leave_live_mode() { +} + +/** + * copy all properties from the edit widget to the live widget + */ +void Fl_Widget_Type::copy_properties() { + if (!live_widget) + return; + + // copy all attributes common to all widget types + Fl_Widget *w = live_widget; + w->label(o->label()); + w->tooltip(tooltip()); + w->type(o->type()); + w->box(o->box()); + w->color(o->color()); + w->selection_color(o->selection_color()); + w->labeltype(o->labeltype()); + w->labelfont(o->labelfont()); + w->labelsize(o->labelsize()); + w->labelcolor(o->labelcolor()); + w->align(o->align()); + + // copy all attributes specific to widgets derived from Fl_Button + if (is_button()) { + Fl_Button* d = (Fl_Button*)live_widget, *s = (Fl_Button*)o; + d->down_box(s->down_box()); + d->shortcut(s->shortcut()); + d->value(s->value()); + } + + // copy all attributes specific to Fl_Valuator and derived classes + if (is_valuator()) { + Fl_Valuator* d = (Fl_Valuator*)live_widget, *s = (Fl_Valuator*)o; + d->minimum(s->minimum()); + d->maximum(s->maximum()); + d->step(s->step()); + d->value(s->value()); + if (is_valuator()==2) { + Fl_Slider *d = (Fl_Slider*)live_widget, *s = (Fl_Slider*)o; + d->slider_size(s->slider_size()); + } + } + +/* TODO: implement this + {Fl_Font ff; int fs; Fl_Color fc; if (textstuff(4,ff,fs,fc)) { + Fl_Font f; int s; Fl_Color c; textstuff(0,f,s,c); + if (f != ff) write_string("textfont %d", f); + if (s != fs) write_string("textsize %d", s); + if (c != fc) write_string("textcolor %d", c); + }}*/ + + if (!o->visible()) + w->hide(); + if (!o->active()) + w->deactivate(); + if (resizable() && w->parent()) + w->parent()->resizable(o); +} + +void Fl_Pack_Type::copy_properties() +{ + Fl_Group_Type::copy_properties(); + Fl_Pack *d = (Fl_Pack*)live_widget, *s =(Fl_Pack*)o; + d->spacing(s->spacing()); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/Fl_Widget_Type.h b/Utilities/FLTK/fluid/Fl_Widget_Type.h new file mode 100644 index 0000000000..487a2cc5e1 --- /dev/null +++ b/Utilities/FLTK/fluid/Fl_Widget_Type.h @@ -0,0 +1,42 @@ +// +// "$Id$" +// +// Widget type header file for the Fast Light Tool Kit (FLTK). +// +// Type for creating all subclasses of Fl_Widget +// This should have the widget pointer in it, but it is still in the +// Fl_Type base class. +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include "Fl_Type.h" + +struct Fl_Menu_Item; +class Fluid_Image; + +void* const LOAD = (void *)9831; +extern Fl_Widget_Type *current_widget; // one of the selected ones + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/Fl_Window_Type.cxx b/Utilities/FLTK/fluid/Fl_Window_Type.cxx new file mode 100644 index 0000000000..050324d059 --- /dev/null +++ b/Utilities/FLTK/fluid/Fl_Window_Type.cxx @@ -0,0 +1,1504 @@ +// +// "$Id$" +// +// Window type code for the Fast Light Tool Kit (FLTK). +// +// The widget describing an Fl_Window. This is also all the code +// for interacting with the overlay, which allows the user to +// select, move, and resize the children widgets. +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Overlay_Window.H> +#include <FL/fl_message.H> +#include <FL/fl_draw.H> +#include <FL/x.H> +#include <FL/Fl_Menu_Item.H> +#include <FL/Fl_Round_Button.H> +#include "Fl_Widget_Type.h" +#include "undo.h" +#include <math.h> +#include <stdlib.h> +#include "alignment_panel.h" +#include <stdio.h> + +extern int gridx; +extern int gridy; +extern int snap; +extern int show_guides; + +int include_H_from_C = 1; +extern int i18n_type; +extern const char* i18n_include; +extern const char* i18n_function; +extern const char* i18n_file; +extern const char* i18n_set; + +extern Fl_Preferences fluid_prefs; + +inline int fl_min(int a, int b) { return (a < b ? a : b); } + +#include "widget_panel.h" + +// Update the XYWH values in the widget panel... +static void update_xywh() { + if (current_widget && current_widget->is_widget()) { + widget_x_input->value(((Fl_Widget_Type *)current_widget)->o->x()); + widget_y_input->value(((Fl_Widget_Type *)current_widget)->o->y()); + widget_w_input->value(((Fl_Widget_Type *)current_widget)->o->w()); + widget_h_input->value(((Fl_Widget_Type *)current_widget)->o->h()); + } +} + +void guides_cb(Fl_Check_Button *i, long) { + show_guides = i->value(); + fluid_prefs.set("show_guides", show_guides); + + for (Fl_Type *p = Fl_Type::first; p; p = p->next) { + if (p->is_window()) { + Fl_Window_Type *w = (Fl_Window_Type *)p; + ((Fl_Overlay_Window *)(w->o))->redraw_overlay(); + } + } +} + +void grid_cb(Fl_Input *i, long v) { + int n = atoi(i->value()); + if (n < 0) n = 0; + switch (v) { + case 1: + gridx = n; + fluid_prefs.set("gridx", n); + break; + case 2: + gridy = n; + fluid_prefs.set("gridy", n); + break; + case 3: + snap = n; + fluid_prefs.set("snap", n); + break; + } + + // Next go through all of the windows in the project and set the + // stepping for resizes... + Fl_Type *p; + Fl_Window_Type *w; + + for (p = Fl_Type::first; p; p = p->next) { + if (p->is_window()) { + w = (Fl_Window_Type *)p; + ((Fl_Window *)(w->o))->size_range(gridx, gridy, + Fl::w(), Fl::h(), + gridx, gridy, 0); + } + } +} + +// Set default widget sizes... +void default_widget_size_cb(Fl_Round_Button *b, long size) { + // Update the "normal" text size of new widgets... + b->setonly(); + Fl_Widget_Type::default_size = size; + fluid_prefs.set("widget_size", Fl_Widget_Type::default_size); +} + + +void i18n_type_cb(Fl_Choice *c, void *) { + undo_checkpoint(); + + switch (i18n_type = c->value()) { + case 0 : /* None */ + i18n_include_input->hide(); + i18n_file_input->hide(); + i18n_set_input->hide(); + i18n_function_input->hide(); + break; + case 1 : /* GNU gettext */ + i18n_include_input->value("<libintl.h>"); + i18n_include = i18n_include_input->value(); + i18n_function_input->value("gettext"); + i18n_function = i18n_function_input->value(); + i18n_include_input->show(); + i18n_file_input->hide(); + i18n_set_input->hide(); + i18n_function_input->show(); + break; + case 2 : /* POSIX cat */ + i18n_include_input->value("<nl_types.h>"); + i18n_file_input->value(""); + i18n_file = i18n_file_input->value(); + i18n_set_input->value("1"); + i18n_set = i18n_set_input->value(); + i18n_include_input->show(); + i18n_include = i18n_include_input->value(); + i18n_file_input->show(); + i18n_set_input->show(); + i18n_function_input->hide(); + break; + } + + set_modflag(1); +} + +void i18n_text_cb(Fl_Input *i, void *) { + undo_checkpoint(); + + if (i == i18n_function_input) + i18n_function = i->value(); + else if (i == i18n_file_input) + i18n_file = i->value(); + else if (i == i18n_set_input) + i18n_set = i->value(); + else if (i == i18n_include_input) + i18n_include = i->value(); + + set_modflag(1); +} + +extern const char* header_file_name; +extern const char* code_file_name; + +void show_project_cb(Fl_Widget *, void *) { + if(project_window==0) make_project_window(); + include_H_from_C_button->value(include_H_from_C); + header_file_input->value(header_file_name); + code_file_input->value(code_file_name); + i18n_type_chooser->value(i18n_type); + i18n_function_input->value(i18n_function); + i18n_file_input->value(i18n_file); + i18n_set_input->value(i18n_set); + i18n_include_input->value(i18n_include); + switch (i18n_type) { + case 0 : /* None */ + i18n_include_input->hide(); + i18n_file_input->hide(); + i18n_set_input->hide(); + i18n_function_input->hide(); + break; + case 1 : /* GNU gettext */ + i18n_include_input->show(); + i18n_file_input->hide(); + i18n_set_input->hide(); + i18n_function_input->show(); + break; + case 2 : /* POSIX cat */ + i18n_include_input->show(); + i18n_file_input->show(); + i18n_set_input->show(); + i18n_function_input->hide(); + break; + } + project_window->hotspot(project_window); + project_window->show(); +} + +void show_grid_cb(Fl_Widget *, void *) { + char buf[128]; + sprintf(buf,"%d",gridx); horizontal_input->value(buf); + sprintf(buf,"%d",gridy); vertical_input->value(buf); + sprintf(buf,"%d",snap); snap_input->value(buf); + guides_toggle->value(show_guides); + int s = Fl_Widget_Type::default_size; + if (s<=8) def_widget_size[0]->setonly(); + else if (s<=11) def_widget_size[1]->setonly(); + else if (s<=14) def_widget_size[2]->setonly(); + else if (s<=18) def_widget_size[3]->setonly(); + else if (s<=24) def_widget_size[4]->setonly(); + else if (s<=32) def_widget_size[5]->setonly(); + grid_window->hotspot(grid_window); + grid_window->show(); +} + +void show_settings_cb(Fl_Widget *, void *) { + settings_window->hotspot(settings_window); + settings_window->show(); +} + +void header_input_cb(Fl_Input* i, void*) { + if (header_file_name && strcmp(header_file_name, i->value())) + set_modflag(1); + header_file_name = i->value(); +} +void code_input_cb(Fl_Input* i, void*) { + if (code_file_name && strcmp(code_file_name, i->value())) + set_modflag(1); + code_file_name = i->value(); +} + +void include_H_from_C_button_cb(Fl_Light_Button* b, void*) { + if (include_H_from_C != b->value()) { + set_modflag(1); + include_H_from_C = b->value(); + } +} + +//////////////////////////////////////////////////////////////// + +Fl_Menu_Item window_type_menu[] = { + {"Single",0,0,(void*)FL_WINDOW}, + {"Double",0,0,(void*)(FL_WINDOW+1)}, + {0}}; + +static int overlays_invisible; + +// The following Fl_Widget is used to simulate the windows. It has +// an overlay for the fluid ui, and special-cases the FL_NO_BOX. + +class Overlay_Window : public Fl_Overlay_Window { + void draw(); + void draw_overlay(); +public: + Fl_Window_Type *window; + int handle(int); + Overlay_Window(int W,int H) : Fl_Overlay_Window(W,H) {Fl_Group::current(0);} + void resize(int,int,int,int); + uchar *read_image(int &ww, int &hh); +}; +void Overlay_Window::draw() { + const int CHECKSIZE = 8; + // see if box is clear or a frame or rounded: + if ((damage()&FL_DAMAGE_ALL) && + (!box() || (box()>=4&&!(box()&2)) || box()>=_FL_ROUNDED_BOX)) { + // if so, draw checkerboard so user can see what areas are clear: + for (int Y = 0; Y < h(); Y += CHECKSIZE) + for (int X = 0; X < w(); X += CHECKSIZE) { + fl_color(((Y/(2*CHECKSIZE))&1) != ((X/(2*CHECKSIZE))&1) ? + FL_WHITE : FL_BLACK); + fl_rectf(X,Y,CHECKSIZE,CHECKSIZE); + } + } + Fl_Overlay_Window::draw(); +} + +extern Fl_Window *main_window; + +// Read an image of the overlay window +uchar *Overlay_Window::read_image(int &ww, int &hh) { + // Create an off-screen buffer for the window... + main_window->make_current(); + + ww = w(); + hh = h(); + + Fl_Offscreen offscreen = fl_create_offscreen(ww, hh); + uchar *pixels; + + // Redraw the window into the offscreen buffer... + fl_begin_offscreen(offscreen); + + if (!shown()) image(Fl::scheme_bg_); + + redraw(); + draw(); + + // Read the screen image... + pixels = fl_read_image(0, 0, 0, ww, hh); + + fl_end_offscreen(); + + // Cleanup and return... + fl_delete_offscreen(offscreen); + + return pixels; +} + +void Overlay_Window::draw_overlay() { + window->draw_overlay(); +} +int Overlay_Window::handle(int e) { + return window->handle(e); +} + +Fl_Type *Fl_Window_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_code_block()) p = p->parent; + if (!p) { + fl_message("Please select a function"); + return 0; + } + Fl_Window_Type *myo = new Fl_Window_Type(); + if (!this->o) {// template widget + this->o = new Fl_Window(100,100); + Fl_Group::current(0); + } + // Set the size ranges for this window; in order to avoid opening the + // X display we use an arbitrary maximum size... + ((Fl_Window *)(this->o))->size_range(gridx, gridy, + 3072, 2048, + gridx, gridy, 0); + myo->factory = this; + myo->drag = 0; + myo->numselected = 0; + Overlay_Window *w = new Overlay_Window(100,100); + w->window = myo; + myo->o = w; + myo->add(p); + myo->modal = 0; + myo->non_modal = 0; + return myo; +} + +void Fl_Window_Type::add_child(Fl_Type* cc, Fl_Type* before) { + if (!cc->is_widget()) return; + Fl_Widget_Type* c = (Fl_Widget_Type*)cc; + Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; + ((Fl_Window*)o)->insert(*(c->o), b); + o->redraw(); +} + +void Fl_Window_Type::remove_child(Fl_Type* cc) { + Fl_Widget_Type* c = (Fl_Widget_Type*)cc; + ((Fl_Window*)o)->remove(c->o); + o->redraw(); +} + +void Fl_Window_Type::move_child(Fl_Type* cc, Fl_Type* before) { + Fl_Widget_Type* c = (Fl_Widget_Type*)cc; + ((Fl_Window*)o)->remove(c->o); + Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; + ((Fl_Window*)o)->insert(*(c->o), b); + o->redraw(); +} + +//////////////////////////////////////////////////////////////// + +// Double-click on window widget shows the window, or if already shown, +// it shows the control panel. +void Fl_Window_Type::open() { + Overlay_Window *w = (Overlay_Window *)o; + if (w->shown()) { + w->show(); + Fl_Widget_Type::open(); + } else { + Fl_Widget *p = w->resizable(); + if (!p) w->resizable(w); + w->show(); + w->resizable(p); + } + + w->image(Fl::scheme_bg_); + w->size_range(gridx, gridy, Fl::w(), Fl::h(), gridx, gridy, 0); +} + +// Read an image of the window +uchar *Fl_Window_Type::read_image(int &ww, int &hh) { + Overlay_Window *w = (Overlay_Window *)o; + + // Read the screen image... + return (w->read_image(ww, hh)); +} + + +// control panel items: + +void modal_cb(Fl_Light_Button* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_window()) {i->hide(); return;} + i->show(); + i->value(((Fl_Window_Type *)current_widget)->modal); + } else { + ((Fl_Window_Type *)current_widget)->modal = i->value(); + set_modflag(1); + } +} + +void non_modal_cb(Fl_Light_Button* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_window()) {i->hide(); return;} + i->show(); + i->value(((Fl_Window_Type *)current_widget)->non_modal); + } else { + ((Fl_Window_Type *)current_widget)->non_modal = i->value(); + set_modflag(1); + } +} + +void border_cb(Fl_Light_Button* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_window()) {i->hide(); return;} + i->show(); + i->value(((Fl_Window*)(current_widget->o))->border()); + } else { + ((Fl_Window*)(current_widget->o))->border(i->value()); + set_modflag(1); + } +} + +void xclass_cb(Fl_Input* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_window()) { + i->hide(); + i->parent()->hide(); // hides the "X Class:" label as well + return; + } + i->show(); + i->parent()->show(); + i->value(((Fl_Widget_Type *)current_widget)->xclass); + } else { + int mod = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + mod = 1; + Fl_Widget_Type* w = (Fl_Widget_Type*)o; + if (w->is_window() || w->is_button()) + storestring(i->value(),w->xclass); + if (w->is_window()) ((Fl_Window*)(w->o))->xclass(w->xclass); + else if (w->is_menu_item()) w->redraw(); + } + } + if (mod) set_modflag(1); + } +} + +//////////////////////////////////////////////////////////////// + +void Fl_Window_Type::setlabel(const char *n) { + if (o) ((Fl_Window *)o)->label(n); +} + +// make() is called on this widget when user picks window off New menu: +Fl_Window_Type Fl_Window_type; + +// Resize from window manager... +void Overlay_Window::resize(int X,int Y,int W,int H) { + Fl_Widget* t = resizable(); resizable(0); + Fl_Overlay_Window::resize(X,Y,W,H); + resizable(t); + update_xywh(); +} + +// calculate actual move by moving mouse position (mx,my) to +// nearest multiple of gridsize, and snap to original position +void Fl_Window_Type::newdx() { + int mydx, mydy; + if (Fl::event_state(FL_ALT) || !snap) { + mydx = mx-x1; + mydy = my-y1; + + if (abs(mydx) < 2 && abs(mydy) < 2) mydx = mydy = 0; + } else { + int dx0 = mx-x1; + int ix = (drag&RIGHT) ? br : bx; + mydx = gridx ? ((ix+dx0+gridx/2)/gridx)*gridx - ix : dx0; + if (dx0 > snap) { + if (mydx < 0) mydx = 0; + } else if (dx0 < -snap) { + if (mydx > 0) mydx = 0; + } else + mydx = 0; + int dy0 = my-y1; + int iy = (drag&BOTTOM) ? by : bt; + mydy = gridy ? ((iy+dy0+gridy/2)/gridy)*gridy - iy : dy0; + if (dy0 > snap) { + if (mydy < 0) mydy = 0; + } else if (dy0 < -snap) { + if (mydy > 0) mydy = 0; + } else + mydy = 0; + } + + if (!(drag & (DRAG | BOX | LEFT | RIGHT))) { + mydx = 0; + dx = 0; + } + + if (!(drag & (DRAG | BOX | TOP | BOTTOM))) { + mydy = 0; + dy = 0; + } + + if (dx != mydx || dy != mydy) { + dx = mydx; dy = mydy; + ((Overlay_Window *)o)->redraw_overlay(); + } +} + +// Move a widget according to dx and dy calculated above +void Fl_Window_Type::newposition(Fl_Widget_Type *myo,int &X,int &Y,int &R,int &T) { + X = myo->o->x(); + Y = myo->o->y(); + R = X+myo->o->w(); + T = Y+myo->o->h(); + if (!drag) return; + if (drag&DRAG) { + X += dx; + Y += dy; + R += dx; + T += dy; + } else { + if (drag&LEFT) if (X==bx) X += dx; else if (X<bx+dx) X = bx+dx; + if (drag&TOP) if (Y==by) Y += dy; else if (Y<by+dy) Y = by+dy; + if (drag&RIGHT) if (R==br) R += dx; else if (R>br+dx) R = br+dx; + if (drag&BOTTOM) if (T==bt) T += dy; else if (T>bt+dx) T = bt+dx; + } + if (R<X) {int n = X; X = R; R = n;} + if (T<Y) {int n = Y; Y = T; T = n;} +} + +// draw a vertical arrow pointing toward y2 +static void draw_v_arrow(int x, int y1, int y2) { + int dy = (y1>y2) ? -1 : 1 ; + fl_yxline(x, y1, y2); + fl_xyline(x-4, y2, x+4); + fl_line(x-2, y2-dy*5, x, y2-dy); + fl_line(x+2, y2-dy*5, x, y2-dy); +} + +static void draw_h_arrow(int x1, int y, int x2) { + int dx = (x1>x2) ? -1 : 1 ; + fl_xyline(x1, y, x2); + fl_yxline(x2, y-4, y+4); + fl_line(x2-dx*5, y-2, x2-dx, y); + fl_line(x2-dx*5, y+2, x2-dx, y); +} + +static void draw_top_brace(const Fl_Widget *w) { + fl_yxline(w->x(), w->y()-2, w->y()+6); + fl_yxline(w->x()+w->w()-1, w->y()-2, w->y()+6); + fl_xyline(w->x()-2, w->y(), w->x()+w->w()+1); +} + +static void draw_left_brace(const Fl_Widget *w) { + fl_xyline(w->x()-2, w->y(), w->x()+6); + fl_xyline(w->x()-2, w->y()+w->h()-1, w->x()+6); + fl_yxline(w->x(), w->y()-2, w->y()+w->h()+1); +} + +static void draw_right_brace(const Fl_Widget *w) { + int xx = w->x() + w->w() - 1; + fl_xyline(xx-6, w->y(), xx+2); + fl_xyline(xx-6, w->y()+w->h()-1, xx+2); + fl_yxline(xx, w->y()-2, w->y()+w->h()+1); +} + +static void draw_bottom_brace(const Fl_Widget *w) { + int yy = w->y() + w->h() - 1; + fl_yxline(w->x(), yy-6, yy+2); + fl_yxline(w->x()+w->w()-1, yy-6, yy+2); + fl_xyline(w->x()-2, yy, w->x()+w->w()+1); +} + +static void draw_height(int x, int y, int b, Fl_Align a) { + char buf[16]; + int h = b - y; + sprintf(buf, "%d", h); + fl_font(FL_HELVETICA, 9); + int lw = (int)fl_width(buf); + int lx; + + b --; + if (h < 30) { + // Move height to the side... + if (a == FL_ALIGN_LEFT) lx = x - lw - 2; + else lx = x + 2; + + fl_yxline(x, y, b); + } else { + // Put height inside the arrows... + lx = x - lw / 2; + + fl_yxline(x, y, y + (h - 11) / 2); + fl_yxline(x, y + (h + 11) / 2, b); + } + + // Draw the height... + fl_draw(buf, lx, y + (h + 9) / 2); + + // Draw the arrowheads... + fl_line(x-2, y+5, x, y+1, x+2, y+5); + fl_line(x-2, b-5, x, b-1, x+2, b-5); + + // Draw the end lines... + fl_xyline(x - 4, y, x + 4); + fl_xyline(x - 4, b, x + 4); +} + +static void draw_width(int x, int y, int r, Fl_Align a) { + char buf[16]; + int w = r-x; + sprintf(buf, "%d", w); + fl_font(FL_HELVETICA, 9); + int lw = (int)fl_width(buf); + int ly = y + 4; + + r --; + + if (lw > (w - 20)) { + // Move width above/below the arrows... + if (a == FL_ALIGN_TOP) ly -= 10; + else ly += 10; + + fl_xyline(x, y, r); + } else { + // Put width inside the arrows... + fl_xyline(x, y, x + (w - lw - 2) / 2); + fl_xyline(x + (w + lw + 2) / 2, y, r); + } + + // Draw the width... + fl_draw(buf, x + (w - lw) / 2, ly); + + // Draw the arrowheads... + fl_line(x+5, y-2, x+1, y, x+5, y+2); + fl_line(r-5, y-2, r-1, y, r-5, y+2); + + // Draw the end lines... + fl_yxline(x, y - 4, y + 4); + fl_yxline(r, y - 4, y + 4); +} + +void Fl_Window_Type::draw_overlay() { + if (recalc) { + bx = o->w(); by = o->h(); br = 0; bt = 0; + numselected = 0; + for (Fl_Type *q=next; q && q->level>level; q=q->next) + if (q->selected && q->is_widget() && !q->is_menu_item()) { + numselected++; + Fl_Widget_Type* myo = (Fl_Widget_Type*)q; + if (myo->o->x() < bx) bx = myo->o->x(); + if (myo->o->y() < by) by = myo->o->y(); + if (myo->o->x()+myo->o->w() > br) br = myo->o->x()+myo->o->w(); + if (myo->o->y()+myo->o->h() > bt) bt = myo->o->y()+myo->o->h(); + } + recalc = 0; + sx = bx; sy = by; sr = br; st = bt; + } + fl_color(FL_RED); + if (drag==BOX && (x1 != mx || y1 != my)) { + int x = x1; int r = mx; if (x > r) {x = mx; r = x1;} + int y = y1; int b = my; if (y > b) {y = my; b = y1;} + fl_rect(x,y,r-x,b-y); + } + if (overlays_invisible && !drag) return; + if (selected) fl_rect(0,0,o->w(),o->h()); + if (!numselected) return; + int mybx,myby,mybr,mybt; + int mysx,mysy,mysr,myst; + mybx = mysx = o->w(); myby = mysy = o->h(); mybr = mysr = 0; mybt = myst = 0; + Fl_Type *selection = 0L; // used to store the one selected widget (if n==1) + for (Fl_Type *q=next; q && q->level>level; q = q->next) + if (q->selected && q->is_widget() && !q->is_menu_item()) { + selection = q; + Fl_Widget_Type* myo = (Fl_Widget_Type*)q; + int x,y,r,t; + newposition(myo,x,y,r,t); + if (!show_guides || !drag || numselected != 1) fl_rect(x,y,r-x,t-y); + if (x < mysx) mysx = x; + if (y < mysy) mysy = y; + if (r > mysr) mysr = r; + if (t > myst) myst = t; + if (!(myo->o->align() & FL_ALIGN_INSIDE)) { + // Adjust left/right/top/bottom for top/bottom labels... + int ww, hh; + ww = (myo->o->align() & FL_ALIGN_WRAP) ? myo->o->w() : 0; + hh = myo->o->labelsize(); + myo->o->measure_label(ww, hh); + if (myo->o->align() & FL_ALIGN_TOP) y -= hh; + else if (myo->o->align() & FL_ALIGN_BOTTOM) t += hh; + else if (myo->o->align() & FL_ALIGN_LEFT) x -= ww + 4; + else if (myo->o->align() & FL_ALIGN_RIGHT) r += ww + 4; + } + if (x < mybx) mybx = x; + if (y < myby) myby = y; + if (r > mybr) mybr = r; + if (t > mybt) mybt = t; + } + if (selected) return; + + if (show_guides && drag) { + // draw overlays for UI Guideline distances + // - check for distance to the window edge + // * FLTK suggests 10 pixels from the edge + int d; + int xsp, ysp; + int mybx_bak = mybx, myby_bak = myby, mybr_bak = mybr, mybt_bak = mybt; + Fl_Widget_Type *mysel = (Fl_Widget_Type *)selection; + + + ideal_spacing(xsp, ysp); + + if (drag) { + // Check top spacing... + if (abs(d = myby - ysp) < 3) { + dy -= d; + if (drag & DRAG) mybt -= d; + myby -= d; + draw_v_arrow(mybx+5, myby, 0); + } + + // Check bottom spacing... + if (abs(d = o->h() - mybt - ysp) < 3) { + dy += d; + if (drag & DRAG) myby += d; + mybt += d; + draw_v_arrow(mybx+5, mybt, o->h()); + } + + // Check left spacing... + if (abs(d = mybx - xsp) < 3) { + dx -= d; + if (drag & DRAG) mybr -= d; + mybx -= d; + draw_h_arrow(mybx, myby+5, 0); + } + + // Check right spacing... + if (abs(d = o->w() - mybr - xsp) < 3) { + dx += d; + if (drag & DRAG) mybx += d; + mybr += d; + draw_h_arrow(mybr, myby+5, o->w()); + } + } + + if (numselected==1 && selection && !(drag & DRAG)) { + // Check ideal sizes + int x,y,r,t; + newposition(mysel,x,y,r,t); + int w = r-x; + int h = t-y; + int iw = w, ih = h; + + mysel->ideal_size(iw, ih); + + if (drag & (TOP | BOTTOM)) { + // Check height + if (abs(d = ih - h) < 5) { + // Resize height + if (drag & TOP) { + myby -= d; + y -= d; + dy -= d; + } else { + mybt += d; + t += d; + dy += d; + } + } + + // Draw height guide + draw_height(x < 50 ? x+10 : x-10, y, t, + x < 50 ? FL_ALIGN_RIGHT : FL_ALIGN_LEFT); + } + + if (drag & (LEFT | RIGHT)) { + // Check width + if (abs(d = iw - w) < 5) { + // Resize width + if (drag & LEFT) { + mybx -= d; + x -= d; + dx -= d; + } else { + mybr += d; + r += d; + dx += d; + } + } + + // Draw width guide + draw_width(x, y < 50 ? y+10 : y-10, r, + y < 50 ? FL_ALIGN_BOTTOM : FL_ALIGN_TOP); + } + } + + // Check spacing and alignment between individual widgets + if (drag && selection->is_widget()) { + for (Fl_Type *q=next; q && q->level>level; q = q->next) + if (q != selection && q->is_widget()) { + Fl_Widget_Type *qw = (Fl_Widget_Type*)q; + // Only check visible widgets... + if (!qw->o->visible_r()) continue; + + // Get bounding box of widget... + int qx = qw->o->x(); + int qr = qw->o->x() + qw->o->w(); + int qy = qw->o->y(); + int qt = qw->o->y() + qw->o->h(); + + if (!(qw->o->align() & FL_ALIGN_INSIDE)) { + // Adjust top/bottom for top/bottom labels... + int ww, hh; + ww = qw->o->w(); + hh = qw->o->labelsize(); + qw->o->measure_label(ww, hh); + if (qw->o->align() & FL_ALIGN_TOP) qy -= hh; + if (qw->o->align() & FL_ALIGN_BOTTOM) qt += hh; + } + + // Do horizontal alignment when the widget is within 25 + // pixels vertically... + if (fl_min(abs(qy - mysel->o->y() - mysel->o->h()), + abs(mysel->o->y() - qt)) < 25) { + // Align to left of other widget... + if ((drag & (LEFT | DRAG)) && abs(d = mybx - qx) < 3) { + dx += d; + mybx += d; + if (drag & DRAG) mybr += d; + + draw_left_brace(qw->o); + } + + // Align to right of other widget... + if ((drag & (RIGHT | DRAG)) && + abs(d = qr - mybr) < 3) { + dx += d; + if (drag & DRAG) mybx += d; + mybr += d; + + draw_right_brace(qw->o); + } + } + + // Align to top of other widget... + if ((drag & (TOP | DRAG)) && abs(d = myby - qy) < 3) { + dy += d; + myby += d; + if (drag & DRAG) mybt += d; + + draw_top_brace(qw->o); + } + + // Align to bottom of other widget... + if ((drag & (BOTTOM | DRAG)) && abs(d = qt - mybt) < 3) { + dy += d; + if (drag & DRAG) myby += d; + mybt += d; + + draw_bottom_brace(qw->o); + } + + // Check spacing between widgets + if (mysel->is_group()) mysel->ideal_spacing(xsp, ysp); + else qw->ideal_spacing(xsp, ysp); + + if ((qt)>=myby && qy<=mybt) { + if (drag & (LEFT | DRAG)) { + // Compare left of selected to left of current + if (abs(d = qx - mybx - xsp) >= 3) + d = qx - mybx + xsp; + + if (abs(d) < 3) { + dx += d; + mybx += d; + if (drag & DRAG) mybr += d; + + // Draw left arrow + draw_h_arrow(mybx, (myby+mybt)/2, qx); + } + + // Compare left of selected to right of current + if (abs(d = qr - mybx - xsp) >= 3) + d = qr - mybx + xsp; + + if (abs(d) < 3) { + dx += d; + mybx += d; + if (drag & DRAG) mybr += d; + + // Draw left arrow + draw_h_arrow(mybx, (myby+mybt)/2, qr); + } + } + + if (drag & (RIGHT | DRAG)) { + // Compare right of selected to left of current + if (abs(d = qx - mybr - xsp) >= 3) + d = qx - mybr + xsp; + + if (abs(d) < 3) { + dx += d; + if (drag & DRAG) mybx += d; + mybr += d; + + // Draw right arrow + draw_h_arrow(mybr, (myby+mybt)/2, qx); + } + + // Compare right of selected to right of current + if (abs(d = qr - mybr + xsp) >= 3) + d = qr - mybr - xsp; + + if (abs(d) < 3) { + dx += d; + if (drag & DRAG) mybx += d; + mybr += d; + + // Draw right arrow + draw_h_arrow(mybr, (myby+mybt)/2, qr); + } + } + } + + if (qr>=mybx && qx<=mybr) { + // Compare top of selected to top of current + if (drag & (TOP | DRAG)) { + if (abs(d = qy - myby - ysp) >= 3) + d = qy - myby + ysp; + + if (abs(d) < 3) { + dy += d; + myby += d; + if (drag & DRAG) mybt += d; + + // Draw up arrow... + draw_v_arrow((mybx+mybr)/2, myby, qy); + } + + // Compare top of selected to bottom of current + if (abs(d = qt - myby - ysp) >= 3) + d = qt - myby + ysp; + + if (abs(d) < 3) { + dy += d; + myby += d; + if (drag & DRAG) mybt += d; + + // Draw up arrow... + draw_v_arrow((mybx+mybr)/2, myby, qt); + } + } + + // Compare bottom of selected to top of current + if (drag & (BOTTOM | DRAG)) { + if (abs(d = qy - mybt - ysp) >= 3) + d = qy - mybt + ysp; + + if (abs(d) < 3) { + dy += d; + if (drag & DRAG) myby += d; + mybt += d; + + // Draw down arrow... + draw_v_arrow((mybx+mybr)/2, mybt, qy); + } + + // Compare bottom of selected to bottom of current + if (abs(d = qt - mybt - ysp) >= 3) + d = qt - mybt + ysp; + + if (abs(d) < 3) { + dy += d; + if (drag & DRAG) myby += d; + mybt += d; + + // Draw down arrow... + draw_v_arrow((mybx+mybr)/2, mybt, qt); + } + } + } + } + } + mysx += mybx-mybx_bak; mysr += mybr-mybr_bak; + mysy += myby-myby_bak; myst += mybt-mybt_bak; + } + // align the snapping selection box with the box we draw. + sx = mysx; sy = mysy; sr = mysr; st = myst; + + // Draw selection box + resize handles... + // draw box including all labels + fl_line_style(FL_DOT); + fl_rect(mybx,myby,mybr-mybx,mybt-myby); + fl_line_style(FL_SOLID); + // draw box excluding labels + fl_rect(mysx,mysy,mysr-mysx,myst-mysy); + fl_rectf(mysx,mysy,5,5); + fl_rectf(mysr-5,mysy,5,5); + fl_rectf(mysr-5,myst-5,5,5); + fl_rectf(mysx,myst-5,5,5); +} + +extern Fl_Menu_Item Main_Menu[]; + +// Calculate new bounding box of selected widgets: +void Fl_Window_Type::fix_overlay() { + Main_Menu[40].label("Hide O&verlays"); + overlays_invisible = 0; + recalc = 1; + ((Overlay_Window *)(this->o))->redraw_overlay(); +} + +// do that for every window (when selected set changes): +void redraw_overlays() { + for (Fl_Type *o=Fl_Type::first; o; o=o->next) + if (o->is_window()) ((Fl_Window_Type*)o)->fix_overlay(); +} + +void toggle_overlays(Fl_Widget *,void *) { + overlays_invisible = !overlays_invisible; + + if (overlays_invisible) Main_Menu[40].label("Show O&verlays"); + else Main_Menu[40].label("Hide O&verlays"); + + for (Fl_Type *o=Fl_Type::first; o; o=o->next) + if (o->is_window()) { + Fl_Widget_Type* w = (Fl_Widget_Type*)o; + ((Overlay_Window*)(w->o))->redraw_overlay(); + } +} + +extern void select(Fl_Type *,int); +extern void select_only(Fl_Type *); +extern void deselect(); +extern Fl_Type* in_this_only; +extern void fix_group_size(Fl_Type *t); + +extern Fl_Menu_Item Main_Menu[]; +extern Fl_Menu_Item New_Menu[]; + +// move the selected children according to current dx,dy,drag state: +void Fl_Window_Type::moveallchildren() +{ + undo_checkpoint(); + Fl_Type *i; + for (i=next; i && i->level>level;) { + if (i->selected && i->is_widget() && !i->is_menu_item()) { + Fl_Widget_Type* myo = (Fl_Widget_Type*)i; + int x,y,r,t; + newposition(myo,x,y,r,t); + myo->o->resize(x,y,r-x,t-y); + // move all the children, whether selected or not: + Fl_Type* p; + for (p = myo->next; p && p->level>myo->level; p = p->next) + if (p->is_widget() && !p->is_menu_item()) { + Fl_Widget_Type* myo2 = (Fl_Widget_Type*)p; + int X,Y,R,T; + newposition(myo2,X,Y,R,T); + myo2->o->resize(X,Y,R-X,T-Y); + } + i = p; + } else { + i = i->next; + } + } + for (i=next; i && i->level>level; i=i->next) + fix_group_size(i); + o->redraw(); + recalc = 1; + ((Overlay_Window *)(this->o))->redraw_overlay(); + set_modflag(1); + dx = dy = 0; + + update_xywh(); +} + +int Fl_Window_Type::handle(int event) { + static Fl_Type* selection; + switch (event) { + case FL_PUSH: + x1 = mx = Fl::event_x(); + y1 = my = Fl::event_y(); + drag = dx = dy = 0; + // test for popup menu: + if (Fl::event_button() >= 3) { + in_this_only = this; // modifies how some menu items work. + static const Fl_Menu_Item* myprev; + const Fl_Menu_Item* m = New_Menu->popup(mx,my,"New",myprev); + if (m && m->callback()) {myprev = m; m->do_callback(this->o);} + in_this_only = 0; + return 1; + } + // find the innermost item clicked on: + selection = this; + {for (Fl_Type* i=next; i && i->level>level; i=i->next) + if (i->is_widget() && !i->is_menu_item()) { + Fl_Widget_Type* myo = (Fl_Widget_Type*)i; + for (Fl_Widget *o1 = myo->o; o1; o1 = o1->parent()) + if (!o1->visible()) goto CONTINUE2; + if (Fl::event_inside(myo->o)) selection = myo; + CONTINUE2:; + }} + // see if user grabs edges of selected region: + if (numselected && !(Fl::event_state(FL_SHIFT)) && + mx<=br+snap && mx>=bx-snap && my<=bt+snap && my>=by-snap) { + int snap1 = snap>5 ? snap : 5; + int w1 = (br-bx)/4; if (w1 > snap1) w1 = snap1; + if (mx>=br-w1) drag |= RIGHT; + else if (mx<bx+w1) drag |= LEFT; + w1 = (bt-by)/4; if (w1 > snap1) w1 = snap1; + if (my<=by+w1) drag |= TOP; + else if (my>bt-w1) drag |= BOTTOM; + if (!drag) drag = DRAG; + } + // do object-specific selection of other objects: + {Fl_Type* t = selection->click_test(mx, my); + if (t) { + //if (t == selection) return 1; // indicates mouse eaten w/o change + if (Fl::event_state(FL_SHIFT)) { + Fl::event_is_click(0); + select(t, !t->selected); + } else { + deselect(); + select(t, 1); + if (t->is_menu_item()) t->open(); + } + selection = t; + drag = 0; + } else { + if (!drag) drag = BOX; // if all else fails, start a new selection region + }} + return 1; + + case FL_DRAG: + if (!drag) return 0; + mx = Fl::event_x(); + my = Fl::event_y(); + newdx(); + return 1; + + case FL_RELEASE: + if (!drag) return 0; + mx = Fl::event_x(); + my = Fl::event_y(); + if (drag != BOX && (dx || dy || !Fl::event_is_click())) { + if (dx || dy) moveallchildren(); + } else if ((Fl::event_clicks() || Fl::event_state(FL_CTRL))) { + Fl_Widget_Type::open(); + } else { + if (mx<x1) {int t = x1; x1 = mx; mx = t;} + if (my<y1) {int t = y1; y1 = my; my = t;} + int n = 0; + int toggle = Fl::event_state(FL_SHIFT); + // clear selection on everything: + if (!toggle) deselect(); else Fl::event_is_click(0); + // select everything in box: + for (Fl_Type*i=next; i&&i->level>level; i=i->next) + if (i->is_widget() && !i->is_menu_item()) { + Fl_Widget_Type* myo = (Fl_Widget_Type*)i; + for (Fl_Widget *o1 = myo->o; o1; o1 = o1->parent()) + if (!o1->visible()) goto CONTINUE; + if (Fl::event_inside(myo->o)) selection = myo; + if (myo->o->x()>=x1 && myo->o->y()>y1 && + myo->o->x()+myo->o->w()<mx && myo->o->y()+myo->o->h()<my) { + n++; + select(myo, toggle ? !myo->selected : 1); + } + CONTINUE:; + } + // if nothing in box, select what was clicked on: + if (!n) { + select(selection, toggle ? !selection->selected : 1); + } + } + drag = 0; + ((Overlay_Window *)o)->redraw_overlay(); + return 1; + + case FL_KEYBOARD: { + + int backtab = 0; + switch (Fl::event_key()) { + + case FL_Escape: + ((Fl_Window*)o)->hide(); + return 1; + + case 0xFE20: // backtab + backtab = 1; + case FL_Tab: { + if (Fl::event_state(FL_SHIFT)) backtab = 1; + // find current child: + Fl_Type *i = Fl_Type::current; + while (i && (!i->is_widget() || i->is_menu_item())) i = i->parent; + if (!i) return 0; + Fl_Type *p = i->parent; + while (p && p != this) p = p->parent; + if (!p || !p->is_widget()) { + i = next; if (!i || i->level <= level) return 0; + } + p = i; + for (;;) { + i = backtab ? i->prev : i->next; + if (!i || i->level <= level) {i = p; break;} + if (i->is_widget() && !i->is_menu_item()) break; + } + deselect(); select(i,1); + return 1;} + + case FL_Left: dx = -1; dy = 0; goto ARROW; + case FL_Right: dx = +1; dy = 0; goto ARROW; + case FL_Up: dx = 0; dy = -1; goto ARROW; + case FL_Down: dx = 0; dy = +1; goto ARROW; + ARROW: + // for some reason BOTTOM/TOP are swapped... should be fixed... + drag = (Fl::event_state(FL_SHIFT)) ? (RIGHT|TOP) : DRAG; + if (Fl::event_state(FL_CTRL)) {dx *= gridx; dy *= gridy;} + moveallchildren(); + drag = 0; + return 1; + + case 'o': + toggle_overlays(0, 0); + break; + + default: + return 0; + }} + + case FL_SHORTCUT: { + in_this_only = this; // modifies how some menu items work. + const Fl_Menu_Item* m = Main_Menu->test_shortcut(); + if (m && m->callback()) m->do_callback(this->o); + in_this_only = 0; + return (m != 0);} + + default: + return 0; + } +} + +//////////////////////////////////////////////////////////////// + +#include <stdio.h> +#include "../src/flstring.h" + +void Fl_Window_Type::write_code1() { + Fl_Widget_Type::write_code1(); +} + +void Fl_Window_Type::write_code2() { + write_extra_code(); + if (modal) write_c("%so->set_modal();\n", indent()); + else if (non_modal) write_c("%so->set_non_modal();\n", indent()); + if (!((Fl_Window*)o)->border()) write_c("%so->clear_border();\n", indent()); + if (xclass) { + write_c("%so->xclass(", indent()); + write_cstring(xclass); + write_c(");\n"); + } + if (sr_max_w || sr_max_h) { + write_c("%so->size_range(%d, %d, %d, %d);\n", indent(), sr_min_w, sr_min_h, sr_max_w, sr_max_h); + } else if (sr_min_w || sr_min_h) { + write_c("%so->size_range(%d, %d);\n", indent(), sr_min_w, sr_min_h); + } + write_c("%so->end();\n", indent()); + if (((Fl_Window*)o)->resizable() == o) + write_c("%so->resizable(o);\n", indent()); + write_block_close(); +} + +void Fl_Window_Type::write_properties() { + Fl_Widget_Type::write_properties(); + if (modal) write_string("modal"); + else if (non_modal) write_string("non_modal"); + if (!((Fl_Window*)o)->border()) write_string("noborder"); + if (xclass) {write_string("xclass"); write_word(xclass);} + if (sr_min_w || sr_min_h || sr_max_w || sr_max_h) + write_string("size_range {%d %d %d %d}", sr_min_w, sr_min_h, sr_max_w, sr_max_h); + if (o->visible()) write_string("visible"); +} + +extern int pasteoffset; +void Fl_Window_Type::read_property(const char *c) { + if (!strcmp(c,"modal")) { + modal = 1; + } else if (!strcmp(c,"non_modal")) { + non_modal = 1; + } else if (!strcmp(c, "visible")) { + if (Fl::first_window()) open(); // only if we are using user interface + } else if (!strcmp(c,"noborder")) { + ((Fl_Window*)o)->border(0); + } else if (!strcmp(c,"xclass")) { + storestring(read_word(),xclass); + ((Fl_Window*)o)->xclass(xclass); + } else if (!strcmp(c,"size_range")) { + int mw, mh, MW, MH; + if (sscanf(read_word(),"%d %d %d %d",&mw,&mh,&MW,&MH) == 4) { + sr_min_w = mw; sr_min_h = mh; sr_max_w = MW; sr_max_h = MH; + } + } else if (!strcmp(c,"xywh")) { + Fl_Widget_Type::read_property(c); + pasteoffset = 0; // make it not apply to contents + } else { + Fl_Widget_Type::read_property(c); + } +} + +int Fl_Window_Type::read_fdesign(const char* propname, const char* value) { + int x; + o->box(FL_NO_BOX); // because fdesign always puts an Fl_Box next + if (!strcmp(propname,"Width")) { + if (sscanf(value,"%d",&x) == 1) o->size(x,o->h()); + } else if (!strcmp(propname,"Height")) { + if (sscanf(value,"%d",&x) == 1) o->size(o->w(),x); + } else if (!strcmp(propname,"NumberofWidgets")) { + return 1; // we can figure out count from file + } else if (!strcmp(propname,"border")) { + if (sscanf(value,"%d",&x) == 1) ((Fl_Window*)o)->border(x); + } else if (!strcmp(propname,"title")) { + label(value); + } else { + return Fl_Widget_Type::read_fdesign(propname,value); + } + return 1; +} + +/////////////////////////////////////////////////////////////////////// + +Fl_Widget_Class_Type Fl_Widget_Class_type; +Fl_Widget_Class_Type *current_widget_class = 0; + +Fl_Type *Fl_Widget_Class_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_decl_block()) p = p->parent; + Fl_Widget_Class_Type *myo = new Fl_Widget_Class_Type(); + myo->name("UserInterface"); + + if (!this->o) {// template widget + this->o = new Fl_Window(100,100); + Fl_Group::current(0); + } + // Set the size ranges for this window; in order to avoid opening the + // X display we use an arbitrary maximum size... + ((Fl_Window *)(this->o))->size_range(gridx, gridy, + 3072, 2048, + gridx, gridy, 0); + myo->factory = this; + myo->drag = 0; + myo->numselected = 0; + Overlay_Window *w = new Overlay_Window(100,100); + w->window = myo; + myo->o = w; + myo->add(p); + myo->modal = 0; + myo->non_modal = 0; + myo->wc_relative = 0; + + return myo; +} + +void Fl_Widget_Class_Type::write_properties() { + Fl_Window_Type::write_properties(); + if (wc_relative) write_string("position_relative"); +} + +void Fl_Widget_Class_Type::read_property(const char *c) { + if (!strcmp(c,"position_relative")) { + wc_relative = 1; + } else { + Fl_Window_Type::read_property(c); + } +} + +void Fl_Widget_Class_Type::write_code1() { +#if 0 + Fl_Widget_Type::write_code1(); +#endif // 0 + + current_widget_class = this; + write_public_state = 1; + + const char *c = subclass(); + if (!c) c = "Fl_Group"; + + write_h("\nclass %s : public %s {\n", name(), c); + if (!strcmp(c, "Fl_Window") || + !strcmp(c, "Fl_Double_Window") || + !strcmp(c, "Fl_Gl_Window") || + !strcmp(c, "Fl_Overlay_Window")) { + write_h(" void _%s();\n", name()); + write_h("public:\n"); + write_h(" %s(int X, int Y, int W, int H, const char *L = 0);\n", name()); + write_h(" %s(int W, int H, const char *L = 0);\n", name()); + + write_c("%s::%s(int X, int Y, int W, int H, const char *L)\n", name(), name()); + write_c(" : %s(X, Y, W, H, L) {\n", c); + write_c(" _%s();\n", name()); + write_c("}\n\n"); + + write_c("%s::%s(int W, int H, const char *L)\n", name(), name()); + write_c(" : %s(0, 0, W, H, L) {\n", c); + write_c(" clear_flag(16);\n"); + write_c(" _%s();\n", name()); + write_c("}\n\n"); + + write_c("void %s::_%s() {\n", name(), name()); + write_c(" %s *w = this;\n", name()); + } else { + write_h("public:\n"); + write_h(" %s(int X, int Y, int W, int H, const char *L = 0);\n", name()); + + write_c("%s::%s(int X, int Y, int W, int H, const char *L)\n", name(), name()); + if (wc_relative) + write_c(" : %s(0, 0, W, H, L) {\n", c); + else + write_c(" : %s(X, Y, W, H, L) {\n", c); + } + + write_c(" %s *o = this;\n", name()); + + write_widget_code(); +} + +void Fl_Widget_Class_Type::write_code2() { + write_extra_code(); + if (wc_relative) write_c("%sposition(X, Y);\n", indent()); + if (modal) write_c("%sset_modal();\n", indent()); + else if (non_modal) write_c("%sset_non_modal();\n", indent()); + if (!((Fl_Window*)o)->border()) write_c("%sclear_border();\n", indent()); + if (xclass) { + write_c("%sxclass(", indent()); + write_cstring(xclass); + write_c(");\n"); + } + write_c("%send();\n", indent()); + if (((Fl_Window*)o)->resizable() == o) + write_c("%sresizable(this);\n", indent()); + write_c("}\n"); +} + +//////////////////////////////////////////////////////////////// +// live mode support + +Fl_Widget *Fl_Window_Type::enter_live_mode(int top) { + Fl_Window *win = new Fl_Window(o->x(), o->y(), o->w(), o->h()); + live_widget = win; + if (live_widget) { + copy_properties(); + Fl_Type *n; + for (n = next; n && n->level > level; n = n->next) { + if (n->level == level+1) + n->enter_live_mode(); + } + win->end(); + } + return live_widget; +} + +void Fl_Window_Type::leave_live_mode() { +} + +/** + * copy all properties from the edit widget to the live widget + */ +void Fl_Window_Type::copy_properties() { + Fl_Widget_Type::copy_properties(); + /// \todo copy resizing constraints over +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/Fluid_Image.cxx b/Utilities/FLTK/fluid/Fluid_Image.cxx new file mode 100644 index 0000000000..fba6a9f9c2 --- /dev/null +++ b/Utilities/FLTK/fluid/Fluid_Image.cxx @@ -0,0 +1,229 @@ +// +// "$Id$" +// +// Pixmap label support for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Widget.H> +#include "Fl_Type.h" +#include "Fluid_Image.h" +#include "../src/flstring.h" +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <FL/filename.H> + +extern void goto_source_dir(); // in fluid.C +extern void leave_source_dir(); // in fluid.C + +void Fluid_Image::image(Fl_Widget *o) { + if (o->window() != o) o->image(img); +} + +void Fluid_Image::deimage(Fl_Widget *o) { + if (o->window() != o) o->deimage(img); +} + +static int pixmap_header_written = 0; +static int bitmap_header_written = 0; +static int image_header_written = 0; + +void Fluid_Image::write_static() { + if (!img) return; + if (img->count() > 1) { + // Write Pixmap data... + write_c("\n"); + if (pixmap_header_written != write_number) { + write_c("#include <FL/Fl_Pixmap.H>\n"); + pixmap_header_written = write_number; + } + write_c("static const char *%s[] = {\n", + unique_id(this, "idata", fl_filename_name(name()), 0)); + write_cstring(img->data()[0], strlen(img->data()[0])); + + int i; + int ncolors, chars_per_color; + sscanf(img->data()[0], "%*d%*d%d%d", &ncolors, &chars_per_color); + + if (ncolors < 0) { + write_c(",\n"); + write_cstring(img->data()[1], ncolors * -4); + i = 2; + } else { + for (i = 1; i <= ncolors; i ++) { + write_c(",\n"); + write_cstring(img->data()[i], strlen(img->data()[i])); + } + } + for (; i < img->count(); i ++) { + write_c(",\n"); + write_cstring(img->data()[i], img->w() * chars_per_color); + } + write_c("\n};\n"); + write_c("static Fl_Pixmap %s(%s);\n", + unique_id(this, "image", fl_filename_name(name()), 0), + unique_id(this, "idata", fl_filename_name(name()), 0)); + } else if (img->d() == 0) { + // Write Bitmap data... + write_c("\n"); + if (bitmap_header_written != write_number) { + write_c("#include <FL/Fl_Bitmap.H>\n"); + bitmap_header_written = write_number; + } + write_c("static unsigned char %s[] =\n", + unique_id(this, "idata", fl_filename_name(name()), 0)); + write_cdata(img->data()[0], ((img->w() + 7) / 8) * img->h()); + write_c(";\n"); + write_c("static Fl_Bitmap %s(%s, %d, %d);\n", + unique_id(this, "image", fl_filename_name(name()), 0), + unique_id(this, "idata", fl_filename_name(name()), 0), + img->w(), img->h()); + } else { + // Write image data... + write_c("\n"); + if (image_header_written != write_number) { + write_c("#include <FL/Fl_Image.H>\n"); + image_header_written = write_number; + } + write_c("static unsigned char %s[] =\n", + unique_id(this, "idata", fl_filename_name(name()), 0)); + write_cdata(img->data()[0], (img->w() * img->d() + img->ld()) * img->h()); + write_c(";\n"); + write_c("static Fl_RGB_Image %s(%s, %d, %d, %d, %d);\n", + unique_id(this, "image", fl_filename_name(name()), 0), + unique_id(this, "idata", fl_filename_name(name()), 0), + img->w(), img->h(), img->d(), img->ld()); + } +} + +void Fluid_Image::write_code(int inactive) { + if (!img) return; + write_c("%so->%s(%s);\n", indent(), inactive ? "deimage" : "image", + unique_id(this, "image", fl_filename_name(name()), 0)); +} + + +//////////////////////////////////////////////////////////////// + +static Fluid_Image** images = 0; // sorted list +static int numimages = 0; +static int tablesize = 0; + +Fluid_Image* Fluid_Image::find(const char *iname) { + if (!iname || !*iname) return 0; + + // first search to see if it exists already: + int a = 0; + int b = numimages; + while (a < b) { + int c = (a+b)/2; + int i = strcmp(iname,images[c]->name_); + if (i < 0) b = c; + else if (i > 0) a = c+1; + else return images[c]; + } + + // no, so now see if the file exists: + + goto_source_dir(); + FILE *f = fopen(iname,"rb"); + if (!f) { + read_error("%s : %s",iname,strerror(errno)); + leave_source_dir(); + return 0; + } + fclose(f); + + Fluid_Image *ret = new Fluid_Image(iname); + + if (!ret->img || !ret->img->w() || !ret->img->h()) { + delete ret; + ret = 0; + read_error("%s : unrecognized image format", iname); + } + leave_source_dir(); + if (!ret) return 0; + + // make a new entry in the table: + numimages++; + if (numimages > tablesize) { + tablesize = tablesize ? 2*tablesize : 16; + if (images) images = (Fluid_Image**)realloc(images, tablesize*sizeof(Fluid_Image*)); + else images = (Fluid_Image**)malloc(tablesize*sizeof(Fluid_Image*)); + } + for (b = numimages-1; b > a; b--) images[b] = images[b-1]; + images[a] = ret; + + return ret; +} + +Fluid_Image::Fluid_Image(const char *iname) { + name_ = strdup(iname); + written = 0; + refcount = 0; + img = Fl_Shared_Image::get(iname); +} + +void Fluid_Image::increment() { + ++refcount; +} + +void Fluid_Image::decrement() { + --refcount; + if (refcount > 0) return; + delete this; +} + +Fluid_Image::~Fluid_Image() { + int a; + if (images) { + for (a = 0;; a++) if (images[a] == this) break; + numimages--; + for (; a < numimages; a++) images[a] = images[a+1]; + } + if (img) img->release(); + free((void*)name_); +} + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_File_Chooser.H> + +const char *ui_find_image_name; +Fluid_Image *ui_find_image(const char *oldname) { + goto_source_dir(); + fl_file_chooser_ok_label("Use Image"); + const char *name = fl_file_chooser("Image?","Image Files (*.{bm,bmp,gif,jpg,pbm,pgm,png,ppm,xbm,xpm})",oldname,1); + fl_file_chooser_ok_label(NULL); + ui_find_image_name = name; + Fluid_Image *ret = (name && *name) ? Fluid_Image::find(name) : 0; + leave_source_dir(); + return ret; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/Fluid_Image.h b/Utilities/FLTK/fluid/Fluid_Image.h new file mode 100644 index 0000000000..128c61ffee --- /dev/null +++ b/Utilities/FLTK/fluid/Fluid_Image.h @@ -0,0 +1,66 @@ +// +// "$Id$" +// +// Image header file for the Fast Light Tool Kit (FLTK). +// +// This class stores the image labels for widgets in fluid. This is +// not a class in FLTK itself, and will produce different types of +// code depending on what the image type is. +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef FLUID_IMAGE_H +# define FLUID_IMAGE_H + +# include <FL/Fl_Shared_Image.H> + + +class Fluid_Image { + const char *name_; + int refcount; + Fl_Shared_Image *img; +protected: + Fluid_Image(const char *name); // no public constructor + ~Fluid_Image(); // no public destructor +public: + int written; + static Fluid_Image* find(const char *); + void decrement(); // reference counting & automatic free + void increment(); + void image(Fl_Widget *); // set the image of this widget + void deimage(Fl_Widget *); // set the deimage of this widget + void write_static(); + void write_code(int inactive = 0); + const char *name() const {return name_;} +}; + +// pop up file chooser and return a legal image selected by user, +// or zero for any errors: +Fluid_Image *ui_find_image(const char *); +extern const char *ui_find_image_name; + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/Makefile b/Utilities/FLTK/fluid/Makefile new file mode 100644 index 0000000000..18f4716680 --- /dev/null +++ b/Utilities/FLTK/fluid/Makefile @@ -0,0 +1,137 @@ +# +# "$Id: Makefile 4759 2006-01-15 19:26:08Z mike $" +# +# FLUID makefile for the Fast Light Tool Kit (FLTK). +# +# Copyright 1998-2005 by Bill Spitzak and others. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. +# +# Please report all bugs and problems on the following page: +# +# http://www.fltk.org/str.php +# + +CPPFILES = \ + CodeEditor.cxx \ + Fl_Function_Type.cxx \ + Fl_Group_Type.cxx \ + Fl_Menu_Type.cxx \ + Fl_Type.cxx \ + Fl_Widget_Type.cxx \ + Fl_Window_Type.cxx \ + Fluid_Image.cxx \ + about_panel.cxx \ + align_widget.cxx \ + alignment_panel.cxx \ + code.cxx \ + factory.cxx \ + file.cxx \ + fluid.cxx \ + function_panel.cxx \ + template_panel.cxx \ + undo.cxx \ + widget_panel.cxx + +################################################################ + +OBJECTS = $(CPPFILES:.cxx=.o) + +include ../makeinclude + +all: $(FLUID) fluid$(EXEEXT) + +fluid$(EXEEXT): $(OBJECTS) ../lib/$(LIBNAME) ../lib/$(FLLIBNAME) \ + ../lib/$(IMGLIBNAME) + echo Linking $@... + $(CXX) $(CXXFLAGS) -o $@ $(OBJECTS) $(LINKFLTKFORMS) $(LINKFLTKIMG) $(LDLIBS) + $(POSTBUILD) $@ ../FL/mac.r + $(CP) $@ fluid.app/Contents/MacOS + +fluid-shared$(EXEEXT): $(OBJECTS) ../src/$(DSONAME) ../src/$(FLDSONAME) \ + ../src/$(IMGDSONAME) + echo Linking $@... + $(CXX) $(CXXFLAGS) -o $@ $(OBJECTS) $(LINKSHARED) $(LDLIBS) + $(POSTBUILD) $@ ../FL/mac.r + +clean: + -$(RM) *.o core.* *~ *.bck *.bck + -$(RM) core fluid$(EXEEXT) fluid-shared$(EXEEXT) + +depend: $(CPPFILES) + makedepend -Y -I.. -f makedepend $(CPPFILES) + +# Automatically generated dependencies... +include makedepend + +install: all + echo "Installing FLUID in $(DESTDIR)$(bindir)..." + -$(MKDIR) $(DESTDIR)$(bindir) + $(CP) $(FLUID) $(DESTDIR)$(bindir)/fluid$(EXEEXT) + $(STRIP) $(DESTDIR)$(bindir)/fluid$(EXEEXT) + $(DESTDIR)$(bindir)/fltk-config --post $(DESTDIR)$(bindir)/fluid$(EXEEXT) + $(CHMOD) 755 $(DESTDIR)$(bindir)/fluid$(EXEEXT) + +install-linux: + -$(MKDIR) $(DESTDIR)/usr/share/applnk/Development + $(CP) fluid.desktop $(DESTDIR)/usr/share/applnk/Development + for size in 16 32 48 64 128; do \ + if test ! -d $(DESTDIR)/usr/share/icons/hicolor/$${size}x$${size}/apps; then \ + $(MKDIR) $(DESTDIR)/usr/share/icons/hicolor/$${size}x$${size}/apps; \ + fi; \ + $(CP) icons/fluid-$$size.png $(DESTDIR)/usr/share/icons/hicolor/$${size}x$${size}/apps/fluid.png; \ + done + -$(MKDIR) $(DESTDIR)/usr/share/mimelnk/application + $(CP) x-fluid.desktop $(DESTDIR)/usr/share/mimelnk/application + +install-osx: + -$(MKDIR) $(DESTDIR)/Applications/fluid.app + -$(MKDIR) $(DESTDIR)/Applications/fluid.app/Contents + $(CP) fluid.app/Contents/Info.plist $(DESTDIR)/Applications/fluid.app/Contents/Info.plist + $(CP) fluid.app/Contents/PkgInfo $(DESTDIR)/Applications/fluid.app/Contents/PkgInfo + -$(MKDIR) $(DESTDIR)/Applications/fluid.app/Contents/MacOS + $(LN) $(bindir)/fluid $(DESTDIR)/Application/fluid.app/Contents/MacOS/fluid + -$(MKDIR) $(DESTDIR)/Applications/fluid.app/Contents/Resources + $(CP) fluid.app/Contents/Resources/fluid.icns $(DESTDIR)/Applications/fluid.app/Contents/Resources + +uninstall: + $(RM) $(DESTDIR)$(bindir)/fluid$(EXEEXT) + +uninstall-linux: + $(RM) $(DESTDIR)/usr/share/applnk/Development/fluid.desktop + $(RM) $(DESTDIR)/usr/share/icons/hicolor/*/fluid.png + $(RM) $(DESTDIR)/usr/share/mimelnk/application/x-fluid.desktop + +uninstall-osx: + $(RM) -r $(DESTDIR)/Applications/fluid.app + + +# +# Note: The rebuild target can only be used if you have the original .fl +# files. This is normally only used by the FLTK maintainers... +# + +rebuild: + ./fluid -c about_panel.fl + ./fluid -c alignment_panel.fl + ./fluid -c function_panel.fl + ./fluid -c print_panel.fl + ./fluid -c template_panel.fl + ./fluid -c widget_panel.fl + +# +# End of "$Id: Makefile 4759 2006-01-15 19:26:08Z mike $". +# diff --git a/Utilities/FLTK/fluid/Shortcut_Button.h b/Utilities/FLTK/fluid/Shortcut_Button.h new file mode 100644 index 0000000000..82e40e185d --- /dev/null +++ b/Utilities/FLTK/fluid/Shortcut_Button.h @@ -0,0 +1,41 @@ +// +// "$Id$" +// +// Shortcut header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl_Button.H> + +class Shortcut_Button : public Fl_Button { +public: + int svalue; + int handle(int); + void draw(); + Shortcut_Button(int X,int Y,int W,int H, const char* l = 0) : + Fl_Button(X,Y,W,H,l) {svalue = 0;} +}; + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/about_panel.cxx b/Utilities/FLTK/fluid/about_panel.cxx new file mode 100644 index 0000000000..fd559c7506 --- /dev/null +++ b/Utilities/FLTK/fluid/about_panel.cxx @@ -0,0 +1,308 @@ +// +// "$Id$" +// +// About dialog for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2006 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// generated by Fast Light User Interface Designer (fluid) version 1.0107 + +#include "about_panel.h" +void show_help(const char *name); + +Fl_Double_Window *about_panel=(Fl_Double_Window *)0; + +#include <FL/Fl_Pixmap.H> +static const char *idata_fluid[] = { +"96 96 32 1", +" \tc None", +".\tc #000100", +"+\tc #031F3F", +"@\tc #00366C", +"#\tc #2E302D", +"$\tc #0058AC", +"%\tc #0060BF", +"&\tc #4E504D", +"*\tc #14659F", +"=\tc #006DDC", +"-\tc #2C7087", +";\tc #0080FF", +">\tc #407B74", +",\tc #0F85F9", +"\'\tc #268CCD", +")\tc #7C7E7B", +"!\tc #2D92EC", +"~\tc #4498A9", +"{\tc #2F94FE", +"]\tc #5BA18C", +"^\tc #6BA674", +"/\tc #7DAD62", +"(\tc #93BD53", +"_\tc #A4A6A2", +":\tc #6CB6FF", +"<\tc #ABCC3F", +"[\tc #C4DA2A", +"}\tc #CACCC9", +"|\tc #DCE913", +"1\tc #BBDEFF", +"2\tc #FDFE00", +"3\tc #FDFFFC", +" \ + ", +" \ + ", +" \ + ", +" ........... \ + ", +" ...................... \ + ", +" ........................ \ + ", +" ........#&#&#&#&##...... \ + ", +" ....)__}33333333333}_... \ + ", +" ...&33333333333333333... \ + ", +" ...#33311133333333333... \ + ", +" ...&33!,{,;:333333333... \ + ", +" ...&3:,{{{{,13333333}... \ + ", +" ...&3!{{!{{,13333333}... \ + ", +" ...&3:!{{!{;13333333}... \ + ", +" ...&3{{{{{{;133333333... \ + ", +" ...&31,{{{;,33333333}... \ + ", +" ...&331{{{:133333333}... \ + ", +" ...&3333333333333333_... \ + ", +" ...&3333333333333333}... \ + ", +" ...&3333333333333333_... \ + ", +" ...&3333333333333333}... \ + ", +" ...&3333333333333333_... \ + ", +" ...&3333333333333333}... \ + ", +" ...&3333333333333333_... \ + ", +" ...&3333333331!,,;:3}... \ + ", +" ...&333333333{{{{{;:_... \ + ", +" ...&333333331,{!{!{{}... \ + ", +" ...&333333331{{{{{{,_... \ + ", +" ...)333333331{{!{{{{_... \ + ", +" ...)333333333{{{!{;:_... \ + ", +" ...)3333333331{;;;:3_... \ + ", +" ...)3333333333331333_... \ + ", +" ...)3333333333333333_... \ + ", +" ...)3333333333333333_... \ + ", +" ..._3333333333333333_... \ + ", +" ..._3333333333333333_... \ + ", +" ..._3333333333333333_... \ + ", +" ..._3333333333333333}.... \ + ", +" ...._33333333333333333#... \ + ", +" ....&333333333333333333_.... \ + ", +" ....&33333333333333333333).... \ + ", +" ....333333333333333333333}&.... \ + ", +" ...._33333333333333333333333.... \ + ", +" ....&333333333331:11333333333_.... \ + ", +" ....#33333333333:,,,;:333333333&.... \ + ", +" ....}3333333333:,!{{{;1333333333&.... \ + ", +" ....}33333333333{{{!{{,!3333333333.... \ + ", +" ....)333333333333{{{{!{{{3333333333_.... \ + ", +" ....#3333333333333!{{{{{,:33333333333&.... \ + ", +" ...._33333333333331{{!{,;1333333333333#.... \ + ", +" ...._333333333333333:;,;,13333333333333_.... \ + ", +" ...._333333333333333333113333333333333333_.... \ + ", +" ....&33333333333333333333333333331::1333333&.... \ + ", +" ...._333333333333333333333333333{,{{;{133333#... \ + ", +" ...._3333333333333333333333333331,{!{{,:33333}.... \ + ", +" ....&3333333333133333333333333333:{{{{{{:333333).... \ + ", +" ...#333333331{,,;:333333333333333:{!{!{{:3333333&.... \ + ", +" ....}33333333,{{{{;:333333333333331,{!{{;:33333333#... \ + ", +" ...._333333331,!{!{{,333333333333333{,{{;{1333333333.... \ + ", +" ....&3333333331{{{{{{{3333333333333333::::33333333333)....\ + ", +" ....+!:::::::::{{{{!{{;::::::::::::::::::::::::::!:::::+...\ +. ", +" ...+=;;;;;;;;;;;;{{{{;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=...\ +. ", +" ....%;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%..\ +.. ", +" ....@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$.\ +... ", +" ...+%;;;;;;!!!;;;;;,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;!=;;;+\ +.... ", +" ....%;;;;;!([<|^~]^([%;;;;;;;;;;;;;;;;;,(<\'=;;;;;;;!^/<[|\'=;\ +;=+... ", +" ....$;;;;;\'|2>]22<|22[%=;;;;;;;;;;;;;;;;^22[%=;;;;;;!][22|%=;;\ +;$.... ", +" ....@;;;;;;[2[%^2|*[22(%=;;;;;;;;;;;;;;;,/22|$=;;;;;;;;<22<%=;;;\ +;$.... ", +" ....+=;;;;;~22^$%]~$|22>%=;;;;;;;;;;;;;;;;\'||^%=;;;;;;;,[22^$=;;\ +;;;+.... ", +" ....%;;;;;,[22-%===\'22|*==;;;;;;;;;;;;;;;;;;=%=;;;;;;;;\'22|*%=;\ +;;;;=+... ", +" ....$;;;;;;!22|$%;,;^22<$=;;;;;;;;;;;;;;;;;;===;;;;;;;;;^22|$==;;;\ +;;;%.... ", +" ....@;;;;;\'](22[^]=;;<22^$==!~]/~=;!]]~;;;;{\'~]==;;;;~<<]<22($=;;\ +;;;;;;@.... ", +" ....@;;;;;;]<|22|[<%;!|22-%\'[2222*=;/22(%;~|222(=;;;!<2|^[222>$=;;;\ +;;;;;;+.... ", +" ....=;;;;;;;,[22>$===~22|$==,[22[%=;[22]%=,!|22]%=;![2|*%]22|*==;;;;\ +;;;;;%+... ", +" ....@;;;;;;;;!|22*$=;;/22($=;,[22/$=\'222*%=;!|22-%;;<22>%=]22[$%;;;;\ +;;;;;;;=.... ", +" ....@;;;;;;;;;~22[*==;;[22>%=;\'22|-%,^22[$=;,~22[$%;]22<$%=(22/$=;;;;\ +;;;;;;;;@.... ", +" ....+;;;;;;;;;;^22<$=;;!222*$=;]22[$==[22/$=;;(22/$=![22]$=;|22-%=;;;;;\ +;;;;;;;;+... ", +" ....;;;;;;;;;;;<22^%=;;]22[$=;;(22/$=~222-%=;;[22>%=]22|$%;~22|$==;;;;;\ +;;;;;;;;;.... ", +" ....%;;;;;;;;;;;|22-%=;;(22/$=;{|22-%=<22|$%;;\'22|*%;<22<$==(22<$=;=;;;\ +;;;;;;;;;;$.... ", +" ....+;;;;;;;;;;;!222$==;,|22>%=;~22|$=]|22($=;;]22[$%,|22^%=!|22^$=;;;;;;\ +;;;;;;;;;;@.... ", +" ....+=;;;;;;;;;;;~22[$%;;\'22|*-/;]22($*[<22^$^=;(22/$(-222>$=(222->~;;;;;\ +;;;;;;;;;;;=+.... ", +" ...+;;;;;;;;;;;;;(22/$=;;]22|*<\'=(22/*[~[22>(]=;|22>//=|22/$^(|2|-[%=;;;;\ +;;;;;;;;;;;;=.... ", +" ....$;;;;;;;;;;;;;<22>%=;;]222|>==(222|^=|22|<%=;|222<%=(222|<-222|-==;;;;;\ +;;;;;;;;;;;;$.... ", +" ....@;;;;;;;;;;;;;!|2|$=;;;\'[2[>%=;\'|2[]%=/2|/$==;^2|(*%=!(2|($%<2[-%=;;;;\ +;;;;;;;;;;;;;;;@.... ", +"....@;;;;;;;;;;;;;;\'22($%;;;;=%%==;;;=%%%==;=%%==;;;=%===;;==%%====%%=,;;;;;\ +;;;;;;;;;;;;;;;+... ", +"...+=;;;;;;;;;;!\'=,]22-%=;;;;;;==;=;;;===;=;;===;;;;;===;;;;=;=,;;,=;=;;;;;;\ +;;;;;;;;;;;;;;;=....", +"...+;;;;;;;;;;;[2^=<2<$==;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\ +;;;;;;;;;;;;;;;+...", +"...+;;;;;;;;;;;22(\'2|*%=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\ +;;;;;;;;;;;;;;;;+...", +"...+;;;;;;;;;;;^|<[[-%=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\ +;;;;;;;;;;;;;;;+...", +"...+;;;;;;;;;;;;*~*%===;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\ +;;;;;;;;;;;;;;;@...", +"...+;;;;;;;;;;;;;====;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\ +;;;;;;;;;;;;;;;+...", +"....$=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\ +;;;;;;;;;;;;;=$....", +" .....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\ ++++++++++++++..... ", +" ............................................................................\ +................. ", +" ...........................................................................\ +................. ", +" ........................................................................\ +.............. " +}; +static Fl_Pixmap image_fluid(idata_fluid); + +static void cb_View(Fl_Button*, void*) { + show_help("license.html"); +} + +static void cb_Close(Fl_Return_Button* o, void*) { + ((Fl_Window*)(o->parent()))->hide(); +} + +Fl_Double_Window* make_about_panel() { + Fl_Double_Window* w; + { Fl_Double_Window* o = about_panel = new Fl_Double_Window(315, 175, "About FLUID"); + w = o; + o->color(FL_LIGHT1); + o->selection_color(FL_DARK1); + w->hotspot(o); + { Fl_Box* o = new Fl_Box(10, 10, 115, 120); + o->image(image_fluid); + } + { Fl_Box* o = new Fl_Box(135, 10, 170, 69, "FLTK User\nInterface Designer\nVersion 1.1.7"); + o->color((Fl_Color)12); + o->selection_color(FL_DARK1); + o->labelfont(1); + o->labelsize(18); + o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE); + } + { Fl_Box* o = new Fl_Box(135, 89, 170, 42, "Copyright 1998-2006 by\nBill Spitzak and others"); + o->align(132|FL_ALIGN_INSIDE); + } + { Fl_Button* o = new Fl_Button(89, 141, 123, 25, "View License..."); + o->labelcolor(FL_DARK_BLUE); + o->callback((Fl_Callback*)cb_View); + } + { Fl_Return_Button* o = new Fl_Return_Button(222, 141, 83, 25, "Close"); + o->callback((Fl_Callback*)cb_Close); + } + o->set_non_modal(); + o->end(); + } + return w; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/about_panel.fl b/Utilities/FLTK/fluid/about_panel.fl new file mode 100644 index 0000000000..e068ba64dd --- /dev/null +++ b/Utilities/FLTK/fluid/about_panel.fl @@ -0,0 +1,74 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +comment {// +// "$Id: about_panel.fl 4748 2006-01-15 02:26:54Z mike $" +// +// About dialog for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2006 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +} {selected in_source in_header +} + +decl {void show_help(const char *name);} {public +} + +Function {make_about_panel()} {open +} { + Fl_Window about_panel { + label {About FLUID} open + xywh {391 113 315 175} type Double color 50 selection_color 47 hotspot non_modal visible + } { + Fl_Box {} { + image {icons/fluid-96.xpm} xywh {10 10 115 120} + } + Fl_Box {} { + label {FLTK User +Interface Designer +Version 1.1.7} + xywh {135 10 170 69} color 12 selection_color 47 labelfont 1 labelsize 18 align 21 + } + Fl_Box {} { + label {Copyright 1998-2006 by +Bill Spitzak and others} + xywh {135 89 170 42} align 148 + } + Fl_Button {} { + label {View License...} + callback {show_help("license.html");} + xywh {89 141 123 25} labelcolor 136 + } + Fl_Return_Button {} { + label Close + callback {((Fl_Window*)(o->parent()))->hide();} + xywh {222 141 83 25} + } + } +} + +comment { +// +// End of "$Id: about_panel.fl 4748 2006-01-15 02:26:54Z mike $". +//} {in_source in_header +} diff --git a/Utilities/FLTK/fluid/about_panel.h b/Utilities/FLTK/fluid/about_panel.h new file mode 100644 index 0000000000..829d6a1c62 --- /dev/null +++ b/Utilities/FLTK/fluid/about_panel.h @@ -0,0 +1,44 @@ +// +// "$Id$" +// +// About dialog for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2006 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// generated by Fast Light User Interface Designer (fluid) version 1.0107 + +#ifndef about_panel_h +#define about_panel_h +#include <FL/Fl.H> +extern void show_help(const char *name); +#include <FL/Fl_Double_Window.H> +extern Fl_Double_Window *about_panel; +#include <FL/Fl_Box.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Return_Button.H> +Fl_Double_Window* make_about_panel(); +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/align_widget.cxx b/Utilities/FLTK/fluid/align_widget.cxx new file mode 100644 index 0000000000..5d44028fd6 --- /dev/null +++ b/Utilities/FLTK/fluid/align_widget.cxx @@ -0,0 +1,541 @@ +// +// "$Id$" +// +// Alignment code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Window.H> +#include "Fl_Widget_Type.h" +#include "undo.h" + +/** + * the first behaviour always uses the first selected widget as a reference + * the second behaviour uses the largest widget (most extreme positions) as + * a reference. + */ +#define BREAK_ON_FIRST break +//#define BREAK_ON_FIRST + +void align_widget_cb(Fl_Widget*, long how) +{ + const int max = 32768, min = -32768; + int left, right, top, bot, wdt, hgt, n; + Fl_Type *o; + int changed = 0; + switch ( how ) + { + //---- align + case 10: // align left + left = max; + for (o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (w->x()<left) + left = w->x(); + BREAK_ON_FIRST; + } + if (left!=max) + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + if (!changed) { + changed = 1; + set_modflag(1); + undo_checkpoint(); + } + + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (o->next && o->next->level > o->level && !o->next->selected && + !o->is_menu_button()) { + // When resizing a group, make sure we also move the children... + ((igroup *)w)->full_resize(left, w->y(), w->w(), w->h()); + } else { + // Otherwise, just do the widget... + w->resize(left, w->y(), w->w(), w->h()); + } + w->redraw(); + if (w->window()) w->window()->redraw(); + } + break; + case 11: // align h.center + left = max; right = min; + for (o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (w->x()<left) + left = w->x(); + if (w->x()+w->w()>right) + right = w->x()+w->w(); + BREAK_ON_FIRST; + } + if (left!=max) + { + int center2 = left+right; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + if (!changed) { + changed = 1; + set_modflag(1); + undo_checkpoint(); + } + + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (o->next && o->next->level > o->level && !o->next->selected && + !o->is_menu_button()) { + // When resizing a group, make sure we also move the children... + ((igroup *)w)->full_resize((center2-w->w())/2, w->y(), w->w(), w->h()); + } else { + // Otherwise, just do the widget... + w->resize((center2-w->w())/2, w->y(), w->w(), w->h()); + } + w->redraw(); + if (w->window()) w->window()->redraw(); + } + } + break; + case 12: // align right + right = min; + for (o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (w->x()+w->w()>right) + right = w->x()+w->w(); + BREAK_ON_FIRST; + } + if (right!=min) + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + if (!changed) { + changed = 1; + set_modflag(1); + undo_checkpoint(); + } + + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (o->next && o->next->level > o->level && !o->next->selected && + !o->is_menu_button()) { + // When resizing a group, make sure we also move the children... + ((igroup *)w)->full_resize(right-w->w(), w->y(), w->w(), w->h()); + } else { + // Otherwise, just do the widget... + w->resize(right-w->w(), w->y(), w->w(), w->h()); + } + w->redraw(); + if (w->window()) w->window()->redraw(); + } + break; + case 13: // align top + top = max; + for (o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (w->y()<top) + top = w->y(); + BREAK_ON_FIRST; + } + if (top!=max) + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + if (!changed) { + changed = 1; + set_modflag(1); + undo_checkpoint(); + } + + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (o->next && o->next->level > o->level && !o->next->selected && + !o->is_menu_button()) { + // When resizing a group, make sure we also move the children... + ((igroup *)w)->full_resize(w->x(), top, w->w(), w->h()); + } else { + // Otherwise, just do the widget... + w->resize(w->x(), top, w->w(), w->h()); + } + w->redraw(); + if (w->window()) w->window()->redraw(); + } + break; + case 14: // align v.center + top = max; bot = min; + for (o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (w->y()<top) + top = w->y(); + if (w->y()+w->h()>bot) + bot = w->y()+w->h(); + BREAK_ON_FIRST; + } + if (top!=max) + { + int center2 = top+bot; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + if (!changed) { + changed = 1; + set_modflag(1); + undo_checkpoint(); + } + + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (o->next && o->next->level > o->level && !o->next->selected && + !o->is_menu_button()) { + // When resizing a group, make sure we also move the children... + ((igroup *)w)->full_resize(w->x(), (center2-w->h())/2, w->w(), w->h()); + } else { + // Otherwise, just do the widget... + w->resize(w->x(), (center2-w->h())/2, w->w(), w->h()); + } + w->redraw(); + if (w->window()) w->window()->redraw(); + } + } + break; + case 15: // align bottom + bot = min; + for (o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (w->y()+w->h()>bot) + bot = w->y()+w->h(); + BREAK_ON_FIRST; + } + if (bot!=min) + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + if (!changed) { + changed = 1; + set_modflag(1); + undo_checkpoint(); + } + + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (o->next && o->next->level > o->level && !o->next->selected && + !o->is_menu_button()) { + // When resizing a group, make sure we also move the children... + ((igroup *)w)->full_resize( w->x(), bot-w->h(), w->w(), w->h()); + } else { + // Otherwise, just do the widget... + w->resize( w->x(), bot-w->h(), w->w(), w->h()); + } + w->redraw(); + if (w->window()) w->window()->redraw(); + } + break; + //---- space evently + case 20: // space evenly across + left = max; right = min; wdt = 0, n = 0; + for (o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (w->x()<left) + left = w->x(); + if (w->x()+w->w()>right) + right = w->x()+w->w(); + wdt += w->w(); + n++; + } + wdt = (right-left)-wdt; + n--; + if (n>0) + { + int cnt = 0, wsum = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + if (!changed) { + changed = 1; + set_modflag(1); + undo_checkpoint(); + } + + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (o->next && o->next->level > o->level && !o->next->selected && + !o->is_menu_button()) { + // When resizing a group, make sure we also move the children... + ((igroup *)w)->full_resize(left+wsum+wdt*cnt/n, w->y(), w->w(), w->h()); + } else { + // Otherwise, just do the widget... + w->resize(left+wsum+wdt*cnt/n, w->y(), w->w(), w->h()); + } + w->redraw(); + if (w->window()) w->window()->redraw(); + cnt++; + wsum += w->w(); + } + } + break; + case 21: // space evenly down + top = max; bot = min; hgt = 0, n = 0; + for (o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (w->y()<top) + top = w->y(); + if (w->y()+w->h()>bot) + bot = w->y()+w->h(); + hgt += w->h(); + n++; + } + hgt = (bot-top)-hgt; + n--; + if (n>0) + { + int cnt = 0, hsum = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + if (!changed) { + changed = 1; + set_modflag(1); + undo_checkpoint(); + } + + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (o->next && o->next->level > o->level && !o->next->selected && + !o->is_menu_button()) { + // When resizing a group, make sure we also move the children... + ((igroup *)w)->full_resize(w->x(), top+hsum+hgt*cnt/n, w->w(), w->h()); + } else { + // Otherwise, just do the widget... + w->resize(w->x(), top+hsum+hgt*cnt/n, w->w(), w->h()); + } + w->redraw(); + if (w->window()) w->window()->redraw(); + cnt++; + hsum += w->h(); + } + } + break; + //---- make same size + case 30: // same width + wdt = min; + for (o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (w->w()>wdt) + wdt = w->w(); + BREAK_ON_FIRST; + } + if (wdt!=min) + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + if (!changed) { + changed = 1; + set_modflag(1); + undo_checkpoint(); + } + + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (o->next && o->next->level > o->level && !o->next->selected && + !o->is_menu_button()) { + // When resizing a group, make sure we also move the children... + ((igroup *)w)->full_resize(w->x(), w->y(), wdt, w->h()); + } else { + // Otherwise, just do the widget... + w->resize(w->x(), w->y(), wdt, w->h()); + } + w->redraw(); + if (w->window()) w->window()->redraw(); + } + break; + case 31: // same height + hgt = min; + for (o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (w->h()>hgt) + hgt = w->h(); + BREAK_ON_FIRST; + } + if (hgt!=min) + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + if (!changed) { + changed = 1; + set_modflag(1); + undo_checkpoint(); + } + + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (o->next && o->next->level > o->level && !o->next->selected && + !o->is_menu_button()) { + // When resizing a group, make sure we also move the children... + ((igroup *)w)->full_resize( w->x(), w->y(), w->w(), hgt); + } else { + // Otherwise, just do the widget... + w->resize( w->x(), w->y(), w->w(), hgt); + } + w->redraw(); + if (w->window()) w->window()->redraw(); + } + break; + case 32: // same size + hgt = min; wdt = min; + for (o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (w->w()>wdt) + wdt = w->w(); + if (w->h()>hgt) + hgt = w->h(); + BREAK_ON_FIRST; + } + if (hgt!=min) + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + { + if (!changed) { + changed = 1; + set_modflag(1); + undo_checkpoint(); + } + + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + if (o->next && o->next->level > o->level && !o->next->selected && + !o->is_menu_button()) { + // When resizing a group, make sure we also move the children... + ((igroup *)w)->full_resize( w->x(), w->y(), wdt, hgt); + } else { + // Otherwise, just do the widget... + w->resize( w->x(), w->y(), wdt, hgt); + } + w->redraw(); + if (w->window()) w->window()->redraw(); + } + break; + //---- center in group + case 40: // center hor + for (o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget() && o->parent) + { + if (!changed) { + changed = 1; + set_modflag(1); + undo_checkpoint(); + } + + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + Fl_Widget *p = ((Fl_Widget_Type *)o->parent)->o; + int center2; + + if (w->window() == p) center2 = p->w(); + else center2 = 2*p->x()+p->w(); + + if (o->next && o->next->level > o->level && !o->next->selected && + !o->is_menu_button() && !o->is_menu_button()) { + // When resizing a group, make sure we also move the children... + ((igroup *)w)->full_resize((center2-w->w())/2, w->y(), w->w(), w->h()); + } else { + // Otherwise, just do the widget... + w->resize((center2-w->w())/2, w->y(), w->w(), w->h()); + } + w->redraw(); + if (w->window()) w->window()->redraw(); + } + break; + case 41: // center vert + for (o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget() && o->parent) + { + if (!changed) { + changed = 1; + set_modflag(1); + undo_checkpoint(); + } + + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + Fl_Widget *p = ((Fl_Widget_Type *)o->parent)->o; + int center2; + + if (w->window() == p) center2 = p->h(); + else center2 = 2*p->y()+p->h(); + + if (o->next && o->next->level > o->level && !o->next->selected && + !o->is_menu_button()) { + // When resizing a group, make sure we also move the children... + ((igroup *)w)->full_resize(w->x(), (center2-w->h())/2, w->w(), w->h()); + } else { + // Otherwise, just do the widget... + w->resize(w->x(), (center2-w->h())/2, w->w(), w->h()); + } + set_modflag(1); + w->redraw(); + if (w->window()) w->window()->redraw(); + } + break; + } +} + + +// Set sizes of selected widgets... +void widget_size_cb(Fl_Widget *, long size) { + // Update any selected widgets... + int changed = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->selected && o->is_widget()) { + if (!changed) { + changed = 1; + set_modflag(1); + undo_checkpoint(); + } + + Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + w->labelsize(size); + Fl_Font f; + int s = (int)size; + Fl_Color c; + ((Fl_Widget_Type *)o)->textstuff(2, f, s, c); + + w->redraw(); + // since this may be a major change, the whole window should be redrawn + if (w->window()) w->window()->redraw(); + } + } +} + + +// +// End of "$Id$". +// + diff --git a/Utilities/FLTK/fluid/alignment_panel.cxx b/Utilities/FLTK/fluid/alignment_panel.cxx new file mode 100644 index 0000000000..b0e0892761 --- /dev/null +++ b/Utilities/FLTK/fluid/alignment_panel.cxx @@ -0,0 +1,506 @@ +// +// "$Id$" +// +// Setting and shell dialogs for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// generated by Fast Light User Interface Designer (fluid) version 1.0107 + +#include "alignment_panel.h" + +Fl_Double_Window *project_window=(Fl_Double_Window *)0; + +static void cb_Close(Fl_Button*, void*) { + project_window->hide(); +} + +Fl_Input *header_file_input=(Fl_Input *)0; + +Fl_Input *code_file_input=(Fl_Input *)0; + +Fl_Light_Button *include_H_from_C_button=(Fl_Light_Button *)0; + +Fl_Choice *i18n_type_chooser=(Fl_Choice *)0; + +Fl_Menu_Item menu_i18n_type_chooser[] = { + {"None", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0}, + {"GNU gettext", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0}, + {"POSIX catgets", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +Fl_Input *i18n_include_input=(Fl_Input *)0; + +Fl_Input *i18n_file_input=(Fl_Input *)0; + +Fl_Input *i18n_set_input=(Fl_Input *)0; + +Fl_Input *i18n_function_input=(Fl_Input *)0; + +Fl_Double_Window* make_project_window() { + Fl_Double_Window* w; + { Fl_Double_Window* o = project_window = new Fl_Double_Window(345, 185, "Project Settings"); + w = o; + { Fl_Button* o = new Fl_Button(293, 156, 42, 20, "Close"); + o->tooltip("Close this dialog."); + o->labelsize(11); + o->callback((Fl_Callback*)cb_Close); + } + { Fl_Tabs* o = new Fl_Tabs(10, 10, 325, 138); + o->selection_color((Fl_Color)4); + o->labelsize(11); + { Fl_Group* o = new Fl_Group(10, 30, 325, 116, "Output"); + o->labelsize(11); + { Fl_Box* o = new Fl_Box(20, 40, 304, 15, "Use \"name.ext\" to set name or just \".ext\" to set extension."); + o->labelsize(11); + o->align(132|FL_ALIGN_INSIDE); + } + { Fl_Input* o = header_file_input = new Fl_Input(96, 60, 228, 20, "Header File:"); + o->tooltip("The name of the generated header file."); + o->box(FL_THIN_DOWN_BOX); + o->labelfont(1); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->callback((Fl_Callback*)header_input_cb, (void*)(1)); + o->when(FL_WHEN_CHANGED); + } + { Fl_Input* o = code_file_input = new Fl_Input(97, 85, 227, 20, "Code File:"); + o->tooltip("The name of the generated code file."); + o->box(FL_THIN_DOWN_BOX); + o->labelfont(1); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->callback((Fl_Callback*)code_input_cb, (void*)(1)); + o->when(FL_WHEN_CHANGED); + } + { Fl_Light_Button* o = include_H_from_C_button = new Fl_Light_Button(166, 110, 158, 20, "Include Header from Code"); + o->tooltip("Include the header file from the code file."); + o->value(1); + o->labelsize(11); + o->callback((Fl_Callback*)include_H_from_C_button_cb); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(10, 30, 325, 116, "Internationalization"); + o->labelsize(11); + o->hide(); + { Fl_Choice* o = i18n_type_chooser = new Fl_Choice(80, 42, 100, 20, "Use:"); + o->tooltip("Type of internationalization to use."); + o->box(FL_THIN_UP_BOX); + o->down_box(FL_BORDER_BOX); + o->labelfont(1); + o->labelsize(11); + o->textsize(11); + o->callback((Fl_Callback*)i18n_type_cb); + o->menu(menu_i18n_type_chooser); + } + { Fl_Input* o = i18n_include_input = new Fl_Input(80, 67, 245, 20, "#include:"); + o->tooltip("The include file for internationalization."); + o->box(FL_THIN_DOWN_BOX); + o->labelfont(1); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->callback((Fl_Callback*)i18n_text_cb); + } + { Fl_Input* o = i18n_file_input = new Fl_Input(80, 92, 245, 20, "File:"); + o->tooltip("The name of the message catalog."); + o->box(FL_THIN_DOWN_BOX); + o->labelfont(1); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->callback((Fl_Callback*)i18n_text_cb); + } + { Fl_Input* o = i18n_set_input = new Fl_Input(80, 117, 245, 20, "Set:"); + o->tooltip("The message set number."); + o->type(2); + o->box(FL_THIN_DOWN_BOX); + o->labelfont(1); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->callback((Fl_Callback*)i18n_text_cb); + } + { Fl_Input* o = i18n_function_input = new Fl_Input(80, 92, 245, 20, "Function:"); + o->tooltip("The function to call to internationalize the labels and tooltips."); + o->box(FL_THIN_DOWN_BOX); + o->labelfont(1); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->callback((Fl_Callback*)i18n_text_cb); + } + o->end(); + } + o->end(); + } + o->set_modal(); + o->end(); + } + return w; +} +Fl_Text_Buffer *shell_run_buffer; +void scheme_cb(Fl_Choice *, void *); + +Fl_Double_Window *settings_window=(Fl_Double_Window *)0; + +Fl_Choice *scheme_choice=(Fl_Choice *)0; + +Fl_Menu_Item menu_scheme_choice[] = { + {"Default", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, + {"None", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, + {"Plastic", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +Fl_Check_Button *tooltips_button=(Fl_Check_Button *)0; + +static void cb_tooltips_button(Fl_Check_Button*, void*) { + Fl_Tooltip::enable(tooltips_button->value()); +fluid_prefs.set("show_tooltips", tooltips_button->value()); +} + +Fl_Check_Button *completion_button=(Fl_Check_Button *)0; + +static void cb_completion_button(Fl_Check_Button*, void*) { + fluid_prefs.set("show_completion_dialogs", completion_button->value()); +} + +Fl_Check_Button *openlast_button=(Fl_Check_Button *)0; + +static void cb_openlast_button(Fl_Check_Button*, void*) { + fluid_prefs.set("open_previous_file", openlast_button->value()); +} + +Fl_Check_Button *prevpos_button=(Fl_Check_Button *)0; + +static void cb_prevpos_button(Fl_Check_Button*, void*) { + fluid_prefs.set("prev_window_pos", prevpos_button->value()); +} + +static void cb_Close1(Fl_Button*, void*) { + settings_window->hide(); +} + +Fl_Spinner *recent_spinner=(Fl_Spinner *)0; + +static void cb_recent_spinner(Fl_Spinner*, void*) { + fluid_prefs.set("recent_files", recent_spinner->value()); +load_history(); +} + +Fl_Double_Window* make_settings_window() { + Fl_Double_Window* w; + { Fl_Double_Window* o = settings_window = new Fl_Double_Window(340, 225, "GUI Settings"); + w = o; + { Fl_Choice* o = scheme_choice = new Fl_Choice(116, 10, 115, 25, "Scheme:"); + o->down_box(FL_BORDER_BOX); + o->labelfont(1); + o->callback((Fl_Callback*)scheme_cb); + o->menu(menu_scheme_choice); + int s; + fluid_prefs.get("scheme", s, 0); + scheme_choice->value(s); + scheme_cb(0, 0); + } + { Fl_Group* o = new Fl_Group(116, 45, 215, 100, "Options:\n\n\n\n\n"); + o->labelfont(1); + o->align(FL_ALIGN_LEFT); + { Fl_Check_Button* o = tooltips_button = new Fl_Check_Button(116, 45, 113, 25, "Show Tooltips"); + o->down_box(FL_DOWN_BOX); + o->callback((Fl_Callback*)cb_tooltips_button); + int b; + fluid_prefs.get("show_tooltips", b, 1); + tooltips_button->value(b); + Fl_Tooltip::enable(b); + } + { Fl_Check_Button* o = completion_button = new Fl_Check_Button(116, 70, 186, 25, "Show Completion Dialogs"); + o->down_box(FL_DOWN_BOX); + o->callback((Fl_Callback*)cb_completion_button); + int b; + fluid_prefs.get("show_completion_dialogs", b, 1); + completion_button->value(b); + } + { Fl_Check_Button* o = openlast_button = new Fl_Check_Button(116, 95, 215, 25, "Open Previous File on Startup"); + o->down_box(FL_DOWN_BOX); + o->callback((Fl_Callback*)cb_openlast_button); + int b; + fluid_prefs.get("open_previous_file", b, 0); + openlast_button->value(b); + } + { Fl_Check_Button* o = prevpos_button = new Fl_Check_Button(116, 120, 210, 25, "Remember Window Positions"); + o->down_box(FL_DOWN_BOX); + o->callback((Fl_Callback*)cb_prevpos_button); + int b; + fluid_prefs.get("prev_window_pos", b, 1); + prevpos_button->value(b); + } + o->end(); + } + { Fl_Button* o = new Fl_Button(266, 190, 64, 25, "Close"); + o->tooltip("Close this dialog."); + o->callback((Fl_Callback*)cb_Close1); + } + { Fl_Spinner* o = recent_spinner = new Fl_Spinner(116, 155, 40, 25, "# Recent Files:"); + o->labelfont(1); + o->callback((Fl_Callback*)cb_recent_spinner); + o->when(FL_WHEN_CHANGED); + int c; + fluid_prefs.get("recent_files", c, 5); + recent_spinner->maximum(10); + recent_spinner->value(c); + } + o->set_non_modal(); + o->end(); + } + return w; +} + +Fl_Double_Window *shell_window=(Fl_Double_Window *)0; + +Fl_Input *shell_command_input=(Fl_Input *)0; + +static void cb_shell_command_input(Fl_Input*, void*) { + fluid_prefs.set("shell_command", shell_command_input->value()); +} + +Fl_Check_Button *shell_writecode_button=(Fl_Check_Button *)0; + +static void cb_shell_writecode_button(Fl_Check_Button*, void*) { + fluid_prefs.set("shell_writecode", shell_writecode_button->value()); +} + +Fl_Check_Button *shell_writemsgs_button=(Fl_Check_Button *)0; + +static void cb_shell_writemsgs_button(Fl_Check_Button*, void*) { + fluid_prefs.set("shell_writemsgs", shell_writemsgs_button->value()); +} + +Fl_Check_Button *shell_savefl_button=(Fl_Check_Button *)0; + +static void cb_shell_savefl_button(Fl_Check_Button*, void*) { + fluid_prefs.set("shell_savefl", shell_savefl_button->value()); +} + +static void cb_Cancel(Fl_Button*, void*) { + shell_window->hide(); +} + +Fl_Double_Window *shell_run_window=(Fl_Double_Window *)0; + +Fl_Text_Display *shell_run_display=(Fl_Text_Display *)0; + +Fl_Return_Button *shell_run_button=(Fl_Return_Button *)0; + +static void cb_shell_run_button(Fl_Return_Button*, void*) { + shell_run_window->hide(); +} + +Fl_Double_Window* make_shell_window() { + Fl_Double_Window* w; + { Fl_Double_Window* o = shell_window = new Fl_Double_Window(365, 125, "Shell Command"); + w = o; + { Fl_Input* o = shell_command_input = new Fl_Input(10, 27, 347, 25, "Command:"); + o->labelfont(1); + o->callback((Fl_Callback*)cb_shell_command_input); + o->align(FL_ALIGN_TOP_LEFT); + char buf[1024]; + fluid_prefs.get("shell_command", buf, "", sizeof(buf)); + shell_command_input->value(buf); + } + { Fl_Check_Button* o = shell_writecode_button = new Fl_Check_Button(128, 61, 93, 19, "Write Code"); + o->down_box(FL_DOWN_BOX); + o->callback((Fl_Callback*)cb_shell_writecode_button); + int b; + fluid_prefs.get("shell_writecode", b, 1); + shell_writecode_button->value(b); + } + { Fl_Check_Button* o = shell_writemsgs_button = new Fl_Check_Button(231, 61, 126, 19, "Write Messages"); + o->down_box(FL_DOWN_BOX); + o->callback((Fl_Callback*)cb_shell_writemsgs_button); + int b; + fluid_prefs.get("shell_writemsgs", b, 0); + shell_writemsgs_button->value(b); + } + { Fl_Check_Button* o = shell_savefl_button = new Fl_Check_Button(10, 62, 108, 19, "Save .FL File"); + o->down_box(FL_DOWN_BOX); + o->callback((Fl_Callback*)cb_shell_savefl_button); + int b; + fluid_prefs.get("shell_savefl", b, 1); + shell_savefl_button->value(b); + } + { Fl_Return_Button* o = new Fl_Return_Button(132, 90, 143, 25, "Run Command"); + o->callback((Fl_Callback*)do_shell_command); + } + { Fl_Button* o = new Fl_Button(285, 90, 72, 25, "Cancel"); + o->callback((Fl_Callback*)cb_Cancel); + } + o->end(); + } + { Fl_Double_Window* o = shell_run_window = new Fl_Double_Window(555, 430, "Shell Command Output"); + w = o; + { Fl_Text_Display* o = shell_run_display = new Fl_Text_Display(10, 10, 535, 375); + o->box(FL_DOWN_BOX); + o->textfont(4); + Fl_Group::current()->resizable(o); + shell_run_buffer = new Fl_Text_Buffer(); + shell_run_display->buffer(shell_run_buffer); + } + { Fl_Return_Button* o = shell_run_button = new Fl_Return_Button(468, 395, 77, 25, "Close"); + o->callback((Fl_Callback*)cb_shell_run_button); + } + o->end(); + } + return w; +} + +Fl_Double_Window *grid_window=(Fl_Double_Window *)0; + +Fl_Input *horizontal_input=(Fl_Input *)0; + +Fl_Input *vertical_input=(Fl_Input *)0; + +Fl_Input *snap_input=(Fl_Input *)0; + +Fl_Check_Button *guides_toggle=(Fl_Check_Button *)0; + +static void cb_Close2(Fl_Button*, void*) { + grid_window->hide(); +} + +Fl_Round_Button *def_widget_size[6]={(Fl_Round_Button *)0}; + +Fl_Double_Window* make_layout_window() { + Fl_Double_Window* w; + { Fl_Double_Window* o = grid_window = new Fl_Double_Window(285, 245, "Layout Settings"); + w = o; + { Fl_Input* o = horizontal_input = new Fl_Input(106, 10, 50, 25, "x"); + o->tooltip("Horizontal grid spacing."); + o->type(2); + o->box(FL_THIN_DOWN_BOX); + o->callback((Fl_Callback*)grid_cb, (void*)(1)); + o->align(FL_ALIGN_RIGHT); + o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY); + } + { Fl_Input* o = vertical_input = new Fl_Input(166, 10, 50, 25, "pixels"); + o->tooltip("Vertical grid spacing."); + o->type(2); + o->box(FL_THIN_DOWN_BOX); + o->callback((Fl_Callback*)grid_cb, (void*)(2)); + o->align(FL_ALIGN_RIGHT); + o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY); + } + { Fl_Input* o = snap_input = new Fl_Input(106, 45, 50, 25, "pixel snap"); + o->tooltip("Snap to grid within this many pixels."); + o->type(2); + o->box(FL_THIN_DOWN_BOX); + o->callback((Fl_Callback*)grid_cb, (void*)(3)); + o->align(FL_ALIGN_RIGHT); + o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY); + } + { Fl_Check_Button* o = guides_toggle = new Fl_Check_Button(106, 80, 110, 25, "Show Guides"); + o->tooltip("Show distance and alignment guides in overlay"); + o->down_box(FL_DOWN_BOX); + o->callback((Fl_Callback*)guides_cb, (void*)(4)); + } + { Fl_Button* o = new Fl_Button(215, 210, 60, 25, "Close"); + o->tooltip("Close this dialog."); + o->callback((Fl_Callback*)cb_Close2); + } + { Fl_Box* o = new Fl_Box(26, 10, 70, 25, "Grid:"); + o->labelfont(1); + o->align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE); + } + { Fl_Box* o = new Fl_Box(-1, 115, 97, 25, "Widget Size:"); + o->labelfont(1); + o->align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE); + } + { Fl_Group* o = new Fl_Group(105, 115, 170, 75); + { Fl_Round_Button* o = def_widget_size[0] = new Fl_Round_Button(105, 115, 70, 25); + o->type(102); + o->down_box(FL_ROUND_DOWN_BOX); + o->callback((Fl_Callback*)default_widget_size_cb, (void*)(8)); + } + { Fl_Box* o = new Fl_Box(120, 115, 50, 25, "tiny"); + o->labelsize(8); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + } + { Fl_Round_Button* o = def_widget_size[1] = new Fl_Round_Button(180, 115, 70, 25); + o->type(102); + o->down_box(FL_ROUND_DOWN_BOX); + o->callback((Fl_Callback*)default_widget_size_cb, (void*)(11)); + } + { Fl_Box* o = new Fl_Box(195, 115, 50, 25, "small"); + o->labelsize(11); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + } + { Fl_Round_Button* o = def_widget_size[2] = new Fl_Round_Button(105, 140, 70, 25); + o->type(102); + o->down_box(FL_ROUND_DOWN_BOX); + o->callback((Fl_Callback*)default_widget_size_cb, (void*)(14)); + } + { Fl_Box* o = new Fl_Box(120, 140, 50, 25, "normal"); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + } + { Fl_Round_Button* o = def_widget_size[3] = new Fl_Round_Button(180, 140, 90, 25); + o->type(102); + o->down_box(FL_ROUND_DOWN_BOX); + o->callback((Fl_Callback*)default_widget_size_cb, (void*)(18)); + } + { Fl_Box* o = new Fl_Box(195, 140, 68, 25, "medium"); + o->labelsize(18); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + } + { Fl_Round_Button* o = def_widget_size[4] = new Fl_Round_Button(105, 165, 75, 25); + o->type(102); + o->down_box(FL_ROUND_DOWN_BOX); + o->callback((Fl_Callback*)default_widget_size_cb, (void*)(24)); + } + { Fl_Box* o = new Fl_Box(120, 165, 64, 25, "large"); + o->labelsize(24); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + } + { Fl_Round_Button* o = def_widget_size[5] = new Fl_Round_Button(180, 165, 95, 25); + o->type(102); + o->down_box(FL_ROUND_DOWN_BOX); + o->callback((Fl_Callback*)default_widget_size_cb, (void*)(32)); + } + { Fl_Box* o = new Fl_Box(195, 165, 76, 25, "huge"); + o->labelsize(32); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + } + o->end(); + } + o->set_non_modal(); + o->end(); + } + return w; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/alignment_panel.fl b/Utilities/FLTK/fluid/alignment_panel.fl new file mode 100644 index 0000000000..34cfefa950 --- /dev/null +++ b/Utilities/FLTK/fluid/alignment_panel.fl @@ -0,0 +1,411 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +comment {// +// "$Id: alignment_panel.fl 4632 2005-11-03 22:16:52Z mike $" +// +// Setting and shell dialogs for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +} {in_source in_header +} + +decl {\#include <FL/Fl_Text_Buffer.H>} {public +} + +decl {\#include <FL/Fl_Text_Display.H>} {public +} + +decl {extern void load_history();} {public +} + +Function {make_project_window()} {open +} { + Fl_Window project_window { + label {Project Settings} + xywh {312 395 345 185} type Double + code0 {\#include <FL/Fl_Preferences.H>} + code1 {\#include <FL/Fl_Tooltip.H>} modal visible + } { + Fl_Button {} { + label Close + callback {project_window->hide();} + tooltip {Close this dialog.} xywh {293 156 42 20} labelsize 11 + } + Fl_Tabs {} {open + xywh {10 10 325 138} selection_color 4 labelsize 11 + } { + Fl_Group {} { + label Output open + xywh {10 30 325 116} labelsize 11 + } { + Fl_Box {} { + label {Use "name.ext" to set name or just ".ext" to set extension.} + xywh {20 40 304 15} labelsize 11 align 148 + } + Fl_Input header_file_input { + label {Header File:} + user_data 1 user_data_type {void*} + callback header_input_cb + tooltip {The name of the generated header file.} xywh {96 60 228 20} box THIN_DOWN_BOX labelfont 1 labelsize 11 when 1 textfont 4 textsize 11 + } + Fl_Input code_file_input { + label {Code File:} + user_data 1 user_data_type {void*} + callback code_input_cb + tooltip {The name of the generated code file.} xywh {97 85 227 20} box THIN_DOWN_BOX labelfont 1 labelsize 11 when 1 textfont 4 textsize 11 + } + Fl_Light_Button include_H_from_C_button { + label {Include Header from Code} + callback include_H_from_C_button_cb + tooltip {Include the header file from the code file.} xywh {166 110 158 20} value 1 labelsize 11 + } + } + Fl_Group {} { + label Internationalization open + xywh {10 30 325 116} labelsize 11 hide + } { + Fl_Choice i18n_type_chooser { + label {Use:} + callback i18n_type_cb open + tooltip {Type of internationalization to use.} xywh {80 42 100 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 + } { + MenuItem {} { + label None + xywh {0 0 100 20} labelsize 11 + } + MenuItem {} { + label {GNU gettext} + xywh {0 0 100 20} labelsize 11 + } + MenuItem {} { + label {POSIX catgets} + xywh {0 0 100 20} labelsize 11 + } + } + Fl_Input i18n_include_input { + label {\#include:} + callback i18n_text_cb + tooltip {The include file for internationalization.} xywh {80 67 245 20} box THIN_DOWN_BOX labelfont 1 labelsize 11 textfont 4 textsize 11 + } + Fl_Input i18n_file_input { + label {File:} + callback i18n_text_cb + tooltip {The name of the message catalog.} xywh {80 92 245 20} box THIN_DOWN_BOX labelfont 1 labelsize 11 textfont 4 textsize 11 + } + Fl_Input i18n_set_input { + label {Set:} + callback i18n_text_cb + tooltip {The message set number.} xywh {80 117 245 20} type Int box THIN_DOWN_BOX labelfont 1 labelsize 11 textfont 4 textsize 11 + } + Fl_Input i18n_function_input { + label {Function:} + callback i18n_text_cb + tooltip {The function to call to internationalize the labels and tooltips.} xywh {80 92 245 20} box THIN_DOWN_BOX labelfont 1 labelsize 11 textfont 4 textsize 11 + } + } + } + } +} + +decl {extern void i18n_cb(Fl_Choice *,void *);} {public +} + +decl {extern Fl_Preferences fluid_prefs;} {public +} + +decl {Fl_Text_Buffer *shell_run_buffer;} {public +} + +decl {void scheme_cb(Fl_Choice *, void *);} {public +} + +Function {make_settings_window()} {open +} { + Fl_Window settings_window { + label {GUI Settings} + xywh {326 145 340 225} type Double non_modal visible + } { + Fl_Choice scheme_choice { + label {Scheme:} + callback scheme_cb + xywh {116 10 115 25} down_box BORDER_BOX labelfont 1 + code0 {int s;} + code1 {fluid_prefs.get("scheme", s, 0);} + code2 {scheme_choice->value(s);} + code3 {scheme_cb(0, 0);} + } { + MenuItem {} { + label Default + xywh {0 0 35 25} + } + MenuItem {} { + label None + xywh {0 0 35 25} + } + MenuItem {} { + label Plastic + xywh {0 0 35 25} + } + } + Fl_Group {} { + label {Options: + + + + +} open + xywh {116 45 215 100} labelfont 1 align 4 + } { + Fl_Check_Button tooltips_button { + label {Show Tooltips} + callback {Fl_Tooltip::enable(tooltips_button->value()); +fluid_prefs.set("show_tooltips", tooltips_button->value());} + xywh {116 45 113 25} down_box DOWN_BOX + code0 {int b;} + code1 {fluid_prefs.get("show_tooltips", b, 1);} + code2 {tooltips_button->value(b);} + code3 {Fl_Tooltip::enable(b);} + } + Fl_Check_Button completion_button { + label {Show Completion Dialogs} + callback {fluid_prefs.set("show_completion_dialogs", completion_button->value());} + xywh {116 70 186 25} down_box DOWN_BOX + code0 {int b;} + code1 {fluid_prefs.get("show_completion_dialogs", b, 1);} + code2 {completion_button->value(b);} + } + Fl_Check_Button openlast_button { + label {Open Previous File on Startup} + callback {fluid_prefs.set("open_previous_file", openlast_button->value());} + xywh {116 95 215 25} down_box DOWN_BOX + code0 {int b;} + code1 {fluid_prefs.get("open_previous_file", b, 0);} + code2 {openlast_button->value(b);} + } + Fl_Check_Button prevpos_button { + label {Remember Window Positions} + callback {fluid_prefs.set("prev_window_pos", prevpos_button->value());} + xywh {116 120 210 25} down_box DOWN_BOX + code0 {int b;} + code1 {fluid_prefs.get("prev_window_pos", b, 1);} + code2 {prevpos_button->value(b);} + } + } + Fl_Button {} { + label Close + callback {settings_window->hide();} + tooltip {Close this dialog.} xywh {266 190 64 25} + } + Fl_Spinner recent_spinner { + label {\# Recent Files:} + callback {fluid_prefs.set("recent_files", recent_spinner->value()); +load_history();} + xywh {116 155 40 25} labelfont 1 when 1 + code0 {int c;} + code1 {fluid_prefs.get("recent_files", c, 5);} + code2 {recent_spinner->maximum(10);} + code3 {recent_spinner->value(c);} + } + } +} + +Function {make_shell_window()} {open +} { + Fl_Window shell_window { + label {Shell Command} + xywh {682 167 365 125} type Double visible + } { + Fl_Input shell_command_input { + label {Command:} + callback {fluid_prefs.set("shell_command", shell_command_input->value());} + xywh {10 27 347 25} labelfont 1 align 5 + code0 {char buf[1024];} + code1 {fluid_prefs.get("shell_command", buf, "", sizeof(buf));} + code2 {shell_command_input->value(buf);} + } + Fl_Check_Button shell_writecode_button { + label {Write Code} + callback {fluid_prefs.set("shell_writecode", shell_writecode_button->value());} + xywh {128 61 93 19} down_box DOWN_BOX + code0 {int b;} + code1 {fluid_prefs.get("shell_writecode", b, 1);} + code2 {shell_writecode_button->value(b);} + } + Fl_Check_Button shell_writemsgs_button { + label {Write Messages} + callback {fluid_prefs.set("shell_writemsgs", shell_writemsgs_button->value());} + xywh {231 61 126 19} down_box DOWN_BOX + code0 {int b;} + code1 {fluid_prefs.get("shell_writemsgs", b, 0);} + code2 {shell_writemsgs_button->value(b);} + } + Fl_Check_Button shell_savefl_button { + label {Save .FL File} + callback {fluid_prefs.set("shell_savefl", shell_savefl_button->value());} + xywh {10 62 108 19} down_box DOWN_BOX + code0 {int b;} + code1 {fluid_prefs.get("shell_savefl", b, 1);} + code2 {shell_savefl_button->value(b);} + } + Fl_Return_Button {} { + label {Run Command} + callback do_shell_command + xywh {132 90 143 25} + } + Fl_Button {} { + label Cancel + callback {shell_window->hide();} + xywh {285 90 72 25} + } + } + Fl_Window shell_run_window { + label {Shell Command Output} + xywh {592 332 555 430} type Double hide resizable + } { + Fl_Text_Display shell_run_display { + xywh {10 10 535 375} box DOWN_BOX textfont 4 resizable + code0 {shell_run_buffer = new Fl_Text_Buffer();} + code1 {shell_run_display->buffer(shell_run_buffer);} + } + Fl_Return_Button shell_run_button { + label Close + callback {shell_run_window->hide();} + xywh {468 395 77 25} + } + } +} + +Function {make_layout_window()} {open +} { + Fl_Window grid_window { + label {Layout Settings} selected + xywh {676 337 285 245} type Double non_modal visible + } { + Fl_Input horizontal_input { + label x + user_data 1 user_data_type long + callback grid_cb + tooltip {Horizontal grid spacing.} xywh {106 10 50 25} type Int box THIN_DOWN_BOX align 8 + code0 {o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);} + } + Fl_Input vertical_input { + label pixels + user_data 2 user_data_type long + callback grid_cb + tooltip {Vertical grid spacing.} xywh {166 10 50 25} type Int box THIN_DOWN_BOX align 8 + code0 {o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);} + } + Fl_Input snap_input { + label {pixel snap} + user_data 3 user_data_type long + callback grid_cb + tooltip {Snap to grid within this many pixels.} xywh {106 45 50 25} type Int box THIN_DOWN_BOX align 8 + code0 {o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);} + } + Fl_Check_Button guides_toggle { + label {Show Guides} + user_data 4 user_data_type long + callback guides_cb + tooltip {Show distance and alignment guides in overlay} xywh {106 80 110 25} down_box DOWN_BOX + } + Fl_Button {} { + label Close + callback {grid_window->hide();} + tooltip {Close this dialog.} xywh {215 210 60 25} + } + Fl_Box {} { + label {Grid:} + xywh {26 10 70 25} labelfont 1 align 24 + } + Fl_Box {} { + label {Widget Size:} + xywh {-1 115 97 25} labelfont 1 align 24 + } + Fl_Group {} {open + xywh {105 115 170 75} + } { + Fl_Round_Button {def_widget_size[0]} { + user_data 8 user_data_type long + callback default_widget_size_cb + xywh {105 115 70 25} type Radio down_box ROUND_DOWN_BOX + } + Fl_Box {} { + label tiny + xywh {120 115 50 25} labelsize 8 align 20 + } + Fl_Round_Button {def_widget_size[1]} { + user_data 11 user_data_type long + callback default_widget_size_cb + xywh {180 115 70 25} type Radio down_box ROUND_DOWN_BOX + } + Fl_Box {} { + label small + xywh {195 115 50 25} labelsize 11 align 20 + } + Fl_Round_Button {def_widget_size[2]} { + user_data 14 user_data_type long + callback default_widget_size_cb + xywh {105 140 70 25} type Radio down_box ROUND_DOWN_BOX + } + Fl_Box {} { + label normal + xywh {120 140 50 25} align 20 + } + Fl_Round_Button {def_widget_size[3]} { + user_data 18 user_data_type long + callback default_widget_size_cb + xywh {180 140 90 25} type Radio down_box ROUND_DOWN_BOX + } + Fl_Box {} { + label medium + xywh {195 140 68 25} labelsize 18 align 20 + } + Fl_Round_Button {def_widget_size[4]} { + user_data 24 user_data_type long + callback default_widget_size_cb + xywh {105 165 75 25} type Radio down_box ROUND_DOWN_BOX + } + Fl_Box {} { + label large + xywh {120 165 64 25} labelsize 24 align 20 + } + Fl_Round_Button {def_widget_size[5]} { + user_data 32 user_data_type long + callback default_widget_size_cb + xywh {180 165 95 25} type Radio down_box ROUND_DOWN_BOX + } + Fl_Box {} { + label huge + xywh {195 165 76 25} labelsize 32 align 20 + } + } + } +} + +comment { +// +// End of "$Id: alignment_panel.fl 4632 2005-11-03 22:16:52Z mike $". +//} {in_source in_header +} diff --git a/Utilities/FLTK/fluid/alignment_panel.h b/Utilities/FLTK/fluid/alignment_panel.h new file mode 100644 index 0000000000..a02bd462c3 --- /dev/null +++ b/Utilities/FLTK/fluid/alignment_panel.h @@ -0,0 +1,105 @@ +// +// "$Id$" +// +// Setting and shell dialogs for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// generated by Fast Light User Interface Designer (fluid) version 1.0107 + +#ifndef alignment_panel_h +#define alignment_panel_h +#include <FL/Fl.H> +#include <FL/Fl_Text_Buffer.H> +#include <FL/Fl_Text_Display.H> +extern void load_history(); +#include <FL/Fl_Double_Window.H> +#include <FL/Fl_Preferences.H> +#include <FL/Fl_Tooltip.H> +extern Fl_Double_Window *project_window; +#include <FL/Fl_Button.H> +#include <FL/Fl_Tabs.H> +#include <FL/Fl_Group.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Input.H> +extern void header_input_cb(Fl_Input*, void*); +extern Fl_Input *header_file_input; +extern void code_input_cb(Fl_Input*, void*); +extern Fl_Input *code_file_input; +#include <FL/Fl_Light_Button.H> +extern void include_H_from_C_button_cb(Fl_Light_Button*, void*); +extern Fl_Light_Button *include_H_from_C_button; +#include <FL/Fl_Choice.H> +extern void i18n_type_cb(Fl_Choice*, void*); +extern Fl_Choice *i18n_type_chooser; +extern void i18n_text_cb(Fl_Input*, void*); +extern Fl_Input *i18n_include_input; +extern Fl_Input *i18n_file_input; +extern Fl_Input *i18n_set_input; +extern Fl_Input *i18n_function_input; +Fl_Double_Window* make_project_window(); +extern Fl_Menu_Item menu_i18n_type_chooser[]; +extern void i18n_cb(Fl_Choice *,void *); +extern Fl_Preferences fluid_prefs; +extern Fl_Text_Buffer *shell_run_buffer; +extern void scheme_cb(Fl_Choice *, void *); +extern Fl_Double_Window *settings_window; +extern void scheme_cb(Fl_Choice*, void*); +extern Fl_Choice *scheme_choice; +#include <FL/Fl_Check_Button.H> +extern Fl_Check_Button *tooltips_button; +extern Fl_Check_Button *completion_button; +extern Fl_Check_Button *openlast_button; +extern Fl_Check_Button *prevpos_button; +#include <FL/Fl_Spinner.H> +extern Fl_Spinner *recent_spinner; +Fl_Double_Window* make_settings_window(); +extern Fl_Menu_Item menu_scheme_choice[]; +extern Fl_Double_Window *shell_window; +extern Fl_Input *shell_command_input; +extern Fl_Check_Button *shell_writecode_button; +extern Fl_Check_Button *shell_writemsgs_button; +extern Fl_Check_Button *shell_savefl_button; +#include <FL/Fl_Return_Button.H> +extern void do_shell_command(Fl_Return_Button*, void*); +extern Fl_Double_Window *shell_run_window; +#include <FL/Fl_Text_Display.H> +extern Fl_Text_Display *shell_run_display; +extern Fl_Return_Button *shell_run_button; +Fl_Double_Window* make_shell_window(); +extern Fl_Double_Window *grid_window; +extern void grid_cb(Fl_Input*, long); +extern Fl_Input *horizontal_input; +extern Fl_Input *vertical_input; +extern Fl_Input *snap_input; +extern void guides_cb(Fl_Check_Button*, long); +extern Fl_Check_Button *guides_toggle; +#include <FL/Fl_Round_Button.H> +extern void default_widget_size_cb(Fl_Round_Button*, long); +extern Fl_Round_Button *def_widget_size[6]; +Fl_Double_Window* make_layout_window(); +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/code.cxx b/Utilities/FLTK/fluid/code.cxx new file mode 100644 index 0000000000..25f68fc453 --- /dev/null +++ b/Utilities/FLTK/fluid/code.cxx @@ -0,0 +1,578 @@ +// +// "$Id$" +// +// Code output routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <stdio.h> +#include <stdlib.h> +#include "../src/flstring.h" +#include <stdarg.h> + +#include <FL/Fl.H> +#include "Fl_Type.h" +#include "alignment_panel.h" + +static FILE *code_file; +static FILE *header_file; + +extern char i18n_program[]; +extern int i18n_type; +extern const char* i18n_include; +extern const char* i18n_function; +extern const char* i18n_file; +extern const char* i18n_set; + +// return true if c can be in a C identifier. I needed this so +// it is not messed up by locale settings: +int is_id(char c) { + return c>='a' && c<='z' || c>='A' && c<='Z' || c>='0' && c<='9' || c=='_'; +} + +//////////////////////////////////////////////////////////////// +// Generate unique but human-readable identifiers: + +struct id { + char* text; + void* object; + id *left, *right; + id (const char* t, void* o) : text(strdup(t)), object(o) {left = right = 0;} + ~id(); +}; + +id::~id() { + delete left; + free((void *)text); + delete right; +} + +static id* id_root; + +const char* unique_id(void* o, const char* type, const char* name, const char* label) { + char buffer[128]; + char* q = buffer; + while (*type) *q++ = *type++; + *q++ = '_'; + const char* n = name; + if (!n || !*n) n = label; + if (n && *n) { + while (*n && !is_id(*n)) n++; + while (is_id(*n)) *q++ = *n++; + } + *q = 0; + // okay, search the tree and see if the name was already used: + id** p = &id_root; + int which = 0; + while (*p) { + int i = strcmp(buffer, (*p)->text); + if (!i) { + if ((*p)->object == o) return (*p)->text; + // already used, we need to pick a new name: + sprintf(q,"%x",++which); + p = &id_root; + continue; + } + else if (i < 0) p = &((*p)->left); + else p = &((*p)->right); + } + *p = new id(buffer, o); + return (*p)->text; +} + +//////////////////////////////////////////////////////////////// +// return current indentation: + +static const char* spaces = " "; +int indentation; +const char* indent() { + int i = indentation; if (i>16) i = 16; + return spaces+16-i; +} + +//////////////////////////////////////////////////////////////// +// declarations/include files: +// Each string generated by write_declare is written only once to +// the header file. This is done by keeping a binary tree of all +// the calls so far and not printing it if it is in the tree. + +struct included { + char *text; + included *left, *right; + included(const char *t) { + text = strdup(t); + left = right = 0; + } + ~included(); +}; + +included::~included() { + delete left; + free((void *)text); + delete right; +} +static included *included_root; + +int write_declare(const char *format, ...) { + va_list args; + char buf[1024]; + va_start(args, format); + vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + included **p = &included_root; + while (*p) { + int i = strcmp(buf,(*p)->text); + if (!i) return 0; + else if (i < 0) p = &((*p)->left); + else p = &((*p)->right); + } + fprintf(header_file,"%s\n",buf); + *p = new included(buf); + return 1; +} + +//////////////////////////////////////////////////////////////// + +// silly thing to prevent declaring unused variables: +// When this symbol is on, all attempts to write code don't write +// anything, but set a variable if it looks like the varaible "o" is used: +int varused_test; +int varused; + +// write an array of C characters (adds a null): +void write_cstring(const char *w, int length) { + if (varused_test) return; + const char *e = w+length; + int linelength = 1; + putc('\"', code_file); + for (; w < e;) { + int c = *w++; + switch (c) { + case '\b': c = 'b'; goto QUOTED; + case '\t': c = 't'; goto QUOTED; + case '\n': c = 'n'; goto QUOTED; + case '\f': c = 'f'; goto QUOTED; + case '\r': c = 'r'; goto QUOTED; + case '\"': + case '\'': + case '\\': + QUOTED: + if (linelength >= 77) {fputs("\\\n",code_file); linelength = 0;} + putc('\\', code_file); + putc(c, code_file); + linelength += 2; + break; + case '?': // prevent trigraphs by writing ?? as ?\? + if (*(w-2) == '?') goto QUOTED; + // else fall through: + default: + if (c >= ' ' && c < 127) { + // a legal ASCII character + if (linelength >= 78) {fputs("\\\n",code_file); linelength = 0;} + putc(c, code_file); + linelength++; + break; + } + // otherwise we must print it as an octal constant: + c &= 255; + if (c < 8) { + if (linelength >= 76) {fputs("\\\n",code_file); linelength = 0;} + fprintf(code_file, "\\%o",c); + linelength += 2; + } else if (c < 64) { + if (linelength >= 75) {fputs("\\\n",code_file); linelength = 0;} + fprintf(code_file, "\\%o",c); + linelength += 3; + } else { + if (linelength >= 74) {fputs("\\\n",code_file); linelength = 0;} + fprintf(code_file, "\\%o",c); + linelength += 4; + } + // We must not put more numbers after it, because some C compilers + // consume them as part of the quoted sequence. Use string constant + // pasting to avoid this: + c = *w; + if (w < e && (c>='0'&&c<='9' || c>='a'&&c<='f' || c>='A'&&c<='F')) { + putc('\"', code_file); linelength++; + if (linelength >= 79) {fputs("\n",code_file); linelength = 0;} + putc('\"', code_file); linelength++; + } + break; + } + } + putc('\"', code_file); +} + +// write a C string, quoting characters if necessary: +void write_cstring(const char *w) {write_cstring(w,strlen(w));} + +// write an array of C binary data (does not add a null): +void write_cdata(const char *s, int length) { + if (varused_test) return; + const unsigned char *w = (const unsigned char *)s; + const unsigned char *e = w+length; + int linelength = 1; + putc('{', code_file); + for (; w < e;) { + unsigned char c = *w++; + if (c>99) linelength += 4; + else if (c>9) linelength += 3; + else linelength += 2; + if (linelength >= 77) {fputs("\n",code_file); linelength = 0;} + fprintf(code_file, "%d", c); + if (w<e) putc(',', code_file); + } + putc('}', code_file); +} + +void write_c(const char* format,...) { + if (varused_test) {varused = 1; return;} + va_list args; + va_start(args, format); + vfprintf(code_file, format, args); + va_end(args); +} + +void write_h(const char* format,...) { + if (varused_test) return; + va_list args; + va_start(args, format); + vfprintf(header_file, format, args); + va_end(args); +} + +#include <FL/filename.H> +int write_number; +int write_sourceview; + +// recursively dump code, putting children between the two parts +// of the parent code: +static Fl_Type* write_code(Fl_Type* p) { + if (write_sourceview) { + p->code_line = (int)ftell(code_file); + if (p->header_line_end==-1) + p->header_line = (int)ftell(header_file); + } + // write all code that come before the children code + // (but don't write the last comment until the very end) + if (!(p==Fl_Type::last && p->is_comment())) + p->write_code1(); + // recursively write the code of all children + Fl_Type* q; + if (p->is_widget() && p->is_class()) { + // Handle widget classes specially + for (q = p->next; q && q->level > p->level;) { + if (strcmp(q->type_name(), "Function")) q = write_code(q); + else { + int level = q->level; + do { + q = q->next; + } while (q && q->level > level); + } + } + + // write all code that come after the children + p->write_code2(); + + for (q = p->next; q && q->level > p->level;) { + if (!strcmp(q->type_name(), "Function")) q = write_code(q); + else { + int level = q->level; + do { + q = q->next; + } while (q && q->level > level); + } + } + + write_h("};\n"); + } else { + for (q = p->next; q && q->level > p->level;) q = write_code(q); + // write all code that come after the children + p->write_code2(); + } + if (write_sourceview) { + p->code_line_end = (int)ftell(code_file); + if (p->header_line_end==-1) + p->header_line_end = (int)ftell(header_file); + } + return q; +} + +extern const char* header_file_name; + +int write_code(const char *s, const char *t) { + const char *filemode = "w"; + if (write_sourceview) + filemode = "wb"; + write_number++; + delete id_root; id_root = 0; + indentation = 0; + if (!s) code_file = stdout; + else { + FILE *f = fopen(s, filemode); + if (!f) return 0; + code_file = f; + } + if (!t) header_file = stdout; + else { + FILE *f = fopen(t, filemode); + if (!f) {fclose(code_file); return 0;} + header_file = f; + } + // if the first entry in the Type tree is a comment, then it is probably + // a copyright notice. We print that before anything else in the file! + Fl_Type* first_type = Fl_Type::first; + if (first_type && first_type->is_comment()) { + if (write_sourceview) { + first_type->code_line = (int)ftell(code_file); + first_type->header_line = (int)ftell(header_file); + } + // it is ok to write non-recusive code here, because comments have no children or code2 blocks + first_type->write_code1(); + if (write_sourceview) { + first_type->code_line_end = (int)ftell(code_file); + first_type->header_line_end = (int)ftell(header_file); + } + first_type = first_type->next; + } + + const char *hdr = "\ +// generated by Fast Light User Interface Designer (fluid) version %.4f\n\n"; + fprintf(header_file, hdr, FL_VERSION); + fprintf(code_file, hdr, FL_VERSION); + + {char define_name[102]; + const char* a = fl_filename_name(t); + char* b = define_name; + if (!isalpha(*a)) {*b++ = '_';} + while (*a) {*b++ = isalnum(*a) ? *a : '_'; a++;} + *b = 0; + fprintf(header_file, "#ifndef %s\n", define_name); + fprintf(header_file, "#define %s\n", define_name); + } + + write_declare("#include <FL/Fl.H>"); + if (i18n_type && i18n_include[0]) { + if (i18n_include[0] != '<' && + i18n_include[0] != '\"') + write_c("#include \"%s\"\n", i18n_include); + else + write_c("#include %s\n", i18n_include); + if (i18n_type == 2) { + if (i18n_file[0]) write_c("extern nl_catd %s;\n", i18n_file); + else { + write_c("// Initialize I18N stuff now for menus...\n"); + write_c("#include <locale.h>\n"); + write_c("static char *_locale = setlocale(LC_MESSAGES, \"\");\n"); + write_c("static nl_catd _catalog = catopen(\"%s\", 0);\n", + i18n_program); + } + } + } + if (t && include_H_from_C) { + if (*header_file_name == '.' && strchr(header_file_name, '/') == NULL) { + write_c("#include \"%s\"\n", fl_filename_name(t)); + } else { + write_c("#include \"%s\"\n", t); + } + } + for (Fl_Type* p = first_type; p;) { + // write all static data for this & all children first + if (write_sourceview) p->header_line = (int)ftell(header_file); + p->write_static(); + if (write_sourceview) { + p->header_line_end = (int)ftell(header_file); + if (p->header_line==p->header_line_end) p->header_line_end = -1; + } + for (Fl_Type* q = p->next; q && q->level > p->level; q = q->next) { + if (write_sourceview) q->header_line = (int)ftell(header_file); + q->write_static(); + if (write_sourceview) { + q->header_line_end = (int)ftell(header_file); + if (q->header_line==q->header_line_end) q->header_line_end = -1; + } + } + // then write the nested code: + p = write_code(p); + } + + delete included_root; included_root = 0; + + if (!s) return 1; + + fprintf(header_file, "#endif\n"); + + Fl_Type* last_type = Fl_Type::last; + if (last_type && last_type->is_comment()) { + if (write_sourceview) { + last_type->code_line = (int)ftell(code_file); + last_type->header_line = (int)ftell(header_file); + } + last_type->write_code1(); + if (write_sourceview) { + last_type->code_line_end = (int)ftell(code_file); + last_type->header_line_end = (int)ftell(header_file); + } + } + + int x = fclose(code_file); + code_file = 0; + int y = fclose(header_file); + header_file = 0; + return x >= 0 && y >= 0; +} + +int write_strings(const char *sfile) { + FILE *fp = fopen(sfile, "w"); + Fl_Type *p; + Fl_Widget_Type *w; + int i; + + if (!fp) return 1; + + switch (i18n_type) { + case 0 : /* None, just put static text out */ + fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n", + FL_VERSION); + for (p = Fl_Type::first; p; p = p->next) { + if (p->is_widget()) { + w = (Fl_Widget_Type *)p; + + if (w->label()) { + for (const char *s = w->label(); *s; s ++) + if (*s < 32 || *s > 126 || *s == '\"') + fprintf(fp, "\\%03o", *s); + else + putc(*s, fp); + putc('\n', fp); + } + + if (w->tooltip()) { + for (const char *s = w->tooltip(); *s; s ++) + if (*s < 32 || *s > 126 || *s == '\"') + fprintf(fp, "\\%03o", *s); + else + putc(*s, fp); + putc('\n', fp); + } + } + } + break; + case 1 : /* GNU gettext, put a .po file out */ + fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n", + FL_VERSION); + for (p = Fl_Type::first; p; p = p->next) { + if (p->is_widget()) { + w = (Fl_Widget_Type *)p; + + if (w->label()) { + const char *s; + + fputs("msgid \"", fp); + for (s = w->label(); *s; s ++) + if (*s < 32 || *s > 126 || *s == '\"') + fprintf(fp, "\\%03o", *s); + else + putc(*s, fp); + fputs("\"\n", fp); + + fputs("msgstr \"", fp); + for (s = w->label(); *s; s ++) + if (*s < 32 || *s > 126 || *s == '\"') + fprintf(fp, "\\%03o", *s); + else + putc(*s, fp); + fputs("\"\n", fp); + } + + if (w->tooltip()) { + const char *s; + + fputs("msgid \"", fp); + for (s = w->tooltip(); *s; s ++) + if (*s < 32 || *s > 126 || *s == '\"') + fprintf(fp, "\\%03o", *s); + else + putc(*s, fp); + fputs("\"\n", fp); + + fputs("msgstr \"", fp); + for (s = w->tooltip(); *s; s ++) + if (*s < 32 || *s > 126 || *s == '\"') + fprintf(fp, "\\%03o", *s); + else + putc(*s, fp); + fputs("\"\n", fp); + } + } + } + break; + case 2 : /* POSIX catgets, put a .msg file out */ + fprintf(fp, "$ generated by Fast Light User Interface Designer (fluid) version %.4f\n", + FL_VERSION); + fprintf(fp, "$set %s\n", i18n_set); + fputs("$quote \"\n", fp); + + for (i = 1, p = Fl_Type::first; p; p = p->next) { + if (p->is_widget()) { + w = (Fl_Widget_Type *)p; + + if (w->label()) { + fprintf(fp, "%d \"", i ++); + for (const char *s = w->label(); *s; s ++) + if (*s < 32 || *s > 126 || *s == '\"') + fprintf(fp, "\\%03o", *s); + else + putc(*s, fp); + fputs("\"\n", fp); + } + + if (w->tooltip()) { + fprintf(fp, "%d \"", i ++); + for (const char *s = w->tooltip(); *s; s ++) + if (*s < 32 || *s > 126 || *s == '\"') + fprintf(fp, "\\%03o", *s); + else + putc(*s, fp); + fputs("\"\n", fp); + } + } + } + break; + } + + return fclose(fp); +} + +//////////////////////////////////////////////////////////////// + +void Fl_Type::write_static() {} +void Fl_Type::write_code1() { + write_h("// Header for %s\n", title()); + write_c("// Code for %s\n", title()); +} +void Fl_Type::write_code2() {} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/comments.h b/Utilities/FLTK/fluid/comments.h new file mode 100644 index 0000000000..e55a0b71cf --- /dev/null +++ b/Utilities/FLTK/fluid/comments.h @@ -0,0 +1,82 @@ + +static const char * const comment_text[] = { + // GNU Public License/GPL Header + "//\n" + "// NameOfProgram, ShortDescription\n" + "// Copyright (C) YYYY NameOfAuthor\n" + "//\n" + "// This program is free software; you can redistribute it and/or\n" + "// modify it under the terms of the GNU General Public License\n" + "// as published by the Free Software Foundation; either version 2\n" + "// of the License, or (at your option) any later version.\n" + "//\n" + "// This program is distributed in the hope that it will be useful,\n" + "// but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "// GNU General Public License for more details.\n" + "//\n" + "// You should have received a copy of the GNU General Public License\n" + "// along with this program; if not, write to the Free Software\n" + "// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n" + "//\n", + // GNU Public License/GPL Footer + "\n//\n" + "// NameOfProgram, ShortDescription\n" + "// Copyright (C) YYYY NameOfAuthor\n" + "//", + // GNU Public License/LGPL Header + "//\n" + "// NameOfLibrary, ShortDescription\n" + "// Copyright (C) YYYY NameOfAuthor\n" + "//\n" + "// This library is free software; you can redistribute it and/or\n" + "// modify it under the terms of the GNU Lesser General Public\n" + "// License as published by the Free Software Foundation; either\n" + "// version 2.1 of the License, or (at your option) any later version.\n" + "//\n" + "// This library is distributed in the hope that it will be useful,\n" + "// but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "// GNU Lesser General Public License for more details.\n" + "//\n" + "// You should have received a copy of the GNU Lesser General Public\n" + "// License along with this program; if not, write to the Free Software\n" + "// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n" + "//\n", + // GNU Public License/LGPL Footer + "\n//\n" + "// NameOfLibrary, ShortDescription\n" + "// Copyright (C) YYYY NameOfAuthor\n" + "//", + // FLTK/Header + "//\n" + "// \"$Id$\"\n" + "//\n" + "// ... for the Fast Light Tool Kit (FLTK).\n" + "//\n" + "// Copyright 1998-2005 by Bill Spitzak and others.\n" + "//\n" + "// This library is free software; you can redistribute it and/or\n" + "// modify it under the terms of the GNU Library General Public\n" + "// License as published by the Free Software Foundation; either\n" + "// version 2 of the License, or (at your option) any later version.\n" + "//\n" + "// This library is distributed in the hope that it will be useful,\n" + "// but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" + "// Library General Public License for more details.\n" + "//\n" + "// You should have received a copy of the GNU Library General Public\n" + "// License along with this library; if not, write to the Free Software\n" + "// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307\n" + "// USA.\n" + "//\n" + "// Please report all bugs and problems on the following page:\n" + "//\n" + "// http://www.fltk.org/str.php\n" + "//\n", + // FLTK/Footer + "\n//\n" + "// End of \"$Id$\".\n" + "//", +}; diff --git a/Utilities/FLTK/fluid/factory.cxx b/Utilities/FLTK/fluid/factory.cxx new file mode 100644 index 0000000000..7eaf5dc87a --- /dev/null +++ b/Utilities/FLTK/fluid/factory.cxx @@ -0,0 +1,1202 @@ +// +// "$Id$" +// +// Widget factory code for the Fast Light Tool Kit (FLTK). +// +// Type classes for most of the fltk widgets. Most of the work +// is done by code in Fl_Widget_Type.C. Also a factory instance +// of each of these type classes. +// +// This file also contains the "new" menu, which has a pointer +// to a factory instance for every class (both the ones defined +// here and ones in other files) +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Group.H> +#include <FL/Fl_Menu_Item.H> +#include <FL/Fl_Pixmap.H> +#include <stdio.h> +#include "../src/flstring.h" +#include "undo.h" + +#include "Fl_Widget_Type.h" + +extern Fl_Pixmap *pixmap[]; + +#if !HAVE_STRCASECMP +// +// 'strcasecmp()' - Do a case-insensitive compare... +// + +static int +strcasecmp(const char *s, const char *t) { + while (*s != '\0' && *t != '\0') { + if (tolower(*s) < tolower(*t)) + return (-1); + else if (tolower(*s) > tolower(*t)) + return (1); + + s ++; + t ++; + } + + if (*s == '\0' && *t == '\0') + return (0); + else if (*s != '\0') + return (1); + else + return (-1); +} +#endif // !HAVE_STRCASECMP + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Box.H> +class Fl_Box_Type : public Fl_Widget_Type { +public: + virtual const char *type_name() {return "Fl_Box";} + Fl_Widget *widget(int x,int y,int w, int h) { + return new Fl_Box(x,y,w,h,"label");} + Fl_Widget_Type *_make() {return new Fl_Box_Type();} + int pixmapID() { return 5; } +}; +static Fl_Box_Type Fl_Box_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Button.H> +static Fl_Menu_Item buttontype_menu[] = { + {"Normal",0,0,(void*)0}, + {"Toggle",0,0,(void*)FL_TOGGLE_BUTTON}, + {"Radio",0,0,(void*)FL_RADIO_BUTTON}, + {0}}; +class Fl_Button_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return buttontype_menu;} +public: + virtual void ideal_size(int &w, int &h) { + Fl_Widget_Type::ideal_size(w, h); + w += 2 * (o->labelsize() - 4); + h = (h / 5) * 5; + } + virtual const char *type_name() {return "Fl_Button";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Button(x,y,w,h,"button");} + Fl_Widget_Type *_make() {return new Fl_Button_Type();} + int is_button() const {return 1;} + int pixmapID() { return 2; } +}; +static Fl_Button_Type Fl_Button_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Return_Button.H> +class Fl_Return_Button_Type : public Fl_Button_Type { +public: + virtual void ideal_size(int &w, int &h) { + Fl_Button_Type::ideal_size(w, h); + int W = o->h(); + if (o->w()/3 < W) W = o->w()/3; + w += W + 8 - o->labelsize(); + } + virtual const char *type_name() {return "Fl_Return_Button";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Return_Button(x,y,w,h,"button");} + Fl_Widget_Type *_make() {return new Fl_Return_Button_Type();} + int pixmapID() { return 23; } +}; +static Fl_Return_Button_Type Fl_Return_Button_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Repeat_Button.H> +class Fl_Repeat_Button_Type : public Fl_Widget_Type { +public: + virtual const char *type_name() {return "Fl_Repeat_Button";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Repeat_Button(x,y,w,h,"button");} + Fl_Widget_Type *_make() {return new Fl_Repeat_Button_Type();} + int pixmapID() { return 25; } +}; +static Fl_Repeat_Button_Type Fl_Repeat_Button_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Light_Button.H> +class Fl_Light_Button_Type : public Fl_Button_Type { +public: + virtual void ideal_size(int &w, int &h) { + Fl_Button_Type::ideal_size(w, h); + w += 4; + } + virtual const char *type_name() {return "Fl_Light_Button";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Light_Button(x,y,w,h,"button");} + Fl_Widget_Type *_make() {return new Fl_Light_Button_Type();} + int pixmapID() { return 24; } +}; +static Fl_Light_Button_Type Fl_Light_Button_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Check_Button.H> +class Fl_Check_Button_Type : public Fl_Button_Type { +public: + virtual void ideal_size(int &w, int &h) { + Fl_Button_Type::ideal_size(w, h); + w += 4; + } + virtual const char *type_name() {return "Fl_Check_Button";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Check_Button(x,y,w,h,"button");} + Fl_Widget_Type *_make() {return new Fl_Check_Button_Type();} + int pixmapID() { return 3; } +}; +static Fl_Check_Button_Type Fl_Check_Button_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Round_Button.H> +class Fl_Round_Button_Type : public Fl_Button_Type { +public: + virtual void ideal_size(int &w, int &h) { + Fl_Button_Type::ideal_size(w, h); + w += 4; + } + virtual const char *type_name() {return "Fl_Round_Button";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Round_Button(x,y,w,h,"button");} + Fl_Widget_Type *_make() {return new Fl_Round_Button_Type();} + int pixmapID() { return 4; } +}; +static Fl_Round_Button_Type Fl_Round_Button_type; + +//////////////////////////////////////////////////////////////// + +extern int compile_only; + +#include <FL/Fl_Browser.H> +#include <FL/Fl_Check_Browser.H> +#include <FL/Fl_File_Browser.H> + +static Fl_Menu_Item browser_type_menu[] = { + {"No Select",0,0,(void*)FL_NORMAL_BROWSER}, + {"Select",0,0,(void*)FL_SELECT_BROWSER}, + {"Hold",0,0,(void*)FL_HOLD_BROWSER}, + {"Multi",0,0,(void*)FL_MULTI_BROWSER}, + {0}}; +class Fl_Browser_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return browser_type_menu;} + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c); +public: + virtual void ideal_size(int &w, int &h) { + Fl_Browser *myo = (Fl_Browser *)o; + fl_font(myo->textfont(), myo->textsize()); + h -= Fl::box_dh(o->box()); + w -= Fl::box_dw(o->box()); + int ww = (int)fl_width('m'); + w = ((w + ww - 1) / ww) * ww + Fl::box_dw(o->box()); + h = ((h + fl_height() - 1) / fl_height()) * fl_height() + + Fl::box_dh(o->box()); + if (h < 30) h = 30; + if (w < 50) w = 50; + } + virtual const char *type_name() {return "Fl_Browser";} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_Browser* b = new Fl_Browser(x,y,w,h); + // Fl_Browser::add calls fl_height(), which requires the X display open. + // Avoid this when compiling so it works w/o a display: + if (!compile_only) { + char buffer[20]; + for (int i = 1; i <= 20; i++) { + sprintf(buffer,"Browser Line %d",i); + b->add(buffer); + } + } + return b; + } + Fl_Widget_Type *_make() {return new Fl_Browser_Type();} + int pixmapID() { return 31; } +}; +static Fl_Browser_Type Fl_Browser_type; + +int Fl_Browser_Type::textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Browser *myo = (Fl_Browser*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); + switch (w) { + case 4: + case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; + case 1: myo->textfont(f); break; + case 2: myo->textsize(s); break; + case 3: myo->textcolor(c); break; + } + return 1; +} + +class Fl_Check_Browser_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return browser_type_menu;} + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c); +public: + virtual void ideal_size(int &w, int &h) { + Fl_Check_Browser *myo = (Fl_Check_Browser *)o; + fl_font(myo->textfont(), myo->textsize()); + h -= Fl::box_dh(o->box()); + w -= Fl::box_dw(o->box()) - fl_height(); + int ww = (int)fl_width('m'); + w = ((w + ww - 1) / ww) * ww + Fl::box_dw(o->box()); + h = ((h + fl_height() - 1) / fl_height()) * fl_height() + + Fl::box_dh(o->box()); + if (h < 30) h = 30; + if (w < 50) w = 50; + } + virtual const char *type_name() {return "Fl_Check_Browser";} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_Check_Browser* b = new Fl_Check_Browser(x,y,w,h); + // Fl_Check_Browser::add calls fl_height(), which requires the X display open. + // Avoid this when compiling so it works w/o a display: + if (!compile_only) { + char buffer[20]; + for (int i = 1; i <= 20; i++) { + sprintf(buffer,"Browser Line %d",i); + b->add(buffer); + } + } + return b; + } + Fl_Widget_Type *_make() {return new Fl_Check_Browser_Type();} + int pixmapID() { return 32; } +}; +static Fl_Check_Browser_Type Fl_Check_Browser_type; + +int Fl_Check_Browser_Type::textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Check_Browser *myo = (Fl_Check_Browser*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); + switch (w) { + case 4: + case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; + case 1: myo->textfont(f); break; + case 2: myo->textsize(s); break; + case 3: myo->textcolor(c); break; + } + return 1; +} + +class Fl_File_Browser_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return browser_type_menu;} + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c); +public: + virtual void ideal_size(int &w, int &h) { + Fl_File_Browser *myo = (Fl_File_Browser *)o; + fl_font(myo->textfont(), myo->textsize()); + h -= Fl::box_dh(o->box()); + w -= Fl::box_dw(o->box()) + fl_height(); + int ww = (int)fl_width('m'); + w = ((w + ww - 1) / ww) * ww + Fl::box_dw(o->box()); + h = ((h + fl_height() - 1) / fl_height()) * fl_height() + + Fl::box_dh(o->box()); + if (h < 30) h = 30; + if (w < 50) w = 50; + } + virtual const char *type_name() {return "Fl_File_Browser";} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_File_Browser* b = new Fl_File_Browser(x,y,w,h); + // Fl_File_Browser::add calls fl_height(), which requires the X display open. + // Avoid this when compiling so it works w/o a display: + if (!compile_only) { + b->load("."); + } + return b; + } + Fl_Widget_Type *_make() {return new Fl_File_Browser_Type();} + int pixmapID() { return 33; } +}; +static Fl_File_Browser_Type Fl_File_Browser_type; + +int Fl_File_Browser_Type::textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_File_Browser *myo = (Fl_File_Browser*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); + switch (w) { + case 4: + case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; + case 1: myo->textfont(f); break; + case 2: myo->textsize(s); break; + case 3: myo->textcolor(c); break; + } + return 1; +} + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Counter.H> +static Fl_Menu_Item counter_type_menu[] = { + {"Normal",0,0,(void*)FL_NORMAL_COUNTER}, + {"Simple",0,0,(void*)FL_SIMPLE_COUNTER}, + {0}}; +class Fl_Counter_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return counter_type_menu;} + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c); + int is_valuator() const {return 1;} + int pixmapID() { return 41; } +public: + virtual const char *type_name() {return "Fl_Counter";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Counter(x,y,w,h,"counter:");} + Fl_Widget_Type *_make() {return new Fl_Counter_Type();} +}; +static Fl_Counter_Type Fl_Counter_type; + +int Fl_Counter_Type::textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Counter *myo = (Fl_Counter*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); + switch (w) { + case 4: + case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; + case 1: myo->textfont(f); break; + case 2: myo->textsize(s); break; + case 3: myo->textcolor(c); break; + } + return 1; +} + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Spinner.H> +class Fl_Spinner_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return 0;} + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c); + int pixmapID() { return 47; } +public: + virtual void ideal_size(int &w, int &h) { + Fl_Spinner *myo = (Fl_Spinner *)o; + fl_font(myo->textfont(), myo->textsize()); + h = fl_height() + myo->textsize() - 6; + if (h < 15) h = 15; + w -= Fl::box_dw(o->box()); + int ww = (int)fl_width('m'); + w = ((w + ww - 1) / ww) * ww + Fl::box_dw(o->box()) + h / 2; + if (w < 40) w = 40 ; + } + virtual const char *type_name() {return "Fl_Spinner";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Spinner(x,y,w,h,"spinner:");} + Fl_Widget_Type *_make() {return new Fl_Spinner_Type();} +}; +static Fl_Spinner_Type Fl_Spinner_type; + +int Fl_Spinner_Type::textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Spinner *myo = (Fl_Spinner*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); + switch (w) { + case 4: + case 0: f = (Fl_Font)myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; + case 1: myo->textfont(f); break; + case 2: myo->textsize(s); break; + case 3: myo->textcolor(c); break; + } + return 1; +} + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Input.H> +static Fl_Menu_Item input_type_menu[] = { + {"Normal",0,0,(void*)FL_NORMAL_INPUT}, + {"Multiline",0,0,(void*)FL_MULTILINE_INPUT}, + {"Secret",0,0,(void*)FL_SECRET_INPUT}, + {"Int",0,0,(void*)FL_INT_INPUT}, + {"Float",0,0,(void*)FL_FLOAT_INPUT}, + {0}}; +class Fl_Input_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return input_type_menu;} + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c); +public: + virtual void ideal_size(int &w, int &h) { + Fl_Input *myo = (Fl_Input *)o; + fl_font(myo->textfont(), myo->textsize()); + h = fl_height() + myo->textsize() - 6; + w -= Fl::box_dw(o->box()); + int ww = (int)fl_width('m'); + w = ((w + ww - 1) / ww) * ww + Fl::box_dw(o->box()); + if (h < 15) h = 15; + if (w < 15) w = 15; + } + virtual const char *type_name() {return "Fl_Input";} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_Input *myo = new Fl_Input(x,y,w,h,"input:"); + myo->value("Text Input"); + return myo; + } + Fl_Widget_Type *_make() {return new Fl_Input_Type();} + int pixmapID() { return 14; } + virtual void copy_properties() { + Fl_Widget_Type::copy_properties(); + Fl_Input_ *d = (Fl_Input_*)live_widget, *s = (Fl_Input_*)o; + d->textfont(s->textfont()); + d->textsize(s->textsize()); + d->textcolor(s->textcolor()); + } +}; +static Fl_Input_Type Fl_Input_type; + +int Fl_Input_Type::textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Input_ *myo = (Fl_Input_*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); + switch (w) { + case 4: + case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; + case 1: myo->textfont(f); break; + case 2: myo->textsize(s); break; + case 3: myo->textcolor(c); break; + } + return 1; +} + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_File_Input.H> +class Fl_File_Input_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return 0;} + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c); +public: + virtual void ideal_size(int &w, int &h) { + Fl_File_Input *myo = (Fl_File_Input *)o; + fl_font(myo->textfont(), myo->textsize()); + h = fl_height() + myo->textsize() + 4; + w -= Fl::box_dw(o->box()); + int ww = (int)fl_width('m'); + w = ((w + ww - 1) / ww) * ww + Fl::box_dw(o->box()); + if (h < 20) h = 20; + if (w < 50) w = 50; + } + virtual const char *type_name() {return "Fl_File_Input";} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_File_Input *myo = new Fl_File_Input(x,y,w,h,"file:"); + myo->value("/now/is/the/time/for/a/filename.ext"); + return myo; + } + Fl_Widget_Type *_make() {return new Fl_File_Input_Type();} + int pixmapID() { return 30; } +}; +static Fl_File_Input_Type Fl_File_Input_type; + +int Fl_File_Input_Type::textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_File_Input *myo = (Fl_File_Input*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); + switch (w) { + case 4: + case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; + case 1: myo->textfont(f); break; + case 2: myo->textsize(s); break; + case 3: myo->textcolor(c); break; + } + return 1; +} + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Text_Display.H> +class Fl_Text_Display_Type : public Fl_Widget_Type { + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c); +public: + virtual void ideal_size(int &w, int &h) { + Fl_Text_Display *myo = (Fl_Text_Display *)o; + fl_font(myo->textfont(), myo->textsize()); + h -= Fl::box_dh(o->box()); + w -= Fl::box_dw(o->box()); + int ww = (int)fl_width('m'); + w = ((w + ww - 1) / ww) * ww + Fl::box_dw(o->box()); + h = ((h + fl_height() - 1) / fl_height()) * fl_height() + + Fl::box_dh(o->box()); + if (h < 30) h = 30; + if (w < 50) w = 50; + } + virtual const char *type_name() {return "Fl_Text_Display";} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_Text_Display *myo = new Fl_Text_Display(x,y,w,h); + return myo; + } + Fl_Widget_Type *_make() {return new Fl_Text_Display_Type();} + int pixmapID() { return 28; } +}; +static Fl_Text_Display_Type Fl_Text_Display_type; + +int Fl_Text_Display_Type::textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Text_Display *myo = (Fl_Text_Display*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); + switch (w) { + case 4: + case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; + case 1: myo->textfont(f); break; + case 2: myo->textsize(s); break; + case 3: myo->textcolor(c); break; + } + return 1; +} + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Text_Editor.H> +class Fl_Text_Editor_Type : public Fl_Widget_Type { + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c); +public: + virtual void ideal_size(int &w, int &h) { + Fl_Text_Editor *myo = (Fl_Text_Editor *)o; + fl_font(myo->textfont(), myo->textsize()); + h -= Fl::box_dh(o->box()); + w -= Fl::box_dw(o->box()); + int ww = (int)fl_width('m'); + w = ((w + ww - 1) / ww) * ww + Fl::box_dw(o->box()); + h = ((h + fl_height() - 1) / fl_height()) * fl_height() + + Fl::box_dh(o->box()); + if (h < 30) h = 30; + if (w < 50) w = 50; + } + virtual const char *type_name() {return "Fl_Text_Editor";} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_Text_Editor *myo = new Fl_Text_Editor(x,y,w,h); + return myo; + } + Fl_Widget_Type *_make() {return new Fl_Text_Editor_Type();} + int pixmapID() { return 29; } +}; +static Fl_Text_Editor_Type Fl_Text_Editor_type; + +int Fl_Text_Editor_Type::textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Text_Editor *myo = (Fl_Text_Editor*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); + switch (w) { + case 4: + case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; + case 1: myo->textfont(f); break; + case 2: myo->textsize(s); break; + case 3: myo->textcolor(c); break; + } + return 1; +} + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Clock.H> +class Fl_Clock_Type : public Fl_Widget_Type { +public: + virtual const char *type_name() {return "Fl_Clock";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Clock(x,y,w,h);} + Fl_Widget_Type *_make() {return new Fl_Clock_Type();} + int pixmapID() { return 34; } +}; +static Fl_Clock_Type Fl_Clock_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Help_View.H> +class Fl_Help_View_Type : public Fl_Widget_Type { +public: + virtual void ideal_size(int &w, int &h) { + Fl_Help_View *myo = (Fl_Help_View *)o; + fl_font(myo->textfont(), myo->textsize()); + h -= Fl::box_dh(o->box()); + w -= Fl::box_dw(o->box()); + int ww = (int)fl_width('m'); + w = ((w + ww - 1) / ww) * ww + Fl::box_dw(o->box()); + h = ((h + fl_height() - 1) / fl_height()) * fl_height() + + Fl::box_dh(o->box()); + if (h < 30) h = 30; + if (w < 50) w = 50; + } + virtual const char *type_name() {return "Fl_Help_View";} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_Help_View *myo = new Fl_Help_View(x,y,w,h); + myo->value("<HTML><BODY><H1>Fl_Help_View Widget</H1>" + "<P>This is a Fl_Help_View widget.</P></BODY></HTML>"); + return myo;} + Fl_Widget_Type *_make() {return new Fl_Help_View_Type();} + int pixmapID() { return 35; } +}; +static Fl_Help_View_Type Fl_Help_View_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Progress.H> +class Fl_Progress_Type : public Fl_Widget_Type { +public: + virtual const char *type_name() {return "Fl_Progress";} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_Progress *myo = new Fl_Progress(x,y,w,h,"label"); + myo->value(50); + return myo;} + Fl_Widget_Type *_make() {return new Fl_Progress_Type();} + int pixmapID() { return 36; } +}; +static Fl_Progress_Type Fl_Progress_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Adjuster.H> +class Fl_Adjuster_Type : public Fl_Widget_Type { + int is_valuator() const {return 1;} +public: + virtual const char *type_name() {return "Fl_Adjuster";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Adjuster(x,y,w,h);} + Fl_Widget_Type *_make() {return new Fl_Adjuster_Type();} + int pixmapID() { return 40; } +}; +static Fl_Adjuster_Type Fl_Adjuster_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Dial.H> +static Fl_Menu_Item dial_type_menu[] = { + {"Dot",0,0,(void*)0}, + {"Line",0,0,(void*)FL_LINE_DIAL}, + {"Fill",0,0,(void*)FL_FILL_DIAL}, + {0}}; +class Fl_Dial_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return dial_type_menu;} + int is_valuator() const {return 1;} +public: + virtual const char *type_name() {return "Fl_Dial";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Dial(x,y,w,h);} + Fl_Widget_Type *_make() {return new Fl_Dial_Type();} + int pixmapID() { return 42; } +}; +static Fl_Dial_Type Fl_Dial_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Roller.H> +static Fl_Menu_Item roller_type_menu[] = { + {"Vertical",0,0,(void*)0}, + {"Horizontal",0,0,(void*)FL_HORIZONTAL}, + {0}}; +class Fl_Roller_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return roller_type_menu;} + int is_valuator() const {return 1;} +public: + virtual const char *type_name() {return "Fl_Roller";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Roller(x,y,w,h);} + Fl_Widget_Type *_make() {return new Fl_Roller_Type();} + int pixmapID() { return 43; } +}; +static Fl_Roller_Type Fl_Roller_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Scrollbar.H> +static Fl_Menu_Item slider_type_menu[] = { + {"Vertical",0,0,(void*)FL_VERT_SLIDER}, + {"Horizontal",0,0,(void*)FL_HOR_SLIDER}, + {"Vert Fill",0,0,(void*)FL_VERT_FILL_SLIDER}, + {"Horz Fill",0,0,(void*)FL_HOR_FILL_SLIDER}, + {"Vert Knob",0,0,(void*)FL_VERT_NICE_SLIDER}, + {"Horz Knob",0,0,(void*)FL_HOR_NICE_SLIDER}, + {0}}; +class Fl_Slider_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return slider_type_menu;} + int is_valuator() const {return 2;} +public: + virtual const char *type_name() {return "Fl_Slider";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Slider(x,y,w,h,"slider:");} + Fl_Widget_Type *_make() {return new Fl_Slider_Type();} + int pixmapID() { return 37; } +}; +static Fl_Slider_Type Fl_Slider_type; + +static Fl_Menu_Item scrollbar_type_menu[] = { + {"Vertical",0,0,(void*)FL_VERT_SLIDER}, + {"Horizontal",0,0,(void*)FL_HOR_SLIDER}, + {0}}; +class Fl_Scrollbar_Type : public Fl_Slider_Type { + Fl_Menu_Item *subtypes() {return scrollbar_type_menu;} +public: + virtual const char *type_name() {return "Fl_Scrollbar";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Scrollbar(x,y,w,h);} + Fl_Widget_Type *_make() {return new Fl_Scrollbar_Type();} + int pixmapID() { return 38; } +}; +static Fl_Scrollbar_Type Fl_Scrollbar_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Output.H> +static Fl_Menu_Item output_type_menu[] = { + {"Normal",0,0,(void*)FL_NORMAL_OUTPUT}, + {"Multiline",0,0,(void*)FL_MULTILINE_OUTPUT}, + {0}}; +class Fl_Output_Type : public Fl_Input_Type { + Fl_Menu_Item *subtypes() {return output_type_menu;} +public: + virtual void ideal_size(int &w, int &h) { + Fl_Output *myo = (Fl_Output *)o; + fl_font(myo->textfont(), myo->textsize()); + h = fl_height() + myo->textsize() - 6; + w -= Fl::box_dw(o->box()); + int ww = (int)fl_width('m'); + w = ((w + ww - 1) / ww) * ww + Fl::box_dw(o->box()); + if (h < 15) h = 15; + if (w < 15) w = 15; + } + virtual const char *type_name() {return "Fl_Output";} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_Output *myo = new Fl_Output(x,y,w,h,"output:"); + myo->value("Text Output"); + return myo; + } + Fl_Widget_Type *_make() {return new Fl_Output_Type();} + int pixmapID() { return 27; } +}; +static Fl_Output_Type Fl_Output_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Value_Input.H> +class Fl_Value_Input_Type : public Fl_Widget_Type { +public: + virtual void ideal_size(int &w, int &h) { + Fl_Value_Input *myo = (Fl_Value_Input *)o; + fl_font(myo->textfont(), myo->textsize()); + h = fl_height() + myo->textsize() - 6; + w -= Fl::box_dw(o->box()); + int ww = (int)fl_width('m'); + w = ((w + ww - 1) / ww) * ww + Fl::box_dw(o->box()); + if (h < 15) h = 15; + if (w < 15) w = 15; + } + virtual const char *type_name() {return "Fl_Value_Input";} + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c); + int is_valuator() const {return 1;} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_Value_Input *myo = new Fl_Value_Input(x,y,w,h,"value:"); + return myo; + } + Fl_Widget_Type *_make() {return new Fl_Value_Input_Type();} + int pixmapID() { return 44; } +}; +static Fl_Value_Input_Type Fl_Value_Input_type; + +int Fl_Value_Input_Type::textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Value_Input *myo = (Fl_Value_Input*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); + switch (w) { + case 4: + case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; + case 1: myo->textfont(f); break; + case 2: myo->textsize(s); break; + case 3: myo->textcolor(c); break; + } + return 1; +} + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Value_Output.H> +class Fl_Value_Output_Type : public Fl_Widget_Type { +public: + virtual void ideal_size(int &w, int &h) { + Fl_Value_Output *myo = (Fl_Value_Output *)o; + fl_font(myo->textfont(), myo->textsize()); + h = fl_height() + myo->textsize() - 6; + w = o->w() - Fl::box_dw(o->box()); + int ww = (int)fl_width('m'); + w = ((w + ww - 1) / ww) * ww + Fl::box_dw(o->box()); + if (h < 15) h = 15; + if (w < 15) w = 15; + } + virtual const char *type_name() {return "Fl_Value_Output";} + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c); + int is_valuator() const {return 1;} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_Value_Output *myo = new Fl_Value_Output(x,y,w,h,"value:"); + return myo; + } + Fl_Widget_Type *_make() {return new Fl_Value_Output_Type();} + int pixmapID() { return 45; } +}; +static Fl_Value_Output_Type Fl_Value_Output_type; + +int Fl_Value_Output_Type::textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Value_Output *myo = (Fl_Value_Output*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); + switch (w) { + case 4: + case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; + case 1: myo->textfont(f); break; + case 2: myo->textsize(s); break; + case 3: myo->textcolor(c); break; + } + return 1; +} + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Value_Slider.H> +class Fl_Value_Slider_Type : public Fl_Slider_Type { + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c); +public: + virtual const char *type_name() {return "Fl_Value_Slider";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Value_Slider(x,y,w,h,"slider:");} + Fl_Widget_Type *_make() {return new Fl_Value_Slider_Type();} + int pixmapID() { return 39; } +}; +static Fl_Value_Slider_Type Fl_Value_Slider_type; + +int Fl_Value_Slider_Type::textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Value_Slider *myo = (Fl_Value_Slider*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); + switch (w) { + case 4: + case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; + case 1: myo->textfont(f); break; + case 2: myo->textsize(s); break; + case 3: myo->textcolor(c); break; + } + return 1; +} + +//////////////////////////////////////////////////////////////// + +extern class Fl_Function_Type Fl_Function_type; +extern class Fl_Code_Type Fl_Code_type; +extern class Fl_CodeBlock_Type Fl_CodeBlock_type; +extern class Fl_Decl_Type Fl_Decl_type; +extern class Fl_DeclBlock_Type Fl_DeclBlock_type; +extern class Fl_Comment_Type Fl_Comment_type; +extern class Fl_Class_Type Fl_Class_type; +extern class Fl_Window_Type Fl_Window_type; +extern class Fl_Widget_Class_Type Fl_Widget_Class_type; +extern class Fl_Group_Type Fl_Group_type; +extern class Fl_Pack_Type Fl_Pack_type; +extern class Fl_Tabs_Type Fl_Tabs_type; +extern class Fl_Scroll_Type Fl_Scroll_type; +extern class Fl_Tile_Type Fl_Tile_type; +extern class Fl_Input_Choice_Type Fl_Input_Choice_type; +extern class Fl_Choice_Type Fl_Choice_type; +extern class Fl_Menu_Bar_Type Fl_Menu_Bar_type; +extern class Fl_Menu_Button_Type Fl_Menu_Button_type; +extern class Fl_Menu_Item_Type Fl_Menu_Item_type; +extern class Fl_Submenu_Type Fl_Submenu_type; +extern class Fl_Wizard_Type Fl_Wizard_type; + +extern void select(Fl_Type *,int); +extern void select_only(Fl_Type *); + +#include <FL/Fl_Window.H> + +static void cb(Fl_Widget *, void *v) { + undo_checkpoint(); + undo_suspend(); + Fl_Type *t = ((Fl_Type*)v)->make(); + if (t) { + if (t->is_widget() && !t->is_window()) { + Fl_Widget_Type *wt = (Fl_Widget_Type *)t; + + // Set font sizes... + wt->o->labelsize(Fl_Widget_Type::default_size); + + Fl_Font f; + int s = Fl_Widget_Type::default_size; + Fl_Color c; + + wt->textstuff(2, f, s, c); + + // Resize and/or reposition new widget... + int w = 0, h = 0; + wt->ideal_size(w, h); + + if (!strcmp(wt->type_name(), "Fl_Menu_Bar")) { + // Move and resize the menubar across the top of the window... + wt->o->resize(0, 0, w, h); + } else { + // Just resize to the ideal size... + wt->o->size(w, h); + } + } + select_only(t); + set_modflag(1); + t->open(); + } else { + undo_current --; + undo_last --; + } + undo_resume(); +} + +Fl_Menu_Item New_Menu[] = { +{"Code",0,0,0,FL_SUBMENU}, + {"Function/Method",0,cb,(void*)&Fl_Function_type}, + {"Code",0,cb,(void*)&Fl_Code_type}, + {"Code Block",0,cb,(void*)&Fl_CodeBlock_type}, + {"Declaration",0,cb,(void*)&Fl_Decl_type}, + {"Declaration Block",0,cb,(void*)&Fl_DeclBlock_type}, + {"Class",0,cb,(void*)&Fl_Class_type}, + {"Widget Class",0,cb,(void*)&Fl_Widget_Class_type}, + {"Comment",0,cb,(void*)&Fl_Comment_type}, +{0}, +{"Group",0,0,0,FL_SUBMENU}, + {0,0,cb,(void*)&Fl_Window_type}, + {0,0,cb,(void*)&Fl_Group_type}, + {0,0,cb,(void*)&Fl_Pack_type}, + {0,0,cb,(void*)&Fl_Tabs_type}, + {0,0,cb,(void*)&Fl_Scroll_type}, + {0,0,cb,(void*)&Fl_Tile_type}, + {0,0,cb,(void*)&Fl_Wizard_type}, +{0}, +{"Buttons",0,0,0,FL_SUBMENU}, + {0,0,cb,(void*)&Fl_Button_type}, + {0,0,cb,(void*)&Fl_Return_Button_type}, + {0,0,cb,(void*)&Fl_Light_Button_type}, + {0,0,cb,(void*)&Fl_Check_Button_type}, + {0,0,cb,(void*)&Fl_Repeat_Button_type}, + {0,0,cb,(void*)&Fl_Round_Button_type}, +{0}, +{"Valuators",0,0,0,FL_SUBMENU}, + {0,0,cb,(void*)&Fl_Slider_type}, + {0,0,cb,(void*)&Fl_Scrollbar_type}, + {0,0,cb,(void*)&Fl_Value_Slider_type}, + {0,0,cb,(void*)&Fl_Adjuster_type}, + {0,0,cb,(void*)&Fl_Counter_type}, + {0,0,cb,(void*)&Fl_Spinner_type}, + {0,0,cb,(void*)&Fl_Dial_type}, + {0,0,cb,(void*)&Fl_Roller_type}, + {0,0,cb,(void*)&Fl_Value_Input_type}, + {0,0,cb,(void*)&Fl_Value_Output_type}, +{0}, +{"Text",0,0,0,FL_SUBMENU}, + {0,0,cb,(void*)&Fl_File_Input_type}, + {0,0,cb,(void*)&Fl_Input_type}, + {0,0,cb,(void*)&Fl_Output_type}, + {0,0,cb,(void*)&Fl_Text_Display_type}, + {0,0,cb,(void*)&Fl_Text_Editor_type}, +{0}, +{"Menus",0,0,0,FL_SUBMENU}, + {0,0,cb,(void*)&Fl_Menu_Bar_type}, + {0,0,cb,(void*)&Fl_Menu_Button_type}, + {0,0,cb,(void*)&Fl_Choice_type}, + {0,0,cb,(void*)&Fl_Input_Choice_type}, + {0,0,cb, (void*)&Fl_Submenu_type}, + {0,0,cb, (void*)&Fl_Menu_Item_type}, +{0}, +{"Browsers",0,0,0,FL_SUBMENU}, + {0,0,cb,(void*)&Fl_Browser_type}, + {0,0,cb,(void*)&Fl_Check_Browser_type}, + {0,0,cb,(void*)&Fl_File_Browser_type}, +{0}, +{"Other",0,0,0,FL_SUBMENU}, + {0,0,cb,(void*)&Fl_Box_type}, + {0,0,cb,(void*)&Fl_Clock_type}, + {0,0,cb,(void*)&Fl_Help_View_type}, + {0,0,cb,(void*)&Fl_Progress_type}, +{0}, +{0}}; + +#include <FL/Fl_Multi_Label.H> + +// modify a menuitem to display an icon in front of the label +static void make_iconlabel( Fl_Menu_Item *mi, Fl_Image *ic, const char *txt ) +{ + if (ic) { + char *t1 = new char[strlen(txt)+6]; + strcpy( t1, " " ); + strcat(t1, txt); + strcat(t1, "..."); + mi->image( ic ); + Fl_Multi_Label *ml = new Fl_Multi_Label; + ml->labela = (char*)ic; + ml->labelb = t1; + ml->typea = _FL_IMAGE_LABEL; + ml->typeb = FL_NORMAL_LABEL; + ml->label( mi ); + } + else if (txt!=mi->text) + mi->label(txt); +} + +void fill_in_New_Menu() { + for (unsigned i = 0; i < sizeof(New_Menu)/sizeof(*New_Menu); i++) { + Fl_Menu_Item *m = New_Menu+i; + if (m->user_data()) { + Fl_Type *t = (Fl_Type*)m->user_data(); + if (m->text) { + make_iconlabel( m, pixmap[t->pixmapID()], m->label() ); + } + else { + const char *n = t->type_name(); + if (!strncmp(n,"Fl_",3)) n += 3; + make_iconlabel( m, pixmap[t->pixmapID()], n ); + } + } + } +} + +// use keyword to pick the type, this is used to parse files: +int reading_file; +Fl_Type *Fl_Type_make(const char *tn) { + reading_file = 1; // makes labels be null + Fl_Type *r = 0; + for (unsigned i = 0; i < sizeof(New_Menu)/sizeof(*New_Menu); i++) { + Fl_Menu_Item *m = New_Menu+i; + if (!m->user_data()) continue; + Fl_Type *t = (Fl_Type*)(m->user_data()); + if (!strcasecmp(tn,t->type_name())) {r = t->make(); break;} + } + reading_file = 0; + return r; +} + +//////////////////////////////////////////////////////////////// + +// Since I have included all the .H files, do this table here: +// This table is only used to read fdesign files: + +struct symbol {const char *name; int value;}; + +static symbol table[] = { + {"BLACK", FL_BLACK}, + {"RED", FL_RED}, + {"GREEN", FL_GREEN}, + {"YELLOW", FL_YELLOW}, + {"BLUE", FL_BLUE}, + {"MAGENTA", FL_MAGENTA}, + {"CYAN", FL_CYAN}, + {"WHITE", FL_WHITE}, + + {"LCOL", FL_BLACK}, + {"COL1", FL_GRAY}, + {"MCOL", FL_LIGHT1}, + {"LEFT_BCOL", FL_LIGHT3}, + {"TOP_BCOL", FL_LIGHT2}, + {"BOTTOM_BCOL", FL_DARK2}, + {"RIGHT_BCOL", FL_DARK3}, + {"INACTIVE", FL_INACTIVE_COLOR}, + {"INACTIVE_COL", FL_INACTIVE_COLOR}, + {"FREE_COL1", FL_FREE_COLOR}, + {"FREE_COL2", FL_FREE_COLOR+1}, + {"FREE_COL3", FL_FREE_COLOR+2}, + {"FREE_COL4", FL_FREE_COLOR+3}, + {"FREE_COL5", FL_FREE_COLOR+4}, + {"FREE_COL6", FL_FREE_COLOR+5}, + {"FREE_COL7", FL_FREE_COLOR+6}, + {"FREE_COL8", FL_FREE_COLOR+7}, + {"FREE_COL9", FL_FREE_COLOR+8}, + {"FREE_COL10", FL_FREE_COLOR+9}, + {"FREE_COL11", FL_FREE_COLOR+10}, + {"FREE_COL12", FL_FREE_COLOR+11}, + {"FREE_COL13", FL_FREE_COLOR+12}, + {"FREE_COL14", FL_FREE_COLOR+13}, + {"FREE_COL15", FL_FREE_COLOR+14}, + {"FREE_COL16", FL_FREE_COLOR+15}, + {"TOMATO", 131}, + {"INDIANRED", 164}, + {"SLATEBLUE", 195}, + {"DARKGOLD", 84}, + {"PALEGREEN", 157}, + {"ORCHID", 203}, + {"DARKCYAN", 189}, + {"DARKTOMATO", 113}, + {"WHEAT", 174}, + {"ALIGN_CENTER", FL_ALIGN_CENTER}, + {"ALIGN_TOP", FL_ALIGN_TOP}, + {"ALIGN_BOTTOM", FL_ALIGN_BOTTOM}, + {"ALIGN_LEFT", FL_ALIGN_LEFT}, + {"ALIGN_RIGHT", FL_ALIGN_RIGHT}, + {"ALIGN_INSIDE", FL_ALIGN_INSIDE}, + {"ALIGN_TOP_LEFT", FL_ALIGN_TOP | FL_ALIGN_LEFT}, + {"ALIGN_TOP_RIGHT", FL_ALIGN_TOP | FL_ALIGN_RIGHT}, + {"ALIGN_BOTTOM_LEFT", FL_ALIGN_BOTTOM | FL_ALIGN_LEFT}, + {"ALIGN_BOTTOM_RIGHT", FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT}, + {"ALIGN_CENTER|FL_ALIGN_INSIDE", FL_ALIGN_CENTER|FL_ALIGN_INSIDE}, + {"ALIGN_TOP|FL_ALIGN_INSIDE", FL_ALIGN_TOP|FL_ALIGN_INSIDE}, + {"ALIGN_BOTTOM|FL_ALIGN_INSIDE", FL_ALIGN_BOTTOM|FL_ALIGN_INSIDE}, + {"ALIGN_LEFT|FL_ALIGN_INSIDE", FL_ALIGN_LEFT|FL_ALIGN_INSIDE}, + {"ALIGN_RIGHT|FL_ALIGN_INSIDE", FL_ALIGN_RIGHT|FL_ALIGN_INSIDE}, + {"ALIGN_INSIDE|FL_ALIGN_INSIDE", FL_ALIGN_INSIDE|FL_ALIGN_INSIDE}, + {"ALIGN_TOP_LEFT|FL_ALIGN_INSIDE", FL_ALIGN_TOP|FL_ALIGN_LEFT|FL_ALIGN_INSIDE}, + {"ALIGN_TOP_RIGHT|FL_ALIGN_INSIDE", FL_ALIGN_TOP|FL_ALIGN_RIGHT|FL_ALIGN_INSIDE}, + {"ALIGN_BOTTOM_LEFT|FL_ALIGN_INSIDE", FL_ALIGN_BOTTOM|FL_ALIGN_LEFT|FL_ALIGN_INSIDE}, + {"ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE",FL_ALIGN_BOTTOM|FL_ALIGN_RIGHT|FL_ALIGN_INSIDE}, + + {"ALIGN_LEFT_TOP", FL_ALIGN_TOP | FL_ALIGN_LEFT}, + {"ALIGN_RIGHT_TOP", FL_ALIGN_TOP | FL_ALIGN_RIGHT}, + {"ALIGN_LEFT_BOTTOM", FL_ALIGN_BOTTOM | FL_ALIGN_LEFT}, + {"ALIGN_RIGHT_BOTTOM", FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT}, + {"INVALID_STYLE", 255}, + {"NORMAL_STYLE", FL_HELVETICA}, + {"BOLD_STYLE", FL_HELVETICA|FL_BOLD}, + {"ITALIC_STYLE", FL_HELVETICA|FL_ITALIC}, + {"BOLDITALIC_STYLE", FL_HELVETICA|FL_BOLD|FL_ITALIC}, + {"FIXED_STYLE", FL_COURIER}, + {"FIXEDBOLD_STYLE", FL_COURIER|FL_BOLD}, + {"FIXEDITALIC_STYLE", FL_COURIER|FL_ITALIC}, + {"FIXEDBOLDITALIC_STYLE", FL_COURIER|FL_BOLD|FL_ITALIC}, + {"TIMES_STYLE", FL_TIMES}, + {"TIMESBOLD_STYLE", FL_TIMES|FL_BOLD}, + {"TIMESITALIC_STYLE", FL_TIMES|FL_ITALIC}, + {"TIMESBOLDITALIC_STYLE", FL_TIMES|FL_BOLD|FL_ITALIC}, + {"SHADOW_STYLE", (_FL_SHADOW_LABEL<<8)}, + {"ENGRAVED_STYLE", (_FL_ENGRAVED_LABEL<<8)}, + {"EMBOSSED_STYLE", (_FL_EMBOSSED_LABEL<<0)}, + {"TINY_SIZE", 8}, + {"SMALL_SIZE", 11}, + {"NORMAL_SIZE", FL_NORMAL_SIZE}, + {"MEDIUM_SIZE", 18}, + {"LARGE_SIZE", 24}, + {"HUGE_SIZE", 32}, + {"DEFAULT_SIZE", FL_NORMAL_SIZE}, + {"TINY_FONT", 8}, + {"SMALL_FONT", 11}, + {"NORMAL_FONT", FL_NORMAL_SIZE}, + {"MEDIUM_FONT", 18}, + {"LARGE_FONT", 24}, + {"HUGE_FONT", 32}, + {"NORMAL_FONT1", 11}, + {"NORMAL_FONT2", FL_NORMAL_SIZE}, + {"DEFAULT_FONT", 11}, + {"RETURN_END_CHANGED", 0}, + {"RETURN_CHANGED", 1}, + {"RETURN_END", 2}, + {"RETURN_ALWAYS", 3}, + {"PUSH_BUTTON", FL_TOGGLE_BUTTON}, + {"RADIO_BUTTON", FL_RADIO_BUTTON}, + {"HIDDEN_BUTTON", FL_HIDDEN_BUTTON}, + {"SELECT_BROWSER", FL_SELECT_BROWSER}, + {"HOLD_BROWSER", FL_HOLD_BROWSER}, + {"MULTI_BROWSER", FL_MULTI_BROWSER}, + {"SIMPLE_COUNTER", FL_SIMPLE_COUNTER}, + {"LINE_DIAL", FL_LINE_DIAL}, + {"FILL_DIAL", FL_FILL_DIAL}, + {"VERT_SLIDER", FL_VERT_SLIDER}, + {"HOR_SLIDER", FL_HOR_SLIDER}, + {"VERT_FILL_SLIDER", FL_VERT_FILL_SLIDER}, + {"HOR_FILL_SLIDER", FL_HOR_FILL_SLIDER}, + {"VERT_NICE_SLIDER", FL_VERT_NICE_SLIDER}, + {"HOR_NICE_SLIDER", FL_HOR_NICE_SLIDER}, +}; + +#include <stdlib.h> + +int lookup_symbol(const char *name, int &v, int numberok) { + if (name[0]=='F' && name[1]=='L' && name[2]=='_') name += 3; + for (int i=0; i < int(sizeof(table)/sizeof(*table)); i++) + if (!strcasecmp(name,table[i].name)) {v = table[i].value; return 1;} + if (numberok && ((v = atoi(name)) || !strcmp(name,"0"))) return 1; + return 0; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/file.cxx b/Utilities/FLTK/fluid/file.cxx new file mode 100644 index 0000000000..fe41fc4b31 --- /dev/null +++ b/Utilities/FLTK/fluid/file.cxx @@ -0,0 +1,643 @@ +// +// "$Id$" +// +// Fluid file routines for the Fast Light Tool Kit (FLTK). +// +// You may find the basic read_* and write_* routines to +// be useful for other programs. I have used them many times. +// They are somewhat similar to tcl, using matching { and } +// to quote strings. +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <stdio.h> +#include <stdlib.h> +#include "../src/flstring.h" +#include <stdarg.h> +#include "alignment_panel.h" + +//////////////////////////////////////////////////////////////// +// BASIC FILE WRITING: + +static FILE *fout; + +int open_write(const char *s) { + if (!s) {fout = stdout; return 1;} + FILE *f = fopen(s,"w"); + if (!f) return 0; + fout = f; + return 1; +} + +int close_write() { + if (fout != stdout) { + int x = fclose(fout); + fout = stdout; + return x >= 0; + } + return 1; +} + +static int needspace; +int is_id(char); // in code.C + +// write a string, quoting characters if necessary: +void write_word(const char *w) { + if (needspace) putc(' ', fout); + needspace = 1; + if (!w || !*w) {fprintf(fout,"{}"); return;} + const char *p; + // see if it is a single word: + for (p = w; is_id(*p); p++) ; + if (!*p) {fprintf(fout,"%s",w); return;} + // see if there are matching braces: + int n = 0; + for (p = w; *p; p++) { + if (*p == '{') n++; + else if (*p == '}') {n--; if (n<0) break;} + } + int mismatched = (n != 0); + // write out brace-quoted string: + putc('{', fout); + for (; *w; w++) { + switch (*w) { + case '{': + case '}': + if (!mismatched) break; + case '\\': + case '#': + putc('\\',fout); + break; + } + putc(*w,fout); + } + putc('}', fout); +} + +// write an arbitrary formatted word, or a comment, etc: +void write_string(const char *format, ...) { + va_list args; + va_start(args, format); + if (needspace) fputc(' ',fout); + vfprintf(fout, format, args); + va_end(args); + needspace = !isspace(format[strlen(format)-1]); +} + +// start a new line and indent it for a given nesting level: +void write_indent(int n) { + fputc('\n',fout); + while (n--) {fputc(' ',fout); fputc(' ',fout);} + needspace = 0; +} + +// write a '{' at the given indenting level: +void write_open(int) { + if (needspace) fputc(' ',fout); + fputc('{',fout); + needspace = 0; +} + +// write a '}' at the given indenting level: +void write_close(int n) { + if (needspace) write_indent(n); + fputc('}',fout); + needspace = 1; +} + +//////////////////////////////////////////////////////////////// +// BASIC FILE READING: + +static FILE *fin; +static int lineno; +static const char *fname; + +int open_read(const char *s) { + lineno = 1; + if (!s) {fin = stdin; fname = "stdin"; return 1;} + FILE *f = fopen(s,"r"); + if (!f) return 0; + fin = f; + fname = s; + return 1; +} + +int close_read() { + if (fin != stdin) { + int x = fclose(fin); + fin = 0; + return x >= 0; + } + return 1; +} + +#include <FL/fl_message.H> + +void read_error(const char *format, ...) { + va_list args; + va_start(args, format); + if (!fin) { + char buffer[1024]; + vsnprintf(buffer, sizeof(buffer), format, args); + fl_message(buffer); + } else { + fprintf(stderr, "%s:%d: ", fname, lineno); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); + } + va_end(args); +} + +static int hexdigit(int x) { + if (isdigit(x)) return x-'0'; + if (isupper(x)) return x-'A'+10; + if (islower(x)) return x-'a'+10; + return 20; +} + + +static int read_quoted() { // read whatever character is after a \ . + int c,d,x; + switch(c = fgetc(fin)) { + case '\n': lineno++; return -1; + case 'a' : return('\a'); + case 'b' : return('\b'); + case 'f' : return('\f'); + case 'n' : return('\n'); + case 'r' : return('\r'); + case 't' : return('\t'); + case 'v' : return('\v'); + case 'x' : /* read hex */ + for (c=x=0; x<3; x++) { + int ch = fgetc(fin); + d = hexdigit(ch); + if (d > 15) {ungetc(ch,fin); break;} + c = (c<<4)+d; + } + break; + default: /* read octal */ + if (c<'0' || c>'7') break; + c -= '0'; + for (x=0; x<2; x++) { + int ch = fgetc(fin); + d = hexdigit(ch); + if (d>7) {ungetc(ch,fin); break;} + c = (c<<3)+d; + } + break; + } + return(c); +} + +// return a word read from the file, or NULL at the EOF: +// This will skip all comments (# to end of line), and evaluate +// all \xxx sequences and use \ at the end of line to remove the newline. +// A word is any one of: +// a continuous string of non-space chars except { and } and # +// everything between matching {...} (unless wantbrace != 0) +// the characters '{' and '}' + +static char *buffer; +static int buflen; +static void expand_buffer(int length) { + if (length >= buflen) { + if (!buflen) { + buflen = length+1; + buffer = (char*)malloc(buflen); + } else { + buflen = 2*buflen; + if (length >= buflen) buflen = length+1; + buffer = (char *)realloc((void *)buffer,buflen); + } + } +} + +const char *read_word(int wantbrace) { + int x; + + // skip all the whitespace before it: + for (;;) { + x = getc(fin); + if (x < 0) { // eof + return 0; + } else if (x == '#') { // comment + do x = getc(fin); while (x >= 0 && x != '\n'); + lineno++; + continue; + } else if (x == '\n') { + lineno++; + } else if (!isspace(x)) { + break; + } + } + + expand_buffer(100); + + if (x == '{' && !wantbrace) { + + // read in whatever is between braces + int length = 0; + int nesting = 0; + for (;;) { + x = getc(fin); + if (x<0) {read_error("Missing '}'"); break;} + else if (x == '#') { // embedded comment + do x = getc(fin); while (x >= 0 && x != '\n'); + lineno++; + continue; + } else if (x == '\n') lineno++; + else if (x == '\\') {x = read_quoted(); if (x<0) continue;} + else if (x == '{') nesting++; + else if (x == '}') {if (!nesting--) break;} + buffer[length++] = x; + expand_buffer(length); + } + buffer[length] = 0; + return buffer; + + } else if (x == '{' || x == '}') { + // all the punctuation is a word: + buffer[0] = x; + buffer[1] = 0; + return buffer; + + } else { + + // read in an unquoted word: + int length = 0; + for (;;) { + if (x == '\\') {x = read_quoted(); if (x<0) continue;} + else if (x<0 || isspace(x) || x=='{' || x=='}' || x=='#') break; + buffer[length++] = x; + expand_buffer(length); + x = getc(fin); + } + ungetc(x, fin); + buffer[length] = 0; + return buffer; + + } +} + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl.H> +#include "Fl_Widget_Type.h" + +// global int variables: +extern int i18n_type; +extern const char* i18n_include; +extern const char* i18n_function; +extern const char* i18n_file; +extern const char* i18n_set; + + +extern int header_file_set; +extern int code_file_set; +extern const char* header_file_name; +extern const char* code_file_name; + +int write_file(const char *filename, int selected_only) { + if (!open_write(filename)) return 0; + write_string("# data file for the Fltk User Interface Designer (fluid)\n" + "version %.4f",FL_VERSION); + if(!include_H_from_C) + write_string("\ndo_not_include_H_from_C"); + if (i18n_type) { + write_string("\ni18n_type %d", i18n_type); + write_string("\ni18n_include %s", i18n_include); + switch (i18n_type) { + case 1 : /* GNU gettext */ + write_string("\ni18n_function %s", i18n_function); + break; + case 2 : /* POSIX catgets */ + if (i18n_file[0]) write_string("\ni18n_file %s", i18n_file); + write_string("\ni18n_set %s", i18n_set); + break; + } + } + if (!selected_only) { + write_string("\nheader_name"); write_word(header_file_name); + write_string("\ncode_name"); write_word(code_file_name); + } + for (Fl_Type *p = Fl_Type::first; p;) { + if (!selected_only || p->selected) { + p->write(); + write_string("\n"); + int q = p->level; + for (p = p->next; p && p->level > q; p = p->next); + } else { + p = p->next; + } + } + return close_write(); +} + +//////////////////////////////////////////////////////////////// +// read all the objects out of the input file: + +void read_fdesign(); + +double read_version; + +extern Fl_Type *Fl_Type_make(const char *tn); + +static void read_children(Fl_Type *p, int paste) { + Fl_Type::current = p; + for (;;) { + const char *c = read_word(); + REUSE_C: + if (!c) { + if (p && !paste) read_error("Missing '}'"); + break; + } + + if (!strcmp(c,"}")) { + if (!p) read_error("Unexpected '}'"); + break; + } + + // this is the first word in a .fd file: + if (!strcmp(c,"Magic:")) { + read_fdesign(); + return; + } + + if (!strcmp(c,"version")) { + c = read_word(); + read_version = strtod(c,0); + if (read_version<=0 || read_version>FL_VERSION) + read_error("unknown version '%s'",c); + continue; + } + + // back compatability with Vincent Penne's original class code: + if (!p && !strcmp(c,"define_in_struct")) { + Fl_Type *t = Fl_Type_make("class"); + t->name(read_word()); + Fl_Type::current = p = t; + paste = 1; // stops "missing }" error + continue; + } + + if (!strcmp(c,"do_not_include_H_from_C")) { + include_H_from_C=0; + goto CONTINUE; + } + if (!strcmp(c,"i18n_type")) { + i18n_type = atoi(read_word()); + goto CONTINUE; + } + if (!strcmp(c,"i18n_function")) { + i18n_function = strdup(read_word()); + goto CONTINUE; + } + if (!strcmp(c,"i18n_file")) { + i18n_file = strdup(read_word()); + goto CONTINUE; + } + if (!strcmp(c,"i18n_set")) { + i18n_set = strdup(read_word()); + goto CONTINUE; + } + if (!strcmp(c,"i18n_include")) { + i18n_include = strdup(read_word()); + goto CONTINUE; + } + if (!strcmp(c,"i18n_type")) + { + i18n_type = atoi(read_word()); + goto CONTINUE; + } + if (!strcmp(c,"i18n_type")) + { + i18n_type = atoi(read_word()); + goto CONTINUE; + } + if (!strcmp(c,"header_name")) { + if (!header_file_set) header_file_name = strdup(read_word()); + else read_word(); + goto CONTINUE; + } + + if (!strcmp(c,"code_name")) { + if (!code_file_set) code_file_name = strdup(read_word()); + else read_word(); + goto CONTINUE; + } + + if (!strcmp(c, "snap") || !strcmp(c, "gridx") || !strcmp(c, "gridy")) { + // grid settings are now global + read_word(); + goto CONTINUE; + } + + {Fl_Type *t = Fl_Type_make(c); + if (!t) { + read_error("Unknown word \"%s\"", c); + continue; + } + t->name(read_word()); + + c = read_word(1); + if (strcmp(c,"{") && t->is_class()) { // <prefix> <name> + ((Fl_Class_Type*)t)->prefix(t->name()); + t->name(c); + c = read_word(1); + } + + if (strcmp(c,"{")) { + read_error("Missing property list for %s\n",t->title()); + goto REUSE_C; + } + + t->open_ = 0; + for (;;) { + const char *cc = read_word(); + if (!cc || !strcmp(cc,"}")) break; + t->read_property(cc); + } + + if (!t->is_parent()) continue; + c = read_word(1); + if (strcmp(c,"{")) { + read_error("Missing child list for %s\n",t->title()); + goto REUSE_C; + } + read_children(t, 0);} + Fl_Type::current = p; + CONTINUE:; + } +} + +extern void deselect(); + +int read_file(const char *filename, int merge) { + Fl_Type *o; + read_version = 0.0; + if (!open_read(filename)) return 0; + if (merge) deselect(); else delete_all(); + read_children(Fl_Type::current, merge); + Fl_Type::current = 0; + // Force menu items to be rebuilt... + for (o = Fl_Type::first; o; o = o->next) + if (o->is_menu_button()) o->add_child(0,0); + for (o = Fl_Type::first; o; o = o->next) + if (o->selected) {Fl_Type::current = o; break;} + return close_read(); +} + +//////////////////////////////////////////////////////////////// +// Read Forms and XForms fdesign files: + +int read_fdesign_line(const char*& name, const char*& value) { + + int length = 0; + int x; + // find a colon: + for (;;) { + x = getc(fin); + if (x < 0) return 0; + if (x == '\n') {length = 0; continue;} // no colon this line... + if (!isspace(x)) { + buffer[length++] = x; + expand_buffer(length); + } + if (x == ':') break; + } + int valueoffset = length; + buffer[length-1] = 0; + + // skip to start of value: + for (;;) { + x = getc(fin); + if (x < 0 || x == '\n' || !isspace(x)) break; + } + + // read the value: + for (;;) { + if (x == '\\') {x = read_quoted(); if (x<0) continue;} + else if (x == '\n') break; + buffer[length++] = x; + expand_buffer(length); + x = getc(fin); + } + buffer[length] = 0; + name = buffer; + value = buffer+valueoffset; + return 1; +} + +int fdesign_flip; +int fdesign_magic; +#include <FL/Fl_Group.H> + +static const char *class_matcher[] = { +"FL_CHECKBUTTON", "Fl_Check_Button", +"FL_ROUNDBUTTON", "Fl_Round_Button", +"FL_ROUND3DBUTTON", "Fl_Round_Button", +"FL_LIGHTBUTTON", "Fl_Light_Button", +"FL_FRAME", "Fl_Box", +"FL_LABELFRAME", "Fl_Box", +"FL_TEXT", "Fl_Box", +"FL_VALSLIDER", "Fl_Value_Slider", +"FL_MENU", "Fl_Menu_Button", +"3", "FL_BITMAP", +"1", "FL_BOX", +"71","FL_BROWSER", +"11","FL_BUTTON", +"4", "FL_CHART", +"42","FL_CHOICE", +"61","FL_CLOCK", +"25","FL_COUNTER", +"22","FL_DIAL", +"101","FL_FREE", +"31","FL_INPUT", +"12","Fl_Light_Button", +"41","FL_MENU", +"23","FL_POSITIONER", +"13","Fl_Round_Button", +"21","FL_SLIDER", +"2", "FL_BOX", // was FL_TEXT +"62","FL_TIMER", +"24","Fl_Value_Slider", +0}; + +void read_fdesign() { + fdesign_magic = atoi(read_word()); + fdesign_flip = (fdesign_magic < 13000); + Fl_Widget_Type *window = 0; + Fl_Widget_Type *group = 0; + Fl_Widget_Type *widget = 0; + if (!Fl_Type::current) { + Fl_Type *t = Fl_Type_make("Function"); + t->name("create_the_forms()"); + Fl_Type::current = t; + } + for (;;) { + const char *name; + const char *value; + if (!read_fdesign_line(name, value)) break; + + if (!strcmp(name,"Name")) { + + window = (Fl_Widget_Type*)Fl_Type_make("Fl_Window"); + window->name(value); + window->label(value); + Fl_Type::current = widget = window; + + } else if (!strcmp(name,"class")) { + + if (!strcmp(value,"FL_BEGIN_GROUP")) { + group = widget = (Fl_Widget_Type*)Fl_Type_make("Fl_Group"); + Fl_Type::current = group; + } else if (!strcmp(value,"FL_END_GROUP")) { + if (group) { + Fl_Group* g = (Fl_Group*)(group->o); + g->begin(); + g->forms_end(); + Fl_Group::current(0); + } + group = widget = 0; + Fl_Type::current = window; + } else { + for (int i = 0; class_matcher[i]; i += 2) + if (!strcmp(value,class_matcher[i])) { + value = class_matcher[i+1]; break;} + widget = (Fl_Widget_Type*)Fl_Type_make(value); + if (!widget) { + printf("class %s not found, using Fl_Button\n", value); + widget = (Fl_Widget_Type*)Fl_Type_make("Fl_Button"); + } + } + + } else if (widget) { + if (!widget->read_fdesign(name, value)) + printf("Ignoring \"%s: %s\"\n", name, value); + } + } +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/fluid.app/Contents/Info.plist b/Utilities/FLTK/fluid/fluid.app/Contents/Info.plist new file mode 100644 index 0000000000..73bbfd6574 --- /dev/null +++ b/Utilities/FLTK/fluid/fluid.app/Contents/Info.plist @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="UTF-8"?> +<plist version="0.9"> + <dict> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + + <key>CFBundleExecutable</key> + <string>fluid</string> + + <key>CFBundleIdentifier</key> + <string>org.fltk.fluid</string> + + <key>CFBundleVersion</key> + <string>1.1.7</string> + + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + + <key>NSHumanReadableCopyright</key> + <string>Copyright 1998-2006 by Bill Spitzak and others</string> + + <key>CFAppleHelpAnchor</key> + <string>help</string> + + <key>CFBundleName</key> + <string>FLUID</string> + + <key>CFBundlePackageType</key> + <string>APPL</string> + + <key>CFBundleSignature</key> + <string>FLID</string> + + <key>CFBundleIconFile</key> + <string>fluid.icns</string> + + <key>CFBundleShortVersionString</key> + <string>1.1.7</string> + + <key>CFBundleGetInfoString</key> + <string>1.1.7, Copyright 1998-2006 by Bill Spitzak and others</string> + + <key>CFBundleDocumentTypes</key> + <array> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>fl</string> + </array> + + <key>CFBundleTypeIconFile</key> + <string>fluid.icns</string> + + <key>CFBundleTypeName</key> + <string>FLUID Designer File</string> + + <key>CFBundleTypeOSTypes</key> + <array> + <string>Flid</string> + </array> + + <key>CFBundleTypeRole</key> + <string>Editor</string> + </dict> + </array> + + </dict> +</plist> diff --git a/Utilities/FLTK/fluid/fluid.app/Contents/PkgInfo b/Utilities/FLTK/fluid/fluid.app/Contents/PkgInfo new file mode 100644 index 0000000000..c5f93635dd --- /dev/null +++ b/Utilities/FLTK/fluid/fluid.app/Contents/PkgInfo @@ -0,0 +1 @@ +FLIDFlid diff --git a/Utilities/FLTK/fluid/fluid.app/Contents/Resources/fluid.icns b/Utilities/FLTK/fluid/fluid.app/Contents/Resources/fluid.icns new file mode 100644 index 0000000000000000000000000000000000000000..0fda05512058483e39f5ef110b8b3bdd5398247a GIT binary patch literal 34579 zcmc~y&MRhMXcx{*E>>n>VDMl*fPm}|*dOqJkpE%-$No?KzyDx>kYzrAO+K^O*oc9F z@#JI%X7}zpshteWAtB!@IvJQ#|Nk%PWMEGJ?_=7@z?}X6L3Sqt^Q8a(XLT^J2K_zI z^FOMMfnD$U|I4fI-ZE}s;N;qKzW4wC{MAQ!n;AG6H57OR1f&Esn41|m<SOQKaxl5^ zOlo1^NVRC3-sF~A*ww<oQLmpnZC+t<TYfVGqe;+AhRF=fo}2E1oDjR}H;NOMg@B## zJ`dRm_m9Dx@bc=r#}FqxKlcCs_N!ngI8E+r?da&~nC#NTz^&1{?r?2$!;IF0<(dr) z%HpLPdo~^3Hht;pZS`eh49p1)yL*=JJG5!l))fs6@vMdo(`M8)R5RDsRMj*zu;@#g znwWH$GDu8jVD`QNc3}Gd|0oXpUkrBO{{pxJ8H4^d{AY-2V_?*K-uR#KwQ&mrBiEkh z|BPVAH9vjv_y7OT|DU!rF>nXo&Gmfo_4m?GvF}407_{_W&RCHYnX$N`IO6XsT?Wqm z|0{Nt26{B+#h3j1zn44t|IxnR-@bnP_2bL;hW{+_#@SgJ9oY;<#TL2Q3=E7M3?RVh znVTQM1Y$uj)3^Ws{|iFcVDkI_|Nr^GEC})Y|Ns9y5GI)X^Z);UE-(v1fKn3+gb5-Y zL21he!~$dSXCVG-88C-|foTtj`~Ux8W{5y7g!})0Gnnu27smhN#=yWJ@f61W|NoUZ z1JiB<_y7O>j7`Yg|Nk4_q4Ga&dyfKkdpi3m!^4690|NsoSpEkCgZ&={hWdXH{Qo}# z<NyB+%>Vx%0Acq3{~z%G|NlY$|NkE#Z2$lNpZfp*L4kwfDv%i1tEAWsQcFeqGjl*0 zo8|E-2G;mR`}gmdJDq`bV^Zet|39WPur?d2J^24+Is@yT%Eo{H-%Mv<IMMi@;RTd_ zKAnN}#Q*;_YPHiDSkL|cA7dCcoq_er|Nr+Fo|(?TaI5h@!-MGz438TBGrnP&%D|A` z{GXv>3InI+xBvgoP5$`*pY<dLMuF=M|JjU<s{a3fE;^BcVP4~ZrXcyn4gVR|O<-V1 zYx>Xr@6G=geS80x_c5?)fBAoZ*{jC?tP_lF|Nl1bVPNCF^8bH=adG2+w!OAR|NlP| z=w@KxY*1hll;>|(VBqOtU=i_=F=1+AU{hsfV32cR?Pg%%I+{55YBK}tQELW<fP38x zf-Kn^xGMXZ71<>@m?Rh&^qXdNGYE3+=n>lQnfik5wRG8WhH1%{LVFklE}8Lu;x3ux zevzTI$>%8hJK=5yLEbNHK6^!W`E2dtJK?{$GU_aUH-n(VZibA53a8qqFXDcZTz;tW zuxu9tlY3>tEC!~IZ04&B$f3P+<CeeR&|WlS(g$#8AKY``Kd#W;J9!f%wAal5Mb(x6 z|KDG@KAk{lKRfvYDYR$K*ozd}EBY_OLc94t+qeIpkKcm@_WR3U8~?K&pE(Z^*z0HR zZ2Zr5Z{AL5U`I4eVCv{^Z=b*r*~P$S(9pTKb4G1b1N+4KhK9Zcbru~A?4ngIcjq2> zl;70A@t~`|Vabc!YN<8`aki|cEho#iZ!Yg^>~5-WF0G%oZ&ztUK6@*JcyL3@&5bqp zy4JqW|5~yAR`IDhPbSthG=#M<Fqkwn2tIFU{+_jC*YtZi2UpL%p7%AkzM+A^w247f zw7Q|8^+)ECi<P&#u5GA&+<SKE(mN%M4UAP{4GfHI`3((1^Dh)^x?1;W!=Z!aA7*d5 zzWG{BePaVl4m$%wU_*n@f*sSV>WZo>i>r!i%S&sEDvE2G8@PNJ7!n#9>US;4tDn@s zoXEgn-jKi)8y!D6fx%)Pa#S)LZ2ZsgV>$zv{xY3`;b`N31}wP-oQs}MXJ9zj_@Cj) zbOweijsF=Q;)z5?&2P>B8KL>5^*<vdtF%KiN#}ot@;(Me?Ju4G89}*%k^4&be@1X# zSl;`eVR;t=Tm1i5>uw+a(e$7F#+U#9?{EK9*ulWA_4$iog`3p<rvDt~^Zx!{DRS$Z zX&Zw$&z0X3jc(L<ytwt{$*14fUi~{;?)duuJ>FIZ@n!!%J9=NTZR+Q{EWEQ>^;vq6 zO8Jlf|JSrIh^GJl|4(PiTh9IM4hv*%R0J<lInTfCU&DWf%q9jgP>%n|esqJzDW^Io z@B5}TA(7MMPXBB8&-g{Vfq{|dUc-N(y;={ZsP8cd3AMc`QCOy#ta{*Y<A0VLd<+Z= z8~zJzuFwDa`^mRYPd`8X_5Rh*C-0wqZ~o6UgMnfH|Ns9|i*Edz^q=z}14Hiq1N(Pv z+t;|C;Xo?{7tCYG0atk}kSY&c-V!8Os#aXRfB)WzX`I-Va(smr<SN+Z8J<Js<#EWr zhRVy~kpB#om%<?rs+d7a#0khtkSPzU=t1TqHwKW6g4NB)jR9nNSY5}4EQnxhfXoJA zYlIjQi~R~n4uqcyAqm5ovq4f2ydJ6f0+Wx1NI}Sam?)gqg#|8H!B=y*1cbqH0W1zD z9-;Yh7F-6(ScBq(7^o-`6%R2OOsc|C4wC#A1F#f`;6}3?qUtuh4K@=ZfKILi>1AMG zNI;i>@ngXXG(N)k==3i=1_lO1u%k==|9^#*fnhPGFhXQLLkfa}jg@#Cn<zr;_I(5! z8|&?LY@!IUm)0lm;{m5FGLtiu85o#6z(K*lz`*<f!~(VBAgwuClAx9%1H=FSARGVx zZ(sno7a15ptwja~P<s(ff|{ZK|9@a$0JRz!7(net28R0o|3OX7|NsAi41hE>|Nn1b z1o<4)-2DIl06T~cYH~svoseed|NlSiLE@mMCzi%1ND3X-g9QG8+z7&>;R6Z|WDE(P z%nVSInN##X!#oCNR)^%-4GWn1iuD#Vuqgb0fB$>qe}=ln46Mp`G&PLAHT-8N0C5%> z8!Me}_|K3B;_Q>t6@A|DpCNZK1B=$bEfYYE>iESB47#oV8DbVQFzBGsx{d!?_Grl0 zfaE~zd}CuZ5Zk)(KTCy<zD~$u1_t}a|19qsi!TI&*scE=K(ue`e};g?3=9FS{~5v; zGcdHZ{%2gvxR8M{^iS)5#=n^h7#M|KHU4M%bmUvZf5yMM^B5Re_B8%yd0?Qf|DxeP z<7L6Q3=ET-{<HKM8mrG~{Li?OaW(^^^}nY7EL#-~#f~)nXNa7|z^MAN`9Jf&1raNn z|1-YVo58@yc%bt?`=6@N!k_;y@K0x8Xl(e;^ymHemj4_lwTxAE{{KIlaVi6c`>+51 zfBUJbUu*u)aZKG<VcY-ze`2RFFiJjb_|Nh{!&q-(^M97#S@!YY8~!u?Qkl%aAkt{S zq9tk|E!|_lAT^7DfoT~78(UI=mSH4wD+8m3StA3pl6L{mWCk|I4J~WeyuQ@Nz;y5h zYXbw5+`W5K7}#9@s7cFx?P+6Rv<q%zVB-BeYchkR;>uV0Oz!{P7)7o5*$splm}Mmx z7=*)P|A$RxkaT}{Je;ZT6OY}8_iUm6twcBdw`H(-7;)s6*klGt@n2O83|DtDaD80D zu=Fhp!?bstlCSF-_MB#%%pl?U--SW;UonH@|6sw7D;OBBZ(^AIO`QLG`xFL=#y@-v z$^Z12IzRE%{7+y|_>;@>bU#DZf0ro?lH1QQFwA@Fu6|&j!@U1qX0iVRLOySlJMukT zbP|Ik>x*^<hAHo(7#4rX2>af|82Y`NY2vq@l6OH98CY2P)c)$PU|`AJUAUZa1p~88 zRTkHOh7AnZlIi#NzhTMr?Uczgf5VdLg_$!af>I_pncnZ8*7X^dO#k0H@ucxT1EFMk zcXIzeP|^e?)9o{7P6Dw($#l=O>C<4z^xJ`*&q2x4p2TGO^WkrlWcq%_<msQ0lj-pp zGbf)#Nv5|Z%;<gyPo^#ZnJ%okf|5%A?OC<s4<eQR`~JJ-KgW|PGbi3bN~M37O`80w z`9H_w$ulS1Moy*gr_7voqWM3|-!1dkgWUE@WfB7;Yi8pNmZ@DcdV70jFcvaTWMFV> zX<%sVZ(#78z`&(c)6leTbMKUu)%7h6Op~V7G&HbIShS_KPN$E7o3FT`;o62XCq6yM zsB3B9x&I-ruA!m(&5P99GT|Nu9_HwVhJ}9%>neV%-|;GHogr>>!)<>$`K`i2zN zZU$M0hKBx2AF3+n|8Fj7pVibfwY9Fkv#GkFW97>KJ;e<T3?5w!3_1-BQuDrEpHh6} zThjFJUow~dZ)?8#zoT-_yQ#N-r&l&KFxF{yFfei#G&D$c{8^k+{qkH&!}tB^=Rd_) zo%o#C_H{-2ty@X8jSY-7{A~=3EUAqRQj7jKmG=CfpFi(^SJn4J>9wy;rXKs5Ui*7Z zPJL4YV;WN{1A|>tgXF%y$yMwBm6RR&mbCr<q{806vkN|6Oy2Onv81Je!LEgYQM<0O zLAw6dout~cpIY1RUTiz|zomcG|Bg97PFCFe*;`lF+`w3;(Zs;WSKibh-S~M;PTlb@ zQwz?1oj?26n%t$oHf10DxpnoI{=&MJ2F7B625@XN$TYR||1B+RsLsi+smjT(%+IZ= zEy%5`%FQjyE2wE}U`b$MU=V0(kluQ2&C!(FhKBljFosefZhd`61G4~F6-(EK#o6Wa z8(4%G7&r?W8(8YA%B$<=H8AFLH!v_TEf-*5S&y0N7!+E;^#X%(E4WGk(|L;-z;y0n z1_rHG0=WxXDZnZT>(>7a;2Z_bMI_~>c6f2$2`lEi;l+CotXS`bm*@Te86hS4#Q%(- z!kf|k*Tnyf(BgVBsCb^lz{s_4>VL))Y!ew6dZ+zo`ZtNOpMlHy`~M%a+KwGt_~Bp6 zf2L~(el+}Ny|cdS$?u3h25y<B|Nr_%+F9_)Ui#DgpZA}Q;Ke`x|KE}oIsNOkY7YYs z+qVDzw=+&VzKz5E#^09zyjz=Z{{8>|9k=b}zyD8gcQeQ~{QrL^h-d2ijSQ8~pX_`7 z_4Jd!KW<$4{{Q8Y=?uBg8vZj(=wgry|M&m@I(~)9CpqkEHuG|wSi~^nt~<lD&j+L` z^_Ule3XtD{9Sn?O_Zt37J!TEQ@m)jf<Qrb|bD><@zou|)x-A@h&PM+5ug3q3-{smE z7&%Tg{+HU!Q1kjeW5m5(4EYy%P0syN(>tBcy5KIm*NuNo{~1rSwlXl(H2s&XVO;rT zCS&ibV)m6~45^Q9GsoVLP&?MgQ2nCiKSNCm17qm##{bg)TxE~^isPz2WToB{$WXFr z7DK@#F8$3Wthtx}H2-J(?cc<}DD$rAzw{3=?;C&9xXK=caOQTih231h=65NPEhvw> z`tjeE|BTNR8W<QkFE##``T6EDWAB^)UvED6@#V(7Pxo$r{q^A1=dZVJy}k3`XWM_4 z0~`zt3Qhl|CzzI7AOHFP|KERL{O{lY|Ns7i@xOl^|CtrQs#x!27axB2Z{B|v6$S>u z`;Gru{(X7>{olO*jCaKw7#LWWD==`ZXUG6|vN=iVWP{q6Sh0YWzrVk~kC`M&#|o=b z1_rLxx4%Pso4-$r;827lEC}nmf*N*~ND{c1@V@B(|Nr%IDMAuQ?#AdMiQ{5E067GT ziBbOusun~MqaL}>r;5uFNaCMB217Au?g&W=D-*dlO$+tN?!h(Og6yy_P`869V%!58 z>Hw)1LpBHp8#LzuQVYVkhDVUKlByn>m_f$>XGJy$J6jN}5K3rcSA!(Vx*w_(OkIW# zEFdXCVU~i`!HFd(l9(K8<k0;8|Nq|*Of^U%Qm}C{xCP(vC27V@aCLCT89ZUs2v>!~ zn81kS02HPzn&Tmw{>7juLU4qhLKL8rU$76_vFt!s2;(2(Mi`1<p@lq5F^HaxPz7f> zf#&W&l34I>8@MtUL;NKcb#S3)3NUq0nq@s)4lCmr@+=?&14B7hRY-!JP=g_q-7h35 ztjxcD5S3t36uFGWs{H@|kD_3uAcA!t4mBvk+u>uC1t{V;ITJx<GcYiC5_CMoh~E$| z@IQfY36pn0>4FO-!{XPpi-my!K8uQ9DMYrJApp5}f(YUvf4CmUBa21q=y@!Hc!bWA zsQ%qKJcePB`d)!W5RXtXQ~Lh%M1w<_OqnI1!6DU2ptSLy0Tr%fU}9oqXk=t!U}Sv5 zz{bcaZ<#XVN85k4pSRb~>?*K*%D}{U{`;i=42(}07?`H~f6BnXIQc*09}t(N;XnI9 zRVE%L-li`d{~4b#K4IWy|Ns9WvxJeckpzQl$A5;)PZ?M^|NnQAXfkG!U^v+RpWz}z zgvqGMn8}E#q5VI@g{KV6?EnAsv=}q;fcTf5GO)1!|Bs{sB*O9kKQF|T9*7<uuK)j= z7$8>herf;DaPBDsx6uFpUtAfOc$gS?*LM78*!GlxL9X#X!@-6I#-1;o{~4A(WnfU4 z{GVarQw9d*$^RJ^AkiT4#ZdW0PZ<~#(d3n&`atSH@(Nx5IS=YXy#F6;VCR1>xaa?a zjqd!<2=Y6#1j9iPU!n6qBgkLOMobMLtCTwbGw`$+Gx0Ql3^YQLo${1{!Kd>-BgoIp z5)3^ZPZ=13I{$Ma`4}n!_wRp@n!s+bZ&`Z2{0H-cCjVz>d&<BNJo!IEJ4nam{|q2? zNl@{s$^RJ|o-!~rLg@x1x(g!Cc#`ok10&;xDgPPl9y2h6O#RQep5-9}qwSBW|C#<Y zGu~%lH26IIKjR<2dkl=MCuja=e5`YqfuVW!f5y*Tw;33Dp3M2rP;!fbk?&adf3|}u zj0{fTxUj#$z{t3&`#;B8W)Tey5e92eBDyDdoq-{w`#;k`X5~g>CS?ZK&i{;uSgtZK z+WhGL&sZwbY|JFW0Gd|Z%y^lB(d<Xhe@0%7W@9D|hMunf3?Y{o7+FvC{%2%>h&6Qm zXS^eSk%6J6??0mxMDxLJ(2(PK21d?%egBzy7$ElW_WoxGImf`rcC7zD=ND@Ru#=eA z_Wo!5taXNgk$LmP|BPQ;8yOgR*Y^KsJi&2_fst|Xl>f|MdKwN+`p<ZP<s<`x-}?Uy zQ%*22@_t+RpB<Jon*TGtQ#;PUP`L0v2RwDO{AawQeUyPAWDz8RfHFtRf5!cchZz_w z7DEyVD0{U2XNWk&z{ql`101c4Jzpk)Qw$?dL+gLW&ngEP7@20a|L6GP$}FuW&CI)Y zB0_K5f5zRM`xzLjI{q^?ap*M|GwX5iewhGCQ%n*JJ?;M)cd+bbU=(@R@t=`bv&ooA zlc8tAe@;Xi>-f*GW)A}+?}^U;3>+=Sj2sOUKz2bhSl53BgWU`ai@RWwlVFbQ{?B-h zZ6^Z*Uv~o|1H@p5<qZs$Cm9$)4q?>e_|Curb}^(hdd9%Q;*^(X-NL{q&b^X>nMo-` zXCDJ!#N&U9j{V<Z7g983_w!$TQyG|RK0Wa6WMJ=Fu=Cot|NqtZGH^Eh|6k9r?*IQs zFB|_e9Gc3&-~yV$73pALDw_dX$Mk3~19!~-|4-N$e*OPn%?ld+u9?cfP~P~T!MTfp z;dH})hIxA!c*Nd=r$AQy|8Bqy(q;xV>AQF*10(athW`wadl(ox8ve6uGcd5&$uihA z{AYZ_G>w6|@zdj=E(QkEhX0KJ#C9{Vu)Y5O|8WZgLruefh7~Iq7%Ch7Go0VUz~I&J zpJ8ze1H=A?{|w117#Q|7{AcLi!@w}3;XgxaGXo><&xZdDvdbA5xqdYKXK>rez--^p z@Vwza^Q?vjjRpn=|Azkz*BTkvc+@@erX9*|U|`^CY+&GMWME|xH3+I{Xk}mx-1Yg( zf{=#)jNiF-GB7M{`_G`+z`!sKH0aR4z;LY@!uM_X&v2uGfyv>=zsCOzZOshqqTB!f zzt(yCSHpjXJ$o1!{2Kl<oNi%YxYO{T!K;CRk<Y8~Kg0D#28LN6lNuQqdCD69GdMOe zu*={1|9?F@gLdP8hKfB53~den8KyNeFsL;AXZ*p{$iT=7nr&}uU|?hdjeNK@F)-MG zVu!tvfkXKA|NmFH7#P?Z|1%ixfdofFGXq05$PrBp3|fu<8B7`&7%Ut9Gk)c0VqnN` z_|LGdk%5tEN5g*xy9NdZZEy_iW?*Fg)bO7{tC@jeW5a)j@+Jm`jE4V=j~E*m82TFi zGi+{VVA#;`pP{G`EWxm&k%1wz;XlL5Jq!%G4gVQGF*PwTvVjJb4VoAj);0WRnApI; z$o#b7KSOpC10&0ahW`vY4GfF|ZyWwIxHLj+N!`Q1klOH{VP7)?gG0lA#utnr--6uX z(7?a|3NNK5(4q`bt=Irg3yilJ8$cyP!+!>aJq!$U8vZl1H#0D_gHlBk1A~3Tf5z9$ z4GauhL9x@!z);=rpJ5>=<Q_NtXJ~9>V2Eq@&v1J$1H<Kp{|o`m3=C%*{xififzu?z z+y(|lLr_@vH$y@)wt<1cy751QQ6q#uV-Eu(A1GamH!-k^g2q%Nn;00*HT-ArZeU>8 z+xVZsvx$L~>&O59|0Eh17^)inGrnVLU|`e&85+8Wfx!u6dou$=Xv2SzD+~-uObkN* z{{R2P!N8Do`{n=tzj&G$7+f3vvtD9g&|m?rl{(PKz_6g<Kl49P2BuwL6B*_;GcZhO z_|G<tLF9oJgL}h&*0l@_I&UHx{<9xp;5Z@%_6zG|2GK_vn;QNztZiUmw0PC<pZN-d z`oUe0NQ`M_U^vw9pDl%TR~0x(u(mKLKg^74_|M$KIA?wXSe7-7ZC5G7yoUd*_gEMd z?skLn5ZBq5T?{PGK>llHV0hZ_pKZ^P9ZcYuVZGJ&ZWbuJGGEwyo4<j9;d#S<);-5I zGciOp{%6@e@m)zx!+)kzr{?Zr01fYfv&MzS|BT1^8W<RSoBlJeU}4B@{LlDEwGq4+ zjrAxG0|V=+rvFS`4C#&k88@=+Vqger_|H()!oX^A_0OXg&PE14#;$jNZsamCFbMAZ z^LmD869cQ>xj#=@IT{&wh338gaV&s=fqTpEhh@yW8CW|0|Np1-gMs<b|NjR*GjOUe zC}Uy(#Z};E2F|Ph|3@?U{{MfH@iPO*xBvh17}oy(to?<7ebN8_%2EH`JA7qe<LtQe z>CR*sNLh<aUO;ON{%4@HJ@{Z!V_Rd}fnP}N!3T{!GiJ`{X;_444=(6wn#t7D@Bq;s zY@E?FlW9id0Z7{p)E;bWnaS7&;)7a$?En8GsQ`&^{QutuG36LU52!tOpaEi4+b=|W z@YkY-#<s?Wwrfc3!3PZo7?1s;L3{AQbcpxi?LoNb;q5_?-<f+F9>CgzAb&B>XgmOG z54N?;WNJGAYY)O?VeLVXpP73aj)B^6p!Oh=k3p@w&i`C+|AO0pp!VQ{h660ee*FjY z2VHyc!KQ|W1>m@Vw+F8^c1@n#)i4*7h~VwP2aOXNXEIG_ScK9Z+||`Qlc}rWSLc65 zM0>Dpa`Q~4$qmPl+k*`du>;8M!37Y_4^Y~J#~L8^v>~?#f6Z+GJE`#+N_+6vqQ(Zs zwreQu!C%J?JeY*7JqSx0$n8OR>OgJ}f)WTQb0D_|LCFA=J&@ajkVHJ`KLaGEptJ{n zEo$nW)Z5f{ZQ_4Mm|o=e;DMHD4KtaiwY2@3@ShQsrkHvfj-j*%+om+lWSY`&Y{Gv| zL>fbG54N<-WNbMw;XemF!6CH=A(E5+Ge8^(YY!T9A7E^N7`$Nl0fy`y42*I$Jq?T? z*Dy|NS=qo?r?icMQKG7^fd%Y=)eVeU99tL|nNkloFvc)#W?*nS+Q1OGiGh)=sHK6u zzOJ^mrna`OvA&^hY6Ek9eO-N516O^0U0rQ$U0p+i?gj=%mZX*j!Mggnn>S4>E3c}q zsjh0Rudc11)WB9(Q&m-6Ti@2eTVGpKRn@hmud=4Dp+IOo14DF6gHYXy5C2Zw{eNx3 zf=x$nefm>gQdKvxfunBsk9V_*%4_Od8u;rEpS$(q*Z==bg%!084HfKb85p!%8o28A z{Qtip>FodiZ$5&S3nu55*G_0)tY6UZpXEnkUPWz719RPuWB(fdbG(VqEUl?;Xs}qr zz$jMH+`v<}`v3p8aj}2?|6i8yv*AC>vgph*kmkCbjsIC%(@JXUn;V$xs!JY%s;F=f zzoCIaeH8;EM`?2dZ+*x2|NmEo$DjHCt0ewk!+(~ds4TGEb#oj3v;Im+Dyph$ZeXsj zsQ|6N?+QyV15cUCtz=+uY-wPuJJ|4_Juf0HudgJot>HiGNB@}I%DM>+Ty<5uzQ5^; zNGk^Unz3$b!++L)(NWnIbxjS7$xO=`7_?g(c<R6W|NlB5Hm9UGKWB5pf7XM6iG|hm z6B;<{Yszwx6H@XjYFir^>vn=>+x+A5K`vpiTgJd33KCt|@SkH}P+~!4RYlqDhX1S+ zLLq)@sPAszsH-k5$S*9fscULrsjsW6xzq5Ubxlw**fk8cOBfiL(?Pzft3J{2pJP%; za#2-HZR4MY{{jh-S>-i#wKX->)it&C4Ry5*HN3U;4Gnd5wbhm7<&`ycji6LeT~$%@ zyWu}eO;|=5$c+_Tix?OgBU>7n=k4A7so_8S_LUpj%4%wtH2l|j=pUC?(bzX{<FR{d zORH*|_wCuetFoe|uC}&i!lIqKN-JvW8XD?rm)!dC;}j^+e+EbARMfRKFvc-1WMBwy zX<)3s*!G{Lp|GOnM8kiU4M9moFPs0f)aH~{FK+nH_B^w&a?bC6jsN+!WtUXfHPpA? z{Qv*y))#*o{<EGBNGPZR8C7SpfPq216_gN4XEglhxak!fmr+nr^`_xJYkgRHNyD7R z|Ey0U(~7E2HT-AW8kb#GUB9LAKW}qVeq~)<&zt}MPbb7xH~wdx7o1X3Q{UdeSfw(L zfswho6_hs0cQ^cJ-|QEimRDNU)9|1DS4ebDc~$wphX1Uq!cvQ?J~sSkYlzA!uc?~S z@SpETSbSb(ZQGmw{~yOhC1*GOXUUJqEUWEoV62gw%fMjL-oR8>b-Up|dtXR$L3wq} zriTA)7eF4V>1+JYQV^a|I<4V9`;Xw5+=^PT<mteKf~wkE4gXoH!xD2kK*`V#lnlEX z7^_%kGcc%iG%(fI{%H8mo*9`{R#R7dt>Hi0ypWWVn%eaZ|5;!8#pIM9ZurlB5@bnT z?bU|=tg}K=OR6_C{AWEE7?V}9uHirHA#mF4ZeXyQ1uB6$8W`&*HT>uJ8W59LRaamC zqv1bW9>^QDR~r7aZU{;$1o@hMT1aY1O<mphhX1VD5t(I8UmO0j)`X@MRa|ZO&oU`A zt+b}MfkANwsQl_|V60o;@SpucKtf@4UEQ39|LpI<xvB0)!+(~Fu=JAojsMwFBC^VB z>t;0kXMO7*lUK2;;Xm6`zv%3;hF=Z;S&|~N%4>TY7^|hHfy%$G2FAM64gc9!f#a<1 zK*N8weSt}Z)gZH3KLkYQl-+3f&;H0SF0ZPtZWpL{06F_Z!++MLAjYbO|Ey2Jl6?&f z5z`nLoVptrYhN_{XKxA5D66fnebVrstrz46kkPC=0uu`+{A>8nzCI|asJgE9PQ!ne zp3t<C>5czc^TIPqt3Y{hD@d-szkxw(3aC8pYGA5w{@3tdFeWOeqOPtD)XRti<-nS! z4gXmh!qSRwH~#0Z3rjDpscZQC|Np<($gI*G4gc9b`NiZ^^n(&u8^{6m{SAy&qLUaH zS(3XO7(qoB`%`d%QMat&ztjW2*oKPg=70bHe+!DrTJh@B|Np;3qO!|sYQYVDzu4yT zvkm`QFZw4GRGew}&-O1WGP|s%ZbAcN3iAX8My9Bq21Zc$u<r^=DypfgJKFG{ZA)Oz z+ph9C4gXn>1jMy`ncMK6{i<K$orcP)0}cOKHwEUrYX>ESBY{bUQ$Xdx1HY2nC6%@H z6B-!fnfe$QnL>LT7(oe<y$9sG`r7*q|Jf#lUfz^n3`%w@0!!YmnBVZ9eNDjrV+ExZ z_Zt4QP71rcF86rDf7Tbl3H5LGH2i1Z7J6@9L0L`R#0CbhJ_ZJzz6PF}PoPi&6}0uW zplo;k+NF$~qU{a;S)XkDaxi^E!+-X>r(Wdc6qSDhl@B-0rDe@;{LgY>$Cou58~(H3 zymcTox3s!$VgqA^a1R3`XGw1ZV|`b{e~w$=@T{+S*7%?GW^!s?$^54O%*T>aS2X@- zdtH#6TT=0`@jvVJq|}_E2TlK(wj?cT{LgkWHYLBjrhZZbW1d78sDSKiV60o(@ZV`+ zNJ?={eM9Y(XMbO>ii*oDs;Joa<?oX@k%?IqH~)UxnG};=SW(^o=<l1=QE^#CWi`jX z{JPN<ot$_1&+CO@aako*byFG`B0Cuv8GZU2-0Kd4*3W~oUqeG(Rbg6OOk!qHWlc?K zPGU@KQdUt}QD#DHLPkMFO)Xrux}q>WAto**r!YSwAucJaxT>~(Y6F922RNa7*Von7 z)Yjbl|Nl||D1U%T=!&Ae+=9}o+Pb>xvVxr4!m_IBs*?QN{F2Jry87CRVyJ9wWl4T+ zUQt<PMM*&(NPYeE1_q^e28Noh2LAeq=eCuV*Z%(hzbz~k6a)?C^|jTNl~px$pjxJ; z3e2plt*NT40#!f_^|jR?W?g+leH}=)8dN)hMP@cIRJSv9H}KWH{QrMm?wtSsZw1HX zRMa+utGxR9rUr)khB`*j@*fa`p&nI&p}qmCaCQUOnA%_e|1U~9_y2ogL~2oW{WY*C zZ|%AN|8uAO``Qwflvh!E9V%F}=hgQYdx{cLa?5J!A%Z-0RmE8;$*JjCpd@*tfq}n` zp$F6uC@U-|C@QV2sk_<0pxDO15C+OlHH}qFHFfnj8yIZc8JL(YBfA?|L5;Bb`kM_* zsdkL8F6S@mb~h)3MpvFNFtASsPc$%aP6kgefawcQA>x;iXpYI?$p!|l$>7NX2BFE& z8G^}Fo)~~m6yTa*08J!-`*)N7Gl2Vb&@p*X-wb(-J`hQK@QmTl`_BOBsm=e-2<e?I zgpbfKf_KA~z{cX2!Uo`%!$;j$z((3v!Uxw^!-v$@V)UKX!v@ed!UoMZ!$!)t!iLAU z!Uw~*!$!S#!bi7v!A7z7KnJY%LWie=_y1>@y8|?nvHw5gFPCkgiHw8)87~WM0Zn8a z{?E9bbu$A)bNl~>e>*@v+X$M>X!+0d@9*!1UyQ&1HvDV+%kXc?f0lp${(@E~HT>iF z`{(!XKY#!KkKVw*$a$pYzu@1mTe~{8y?+1Y+xKr@?!Nr~``@JhY=3`!`||DAzqbFp z|9=1Y`r+cD<DY;0{r^B^9RnldwwC`we-=qG`06p(ES=GqWGBXQ<<-|e6aRDkZQzla z|MdOOe=Yy{{}o3&sj@RLY<u+K*T4Vo_|`Hogth$V`cuuokbK0Bfk9NDk%3kB`0e+< z{`LQ7{I|V<ft6#|y$`?tHUDS++Y-mrz`!B0@A9i3|Nj3kT*JVq^RD?n&)@kB48j|C zvoJ73EMse6U=7`N`3+e6-<C!OmX<Rwet>m<f2q^Jz-qG|#Bcb|;J1o_QQ#G5t=v<7 z28NJz2V5A~x>hhXFtAi@zViO}g#V0xw=^)Yvdld8<l8^cs_b8{c^Vj4lh>Vp^9!`y z>W9rr28O1V|BQc18W`ByH=Vw|aNXVs4GgSYvv%G7^k>3<uD@Rkxr7Tgo_YS`A4u7O zMh2FiE!RH$Y5LE2jBPpC<GlaA2s1DUF5GqF<@0+tavK;}jTRkx{O#X_|6KomzPWMi zz^S_*euH&4G%&Er%-eVG%irezj5Ul)L7kWXjDOcRFmRYJIrQ+;*N<<k8W>n&R-JkI zv-Mx&|Av1}|2hBt`S$wZy(jN}{B8Wt`tRT0KR@gm7+9T`9(x9I5<}Gz21d4XAiw?j zp3uO+5w-mIlP|x1y<lr#5NY3h_1(`uzkmJs_U*^-fB*je{`uqQ?}mSzfB*dY{`vj8 zPe1-P{Ad3MN)Vr(f&x8v?S(hLKrVeJvIsQo)cl|2-@cj((FO)~tB|DKZ@>Rq)xe-5 zF>lY^kFU<HX-~9hdG+Pj$C|40vd5o({`vjo{^5m{#jig81hu|?t#IJx3YiQF{VCgS ze*Dw+pK%Y<0tQCLbuIrH|3$Phuxxnz@q0=G1B>I*V~^FE8CX`{c=c^f0|TqvrN^Ik zu{SaBC0u{;?eD*TPhA-p<Rhh78W>pB794o^^>5pM#y=Sg7#RFp|1<yl{%TqS1Bc9% z<$EqX{P0zwfq^x9?fI9Fmo+l5N^L&#^h-hm1DnsD>+iljuWn@EZ8>`X^Pj)Bl^7T- zH|<%_$iV8i{N#%t|JwgEe({*cz{vIuWaO{+Sq%*AHgmU~z4z+Nr3MCemMPnAy#Ml) zv4MfrbM>ibA0-+X*owDYdH3VXh6V;cw)y++eg6GiiGe|8*|uY+8W~tCHe7o5`(MX@ z#ve9w85q*r|1<shYSX~L9=qcB!}s5Q^ffTBsVzA0;LDHWjSMUm>o30E-N3-kHhssf zkH3DjH88MgEjsk*>kpR(2A1lzhi~ozr^lVQKmF+f&1%kOVDRbq&-CvrcLM`^{iZ8# zfByO9)xf|Ou;S#4AHP6}S76r8Tko?Q7}#|d9(ec_EXx|S;?#?86B`&<wHNKY`l1V- zNW1?tl*|H^LLL7Z|DA4N;NY0O>(1vt|Gw}vFtAl`xcu(dFW&|RR{JGK9=(%jU|<hh zaq7j7zhC(p7+C8zTz>mZuz`WKXw``)A3YlwSff^*dG+&O&wmD|8KB~<^FQO?DGdzl zstXT2`u6Yd&ISf{o;ka2fBOBIr-6Z`VC}h=s~Q>DS~gvI_xta`1_oBXIlFFusBK_i z6P>gD`n%^G4Gb)8o36h9-TR;Mo7pr_vDo#W@lSjM1H0SulP`Y$17%t^(?y3LfBUnu zfq|8K=Jp$JTpJkJ#pdq0`}xnG`UVD8v&Baqy_afWVD(yZ<k9C@4GgRz^Y+~R^0)6l z<9f!a3=GX(|C#>%(rjR0&scZy?XQ2o^cxu1;#Qw|_2YMO0|SfYqC*c3G%~O|EIIb{ z``_Po4Gb&^tIxdH*~q|Jx$gYyub`Z0v*hU0@BjM$GlWb5711CAUokZ>u=i}e@$t{U zCyWgYY+ayy_*1WefhB9rnWwgm4D4BJ&b|Km_dR<9154NDt8Z!=7+5)H?zs8kOd|tp z%Ib5keu7HQ&svih7&(r0|7ZNWt$~4EWZvF;U;h4G(!d}kF>m*tH{TvJGBB`D+j_NE zUWkE#dE%C<Z-4yW+`zypHE;L!XCVy?tSa*lJopsV$iUjY>C&4Ye<y&JBTrypWZu&A zpYcya0|UFolA}+5{QHyDz`$m+XoJ+DcdHv1SoIg|-6YV{z`(9JcZ=bbPu~g~7+CEV zt(VyE(!ju~x9ISrok9%^>=LtQnY{S?>)(X`jC)!77#LYr_5Nr4?cKn@p0MWJ>tFwV zSvD}RMJ_PPzyGYMfq~V1(PGKE<^~3Kr}=IH4_<w+XkcKCTxe8$E2x2iRcPLU1M*1? z4D6QEl-eG={r-32e}*Z23=9#y|C#>%6bA(+sLcKM3zYHHRZLFbd{W-Pz$)s_6L2o0 zfq`9GPio(dXYa%s7+BSnElywSYGh#1^5-i8Wn(!7w^O%YgN$T+r`E&3DD<NDKjXjK z4GbJ|^Y`8V^7r3Qokj*$l{KgCyj;@6z-+zebXg+<o6wA7w_biUYGhzlU3==*ZM`N2 zrjR2b3B&cL?!Ei@Z_<CpI|f}0jLe(*{xkkv*1+K8zv9HRAOHUS+NHuI?6+j^<!7Hh zWbiRb#H~Mk<(xSauj8zp=O2Ikc1Vj!$al%!%TM223E*K-DcN@Hm<^Li#PYpYUVQsA z<v+uwPSB)!&;N#hjDLz67@XQRf=ZJAe?C7tvv=2_OHV%i{Qmm-;hnpVUVHlH$)y9k z4xE4Z;peX}kIwD`%YOg(=-mDtdr#hYbpOJ^J%_J6`||tW)c*`Y9SjUD-T%G+{rUCt z*AFWO2DL?d?|%OC|Np;VAD`a6{ovJ?Uw{96d-LGdtw(RZeE<C7-tGG@KK=Up@7Jei zP}yIfU);NO=gHg8A74JW^YHbT-~XonXK-s{U}XH!^`HOW)tH8t@1C<UFyyQ`_58=b zhW{4-et-M?>C4YQpq11=zkK@i_2-|zzkhuB^ySBIQ0?&h`<G8&fBgCP|KFb<Up{^Q z_Uq5@A74Iy{rTtLjQ<SZ+87uZyZ`h3(PUs~zcr76L21dZ8y|i*fvdm2|Nem(fB*db z2O4Gk2V#KgDG=TCp9jnb+3@%8zkjp;w=;m8_ltvpA@hhc14r+s(@($syY`=fv6X>= zvFktIzhB`D3{%S(c{;Wpx%=Vw_5Tc@y%~(%|9O8uPm|)53S4vG#I3hK|6PY_>Hg32 z_uKQUCy$>#f93w$AAfKBXOIUO)$^b0&)3(FA3S{W>eJ7^H~%v@wJ|WP?FQA}KfiwY z^6kf;e>eX#RJAiOu@!IXhI!=Xf2NZ)Ox@6BP%I3L;N?)%rkO$J!n#2W3?&wz6Hgqd zvN9dCs%sRFun;I{sIRMsbg}E}s&k_(&^CnAEI4=!k|rFwgS@^Tyi)PszpvNkIMU2k zn89_QkXNFEZAK#gZ9-e|3)4m|+T#b3ZP=KQQ-Y{v9fmnLx6;GhvI;{BRRyGB_TZwY zP}Mq2!*1cS7%E<msfDT{bx?b7QM9(d6_>?Oaa!9y7iteKs+y{yjcM3AToyycD=@WC zRb&m+9$eILx1Uh>ms2&gF%2VRe;KA0s)`V@pVsk@Wv>xRQlz#0XHaaz<P=afv@s34 zhiN5>2=b{mn7Sz!A+*OQj&dvTns5ijx0sv+yt*lu9BBIqg+H!sag_TUV!}Y%PbmEl z_xLB|e_H3ifsTJd_S4$`1D*c|+I~XePwVmrd0#$e>Hq&ft?hq{%~B*W{5z{5Whf;i zmV@e$Z2$k?f)c}t&<i`_5XDj?4(P->B8(wh34!s4e*<j)e_Gp*XFoYO7KXe1gyJ9H zK?P(dIwXx)4<i7FJec^Wgrt@hOnjq%|NsC0N9$2gLiW?b&&XyHupi}|bYy*0VsjC) zzlcf}VK;_tFF2LqA-<p=oQmBb@<h2d;ISDh^@f<!SID!TA%jrpgWRx=Ov4Fl(<Sam ziS>j{B2NWT2WI>S?S>=Id;+=%o*n`UeGonZKeK~?i6lwqARiG0vIaM%#ULyfp_V6- zbN={}<TIia6C3$pXZ)e|L=-EbabK{t2;ze@QJx}NQ4%pZA7TCf|7(agniz$KKatHQ ziam`ObBR?$;`u8e2mYYqOkgm`KvMArVm(JtojXaV;lSL9^MojZ_Ms_oA=KuE*@#B} zO+zz?JT4D`6S~oCMdJQ3A<srsUCWV7B$0Uq)g-cb4y5LMWH(Yi8?1zU&>*tW#IgIx z@-sq{AlZ=*ao;BjO93Je-GW$#jijs;AbbKDHan5UC@KX^2=q3QEyBhAgScr45v@eB z2u(KOvJ*x87cs|aVs#M3kq>dlH!}Og$z&D#5Ia%GCak_AB*;Z*s1wBwe4JmVgzUm1 zPq?dx&q`Fe<5<imAVf@857iQUyaoccVM-I#)x&2cirnuYOdIfu5ZTp3u>>E7)CM_8 zt$lnJ!{k27;q@<?WD-mp^=MKmf>h$Wdc-@B&>^XaAm9Suh)2B1#Hsw}fUp5SYZq|_ zlB()5u4{+TT(g!`gNapt3e6(yTwh8WeE6MGi`_;PQ6)0^TKH{6$bK_Iu?ibU@Fqez z^;tg%_6V}6Zz-~gXR-MiNz92_bw0ACNbG;!NS0wT%}MX)BN<K%^Bum!(0Q&BV+3Vt zj^ODLtftIp;&kuD40fnU0PS)<veR&l&vKnaRz*X0G}OPS6g3-s_#J-~+xRSX8+`a3 zuo>0oU><cFeE9AEKLczfGC}PIAASd54$e`%!H3@g=&i9F{K}~=`!5hV@EJmAT<l}I zAEjF!Ooe_vrWN=_ei_0;K;;E~rL>Vn49-objRk~Eg<X&6O`l>P(>XQZ7_cU^qy<wW zl|<fwF1AoWyAzvAW)o%1WkCjpJw&Obk)o9hG;Hk?;pTs~)kLVGp^_Rx`)O!sH^}IE z@a2gh*1+JAZhzeX$N#MXw*TJ%r@w)=|4Y%p<U5$H8>BzLm;*syQDv|sZcz<QT=zzu zfq}sf`6@1&ScA*ZUvA(Ah|>--Czx@WOPu)MGw{J6wnWgmv9Qh5@Lkn3Wu!vZi2(pR C9*l+n literal 0 HcmV?d00001 diff --git a/Utilities/FLTK/fluid/fluid.cxx b/Utilities/FLTK/fluid/fluid.cxx new file mode 100644 index 0000000000..49e287f5a2 --- /dev/null +++ b/Utilities/FLTK/fluid/fluid.cxx @@ -0,0 +1,2240 @@ +// +// "$Id$" +// +// FLUID main entry for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Double_Window.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_File_Icon.H> +#include <FL/Fl_Help_Dialog.H> +#include <FL/Fl_Hold_Browser.H> +#include <FL/Fl_Menu_Bar.H> +#include <FL/Fl_Input.H> +#include <FL/fl_ask.H> +#include <FL/fl_draw.H> +#include <FL/Fl_File_Chooser.H> +#include <FL/fl_message.H> +#include <FL/filename.H> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/stat.h> +#include <time.h> // time(), localtime(), etc. + +#include "../src/flstring.h" +#include "alignment_panel.h" +#include "function_panel.h" +#include "template_panel.h" +#if !defined(WIN32) || defined(__CYGWIN__) +# include "print_panel.cxx" +#endif // !WIN32 || __CYGWIN__ + +#if defined(WIN32) && !defined(__CYGWIN__) +# include <direct.h> +# include <windows.h> +# include <io.h> +# include <commdlg.h> +# include <FL/x.H> +// Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs +// on Windows, which is supposed to be POSIX compliant... +# define access _access +# define chdir _chdir +# define getcwd _getcwd +#else +# include <unistd.h> +#endif +#ifdef __EMX__ +# include <X11/Xlibint.h> +#endif + +#include "about_panel.h" +#include "undo.h" + +#include "Fl_Type.h" + +extern "C" +{ +#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) +# include <zlib.h> +# ifdef HAVE_PNG_H +# include <png.h> +# else +# include <libpng/png.h> +# endif // HAVE_PNG_H +#endif // HAVE_LIBPNG && HAVE_LIBZ +} + +static Fl_Help_Dialog *help_dialog = 0; + +Fl_Preferences fluid_prefs(Fl_Preferences::USER, "fltk.org", "fluid"); +int gridx = 5; +int gridy = 5; +int snap = 1; +int show_guides = 1; + +// File history info... +char absolute_history[10][1024]; +char relative_history[10][1024]; + +void load_history(); +void update_history(const char *); + +// Shell command support... +void show_shell_window(); + +//////////////////////////////////////////////////////////////// + +static const char *filename; +void set_filename(const char *c); +void set_modflag(int mf); +int modflag; + +static char* pwd; +static char in_source_dir; +void goto_source_dir() { + if (in_source_dir) return; + if (!filename || !*filename) return; + const char *p = fl_filename_name(filename); + if (p <= filename) return; // it is in the current directory + char buffer[1024]; + strlcpy(buffer, filename, sizeof(buffer)); + int n = p-filename; if (n>1) n--; buffer[n] = 0; + if (!pwd) { + pwd = getcwd(0,1024); + if (!pwd) {fprintf(stderr,"getwd : %s\n",strerror(errno)); return;} + } + if (chdir(buffer)<0) {fprintf(stderr, "Can't chdir to %s : %s\n", + buffer, strerror(errno)); return;} + in_source_dir = 1; +} + +void leave_source_dir() { + if (!in_source_dir) return; + if (chdir(pwd)<0) {fprintf(stderr, "Can't chdir to %s : %s\n", + pwd, strerror(errno));} + in_source_dir = 0; +} + +char position_window(Fl_Window *w, const char *prefsName, int Visible, int X, int Y, int W=0, int H=0 ) { + Fl_Preferences pos(fluid_prefs, prefsName); + if (prevpos_button->value()) { + pos.get("x", X, X); + pos.get("y", Y, Y); + if ( W!=0 ) { + pos.get("w", W, W); + pos.get("h", H, H); + w->resize( X, Y, W, H ); + } + else + w->position( X, Y ); + } + pos.get("visible", Visible, Visible); + return Visible; +} + +void save_position(Fl_Window *w, const char *prefsName) { + Fl_Preferences pos(fluid_prefs, prefsName); + pos.set("x", w->x()); + pos.set("y", w->y()); + pos.set("w", w->w()); + pos.set("h", w->h()); + pos.set("visible", (int)(w->shown() && w->visible())); +} + +Fl_Window *main_window; +Fl_Menu_Bar *main_menubar; + +static char* cutfname(int which = 0) { + static char name[2][1024]; + static char beenhere = 0; + + if (!beenhere) { + beenhere = 1; + fluid_prefs.getUserdataPath(name[0], sizeof(name[0])); + strlcat(name[0], "cut_buffer", sizeof(name[0])); + fluid_prefs.getUserdataPath(name[1], sizeof(name[1])); + strlcat(name[1], "dup_buffer", sizeof(name[1])); + } + + return name[which]; +} + +void save_cb(Fl_Widget *, void *v) { + const char *c = filename; + if (v || !c || !*c) { + fl_file_chooser_ok_label("Save"); + c=fl_file_chooser("Save To:", "FLUID Files (*.f[ld])", c); + fl_file_chooser_ok_label(NULL); + if (!c) return; + + if (!access(c, 0)) { + const char *basename; + if ((basename = strrchr(c, '/')) != NULL) + basename ++; +#if defined(WIN32) || defined(__EMX__) + if ((basename = strrchr(c, '\\')) != NULL) + basename ++; +#endif // WIN32 || __EMX__ + else + basename = c; + + if (fl_choice("The file \"%s\" already exists.\n" + "Do you want to replace it?", "Cancel", + "Replace", NULL, basename) == 0) return; + } + + if (v != (void *)2) set_filename(c); + } + if (!write_file(c)) { + fl_alert("Error writing %s: %s", c, strerror(errno)); + return; + } + + if (v != (void *)2) { + set_modflag(0); + undo_save = undo_current; + } +} + +void save_template_cb(Fl_Widget *, void *) { + // Setup the template panel... + if (!template_panel) make_template_panel(); + + template_clear(); + template_browser->add("New Template"); + template_load(); + + template_name->show(); + template_name->value(""); + + template_instance->hide(); + + template_delete->show(); + template_delete->deactivate(); + + template_submit->label("Save"); + template_submit->deactivate(); + + template_panel->label("Save Template"); + + // Show the panel and wait for the user to do something... + template_panel->show(); + while (template_panel->shown()) Fl::wait(); + + // Get the template name, return if it is empty... + const char *c = template_name->value(); + if (!c || !*c) return; + + // Convert template name to filename_with_underscores + char safename[1024], *safeptr; + strlcpy(safename, c, sizeof(safename)); + for (safeptr = safename; *safeptr; safeptr ++) { + if (isspace(*safeptr)) *safeptr = '_'; + } + + // Find the templates directory... + char filename[1024]; + fluid_prefs.getUserdataPath(filename, sizeof(filename)); + + strlcat(filename, "templates", sizeof(filename)); +#if defined(WIN32) && !defined(__CYGWIN__) + if (access(filename, 0)) mkdir(filename); +#else + if (access(filename, 0)) mkdir(filename, 0777); +#endif // WIN32 && !__CYGWIN__ + + strlcat(filename, "/", sizeof(filename)); + strlcat(filename, safename, sizeof(filename)); + + char *ext = filename + strlen(filename); + if (ext >= (filename + sizeof(filename) - 5)) { + fl_alert("The template name \"%s\" is too long!", c); + return; + } + + // Save the .fl file... + strcpy(ext, ".fl"); + + if (!access(filename, 0)) { + if (fl_choice("The template \"%s\" already exists.\n" + "Do you want to replace it?", "Cancel", + "Replace", NULL, c) == 0) return; + } + + if (!write_file(filename)) { + fl_alert("Error writing %s: %s", filename, strerror(errno)); + return; + } + +#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) + // Get the screenshot, if any... + Fl_Type *t; + + for (t = Fl_Type::first; t; t = t->next) { + // Find the first window... + if (t->is_window()) break; + } + + if (!t) return; + + // Grab a screenshot... + Fl_Window_Type *wt = (Fl_Window_Type *)t; + uchar *pixels; + int w, h; + + if ((pixels = wt->read_image(w, h)) == NULL) return; + + // Save to a PNG file... + strcpy(ext, ".png"); + + FILE *fp; + + if ((fp = fopen(filename, "wb")) == NULL) { + delete[] pixels; + fl_alert("Error writing %s: %s", filename, strerror(errno)); + return; + } + + png_structp pptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); + png_infop iptr = png_create_info_struct(pptr); + png_bytep ptr = (png_bytep)pixels; + + png_init_io(pptr, fp); + png_set_IHDR(pptr, iptr, w, h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + png_set_sRGB(pptr, iptr, PNG_sRGB_INTENT_PERCEPTUAL); + + png_write_info(pptr, iptr); + + for (int i = h; i > 0; i --, ptr += w * 3) { + png_write_row(pptr, ptr); + } + + png_write_end(pptr, iptr); + png_destroy_write_struct(&pptr, &iptr); + + fclose(fp); + +# if 0 // The original PPM output code... + strcpy(ext, ".ppm"); + fp = fopen(filename, "wb"); + fprintf(fp, "P6\n%d %d 255\n", w, h); + fwrite(pixels, w * h, 3, fp); + fclose(fp); +# endif // 0 + + delete[] pixels; +#endif // HAVE_LIBPNG && HAVE_LIBZ +} + +void revert_cb(Fl_Widget *,void *) { + if (modflag) { + if (!fl_choice("This user interface has been changed. Really revert?", + "Cancel", "Revert", NULL)) return; + } + undo_suspend(); + if (!read_file(filename, 0)) { + undo_resume(); + fl_message("Can't read %s: %s", filename, strerror(errno)); + return; + } + undo_resume(); + set_modflag(0); + undo_clear(); +} + +void exit_cb(Fl_Widget *,void *) { + if (modflag) + switch (fl_choice("Do you want to save changes to this user\n" + "interface before exiting?", "Cancel", + "Save", "Don't Save")) + { + case 0 : /* Cancel */ + return; + case 1 : /* Save */ + save_cb(NULL, NULL); + if (modflag) return; // Didn't save! + } + + save_position(main_window,"main_window_pos"); + + if (widgetbin_panel) { + save_position(widgetbin_panel,"widgetbin_pos"); + delete widgetbin_panel; + } + if (sourceview_panel) { + Fl_Preferences svp(fluid_prefs, "sourceview"); + svp.set("autorefresh", sv_autorefresh->value()); + svp.set("autoposition", sv_autoposition->value()); + svp.set("tab", sv_tab->find(sv_tab->value())); + save_position(sourceview_panel,"sourceview_pos"); + delete sourceview_panel; + } + if (about_panel) + delete about_panel; + if (help_dialog) + delete help_dialog; + + undo_clear(); + + exit(0); +} + +#ifdef __APPLE__ +# include <FL/x.H> + +void +apple_open_cb(const char *c) { + if (modflag) { + switch (fl_choice("Do you want to save changes to this user\n" + "interface before opening another one?", "Don't Save", + "Save", "Cancel")) + { + case 0 : /* Cancel */ + return; + case 1 : /* Save */ + save_cb(NULL, NULL); + if (modflag) return; // Didn't save! + } + } + const char *oldfilename; + oldfilename = filename; + filename = NULL; + set_filename(c); + undo_suspend(); + if (!read_file(c, 0)) { + undo_resume(); + fl_message("Can't read %s: %s", c, strerror(errno)); + free((void *)filename); + filename = oldfilename; + if (main_window) main_window->label(filename); + return; + } + + // Loaded a file; free the old filename... + set_modflag(0); + undo_resume(); + undo_clear(); + if (oldfilename) free((void *)oldfilename); +} +#endif // __APPLE__ + +void open_cb(Fl_Widget *, void *v) { + if (!v && modflag) { + switch (fl_choice("Do you want to save changes to this user\n" + "interface before opening another one?", "Cancel", + "Save", "Don't Save")) + { + case 0 : /* Cancel */ + return; + case 1 : /* Save */ + save_cb(NULL, NULL); + if (modflag) return; // Didn't save! + } + } + const char *c; + const char *oldfilename; + fl_file_chooser_ok_label("Open"); + c = fl_file_chooser("Open:", "FLUID Files (*.f[ld])", filename); + fl_file_chooser_ok_label(NULL); + if (!c) return; + oldfilename = filename; + filename = NULL; + set_filename(c); + if (v != 0) undo_checkpoint(); + undo_suspend(); + if (!read_file(c, v!=0)) { + undo_resume(); + fl_message("Can't read %s: %s", c, strerror(errno)); + free((void *)filename); + filename = oldfilename; + if (main_window) set_modflag(modflag); + return; + } + undo_resume(); + if (v) { + // Inserting a file; restore the original filename... + free((void *)filename); + filename = oldfilename; + set_modflag(1); + } else { + // Loaded a file; free the old filename... + set_modflag(0); + undo_clear(); + if (oldfilename) free((void *)oldfilename); + } +} + +void open_history_cb(Fl_Widget *, void *v) { + if (modflag) { + switch (fl_choice("Do you want to save changes to this user\n" + "interface before opening another one?", "Cancel", + "Save", "Don't Save")) + { + case 0 : /* Cancel */ + return; + case 1 : /* Save */ + save_cb(NULL, NULL); + if (modflag) return; // Didn't save! + } + } + const char *oldfilename = filename; + filename = NULL; + set_filename((char *)v); + undo_suspend(); + if (!read_file(filename, 0)) { + undo_resume(); + undo_clear(); + fl_message("Can't read %s: %s", filename, strerror(errno)); + free((void *)filename); + filename = oldfilename; + if (main_window) main_window->label(filename); + return; + } + set_modflag(0); + undo_resume(); + undo_clear(); + if (oldfilename) free((void *)oldfilename); +} + +void new_cb(Fl_Widget *, void *v) { + // Check if the current file has been modified... + if (!v && modflag) { + // Yes, ask the user what to do... + switch (fl_choice("Do you want to save changes to this user\n" + "interface before creating a new one?", "Cancel", + "Save", "Don't Save")) + { + case 0 : /* Cancel */ + return; + case 1 : /* Save */ + save_cb(NULL, NULL); + if (modflag) return; // Didn't save! + } + } + + // Setup the template panel... + if (!template_panel) make_template_panel(); + + template_clear(); + template_browser->add("Blank"); + template_load(); + + template_name->hide(); + template_name->value(""); + + template_instance->show(); + template_instance->deactivate(); + template_instance->value(""); + + template_delete->hide(); + + template_submit->label("New"); + template_submit->deactivate(); + + template_panel->label("New"); + + // Show the panel and wait for the user to do something... + template_panel->show(); + while (template_panel->shown()) Fl::wait(); + + // See if the user chose anything... + int item = template_browser->value(); + if (item < 1) return; + + // Clear the current data... + delete_all(); + set_filename(NULL); + + // Load the template, if any... + const char *tname = (const char *)template_browser->data(item); + + if (tname) { + // Grab the instance name... + const char *iname = template_instance->value(); + + if (iname && *iname) { + // Copy the template to a temp file, then read it in... + char line[1024], *ptr, *next; + FILE *infile, *outfile; + + if ((infile = fopen(tname, "r")) == NULL) { + fl_alert("Error reading template file \"%s\":\n%s", tname, + strerror(errno)); + set_modflag(0); + undo_clear(); + return; + } + + if ((outfile = fopen(cutfname(1), "w")) == NULL) { + fl_alert("Error writing buffer file \"%s\":\n%s", cutfname(1), + strerror(errno)); + fclose(infile); + set_modflag(0); + undo_clear(); + return; + } + + while (fgets(line, sizeof(line), infile)) { + // Replace @INSTANCE@ with the instance name... + for (ptr = line; (next = strstr(ptr, "@INSTANCE@")) != NULL; ptr = next + 10) { + fwrite(ptr, next - ptr, 1, outfile); + fputs(iname, outfile); + } + + fputs(ptr, outfile); + } + + fclose(infile); + fclose(outfile); + + undo_suspend(); + read_file(cutfname(1), 0); + unlink(cutfname(1)); + undo_resume(); + } else { + // No instance name, so read the template without replacements... + undo_suspend(); + read_file(tname, 0); + undo_resume(); + } + } + + set_modflag(0); + undo_clear(); +} + +int compile_only = 0; +int compile_strings = 0; +int header_file_set = 0; +int code_file_set = 0; +const char* header_file_name = ".h"; +const char* code_file_name = ".cxx"; +int i18n_type = 0; +const char* i18n_include = ""; +const char* i18n_function = ""; +const char* i18n_file = ""; +const char* i18n_set = ""; +char i18n_program[1024] = ""; + +void write_cb(Fl_Widget *, void *) { + if (!filename) { + save_cb(0,0); + if (!filename) return; + } + char cname[1024]; + char hname[1024]; + strlcpy(i18n_program, fl_filename_name(filename), sizeof(i18n_program)); + fl_filename_setext(i18n_program, sizeof(i18n_program), ""); + if (*code_file_name == '.' && strchr(code_file_name, '/') == NULL) { + strlcpy(cname, fl_filename_name(filename), sizeof(cname)); + fl_filename_setext(cname, sizeof(cname), code_file_name); + } else { + strlcpy(cname, code_file_name, sizeof(hname)); + } + if (*header_file_name == '.' && strchr(header_file_name, '/') == NULL) { + strlcpy(hname, fl_filename_name(filename), sizeof(hname)); + fl_filename_setext(hname, sizeof(hname), header_file_name); + } else { + strlcpy(hname, header_file_name, sizeof(hname)); + } + if (!compile_only) goto_source_dir(); + int x = write_code(cname,hname); + if (!compile_only) leave_source_dir(); + strlcat(cname, " and ", sizeof(cname)); + strlcat(cname, hname, sizeof(cname)); + if (compile_only) { + if (!x) {fprintf(stderr,"%s : %s\n",cname,strerror(errno)); exit(1);} + } else { + if (!x) { + fl_message("Can't write %s: %s", cname, strerror(errno)); + } else if (completion_button->value()) { + fl_message("Wrote %s", cname); + } + } +} + +void write_strings_cb(Fl_Widget *, void *) { + static const char *exts[] = { ".txt", ".po", ".msg" }; + if (!filename) { + save_cb(0,0); + if (!filename) return; + } + char sname[1024]; + strlcpy(sname, fl_filename_name(filename), sizeof(sname)); + fl_filename_setext(sname, sizeof(sname), exts[i18n_type]); + if (!compile_only) goto_source_dir(); + int x = write_strings(sname); + if (!compile_only) leave_source_dir(); + if (compile_only) { + if (x) {fprintf(stderr,"%s : %s\n",sname,strerror(errno)); exit(1);} + } else { + if (x) { + fl_message("Can't write %s: %s", sname, strerror(errno)); + } else if (completion_button->value()) { + fl_message("Wrote %s", sname); + } + } +} + +void openwidget_cb(Fl_Widget *, void *) { + if (!Fl_Type::current) { + fl_message("Please select a widget"); + return; + } + Fl_Type::current->open(); +} + +void toggle_overlays(Fl_Widget *,void *); + +void select_all_cb(Fl_Widget *,void *); +void select_none_cb(Fl_Widget *,void *); + +void group_cb(Fl_Widget *, void *); + +void ungroup_cb(Fl_Widget *, void *); + +extern int pasteoffset; +static int ipasteoffset; + +void copy_cb(Fl_Widget*, void*) { + if (!Fl_Type::current) { + fl_beep(); + return; + } + ipasteoffset = 10; + if (!write_file(cutfname(),1)) { + fl_message("Can't write %s: %s", cutfname(), strerror(errno)); + return; + } +} + +extern void select_only(Fl_Type *); +void cut_cb(Fl_Widget *, void *) { + if (!Fl_Type::current) { + fl_beep(); + return; + } + if (!write_file(cutfname(),1)) { + fl_message("Can't write %s: %s", cutfname(), strerror(errno)); + return; + } + undo_checkpoint(); + set_modflag(1); + ipasteoffset = 0; + Fl_Type *p = Fl_Type::current->parent; + while (p && p->selected) p = p->parent; + delete_all(1); + if (p) select_only(p); +} + +void delete_cb(Fl_Widget *, void *) { + if (!Fl_Type::current) { + fl_beep(); + return; + } + undo_checkpoint(); + set_modflag(1); + ipasteoffset = 0; + Fl_Type *p = Fl_Type::current->parent; + while (p && p->selected) p = p->parent; + delete_all(1); + if (p) select_only(p); +} + +extern int force_parent; + +void paste_cb(Fl_Widget*, void*) { + //if (ipasteoffset) force_parent = 1; + pasteoffset = ipasteoffset; + if (gridx>1) pasteoffset = ((pasteoffset-1)/gridx+1)*gridx; + if (gridy>1) pasteoffset = ((pasteoffset-1)/gridy+1)*gridy; + undo_checkpoint(); + undo_suspend(); + if (!read_file(cutfname(), 1)) { + fl_message("Can't read %s: %s", cutfname(), strerror(errno)); + } + undo_resume(); + pasteoffset = 0; + ipasteoffset += 10; + force_parent = 0; +} + +// Duplicate the selected widgets... +void duplicate_cb(Fl_Widget*, void*) { + if (!Fl_Type::current) { + fl_beep(); + return; + } + + if (!write_file(cutfname(1),1)) { + fl_message("Can't write %s: %s", cutfname(1), strerror(errno)); + return; + } + + pasteoffset = 0; + force_parent = 1; + + undo_checkpoint(); + undo_suspend(); + if (!read_file(cutfname(1), 1)) { + fl_message("Can't read %s: %s", cutfname(1), strerror(errno)); + } + unlink(cutfname(1)); + undo_resume(); + + force_parent = 0; +} + +void earlier_cb(Fl_Widget*,void*); + +void later_cb(Fl_Widget*,void*); + +Fl_Type *sort(Fl_Type *parent); + +static void sort_cb(Fl_Widget *,void *) { + sort((Fl_Type*)0); +} + +void show_project_cb(Fl_Widget *, void *); +void show_grid_cb(Fl_Widget *, void *); +void show_settings_cb(Fl_Widget *, void *); + +void align_widget_cb(Fl_Widget *, long); +void widget_size_cb(Fl_Widget *, long); + +void about_cb(Fl_Widget *, void *) { + if (!about_panel) make_about_panel(); + about_panel->show(); +} + +void show_help(const char *name) { + const char *docdir; + char helpname[1024]; + + if (!help_dialog) help_dialog = new Fl_Help_Dialog(); + + if ((docdir = getenv("FLTK_DOCDIR")) == NULL) { +#ifdef __EMX__ + // Doesn't make sense to have a hardcoded fallback + static char fltk_docdir[1024]; + + strlcpy(fltk_docdir, __XOS2RedirRoot("/XFree86/lib/X11/fltk/doc"), + sizeof(fltk_docdir)); + + docdir = fltk_docdir; +#else + docdir = FLTK_DOCDIR; +#endif // __EMX__ + } + snprintf(helpname, sizeof(helpname), "%s/%s", docdir, name); + + help_dialog->load(helpname); + help_dialog->show(); +} + +void help_cb(Fl_Widget *, void *) { + show_help("fluid.html"); +} + +void manual_cb(Fl_Widget *, void *) { + show_help("index.html"); +} + + +//////////////////////////////////////////////////////////////// + +#if defined(WIN32) && !defined(__CYGWIN__) +// Draw a shaded box... +static void win_box(int x, int y, int w, int h) { + fl_color(0xc0, 0xc0, 0xc0); + fl_rectf(x, y, w, h); + fl_color(0, 0, 0); + fl_rect(x, y, w, h); + fl_color(0xf0, 0xf0, 0xf0); + fl_rectf(x + 1, y + 1, 4, h - 2); + fl_rectf(x + 1, y + 1, w - 2, 4); + fl_color(0x90, 0x90, 0x90); + fl_rectf(x + w - 5, y + 1, 4, h - 2); + fl_rectf(x + 1, y + h - 5, w - 2, 4); +} + +// Load and show the print dialog... +void print_menu_cb(Fl_Widget *, void *) { + PRINTDLG dialog; // Print dialog + DOCINFO docinfo; // Document info + int first, last; // First and last page + int page; // Current page + int winpage; // Current window page + int num_pages; // Number of pages + Fl_Type *t; // Current widget + int num_windows; // Number of windows + Fl_Window_Type *windows[1000]; // Windows to print + + + // Show print dialog... + for (t = Fl_Type::first, num_pages = 0; t; t = t->next) { + if (t->is_window()) num_pages ++; + } + + memset(&dialog, 0, sizeof(dialog)); + dialog.lStructSize = sizeof(dialog); + dialog.hwndOwner = fl_xid(main_window); + dialog.Flags = PD_ALLPAGES | + PD_RETURNDC; + dialog.nFromPage = 1; + dialog.nToPage = num_pages; + dialog.nMinPage = 1; + dialog.nMaxPage = num_pages; + dialog.nCopies = 1; + + if (!PrintDlg(&dialog)) return; + + // Get the base filename... + const char *basename = strrchr(filename, '/'); + if (basename) basename ++; + else basename = filename; + + // Do the print job... + memset(&docinfo, 0, sizeof(docinfo)); + docinfo.cbSize = sizeof(docinfo); + docinfo.lpszDocName = basename; + + StartDoc(dialog.hDC, &docinfo); + + // Figure out how many pages we'll have to print... + if (dialog.Flags & PD_PAGENUMS) { + // Get from and to page numbers... + first = dialog.nFromPage; + last = dialog.nToPage; + + if (first > last) { + // Swap first/last page + page = first; + first = last; + last = page; + } + } else { + // Print everything... + first = 1; + last = dialog.nMaxPage; + } + + for (t = Fl_Type::first, num_windows = 0, winpage = 0; t; t = t->next) { + if (t->is_window()) { + winpage ++; + windows[num_windows] = (Fl_Window_Type *)t; + num_windows ++; +#if 0 + if (dialog.Flags & PD_ALLPAGES) num_windows ++; + else if ((dialog.Flags & PD_PAGENUMS) && winpage >= first && + winpage <= last) num_windows ++; + else if ((dialog.Flags & PD_SELECTION) && t->selected) num_windows ++; +#endif // 0 + } + } + + num_pages = num_windows; + + // Figure out the page size and margins... + int width, length; // Size of page + int xdpi, ydpi; // Output resolution + char buffer[1024]; + + width = GetDeviceCaps(dialog.hDC, HORZRES); + length = GetDeviceCaps(dialog.hDC, VERTRES); + xdpi = GetDeviceCaps(dialog.hDC, LOGPIXELSX); + ydpi = GetDeviceCaps(dialog.hDC, LOGPIXELSY); + +// fl_message("width=%d, length=%d, xdpi=%d, ydpi=%d, num_windows=%d\n", +// width, length, xdpi, ydpi, num_windows); + + HDC save_dc = fl_gc; + HWND save_win = fl_window; + int fontsize = 14 * ydpi / 72; + + fl_gc = dialog.hDC; + fl_window = (HWND)dialog.hDC; + fl_push_no_clip(); + + // Get the time and date... + time_t curtime = time(NULL); + struct tm *curdate = localtime(&curtime); + char date[1024]; + + strftime(date, sizeof(date), "%c", curdate); + + // Print each of the windows... + for (winpage = 0; winpage < num_windows; winpage ++) { + // Draw header... + StartPage(dialog.hDC); + + fl_font(FL_HELVETICA_BOLD, fontsize); + fl_color(0, 0, 0); + + fl_draw(basename, 0, fontsize); + + fl_draw(date, (width - (int)fl_width(date)) / 2, fontsize); + + sprintf(buffer, "%d/%d", winpage + 1, num_windows); + fl_draw(buffer, width - (int)fl_width(buffer), fontsize); + + // Get window image... + uchar *pixels; // Window image data + int w, h; // Window image dimensions + int ww, hh; // Scaled size + int ulx, uly; // Upper-lefthand corner + Fl_Window *win; // Window widget + BITMAPINFO info; // Bitmap information + + win = (Fl_Window *)(windows[winpage]->o); + pixels = windows[winpage]->read_image(w, h); + + // Figure out the window size, first at 100 PPI and then scaled + // down if that is too big... + ww = w * xdpi / 100; + hh = h * ydpi / 100; + + if (ww > width) { + ww = width; + hh = h * ww * ydpi / xdpi / w; + } + + if (hh > (length - ydpi / 2)) { + hh = length - ydpi / 2; + ww = w * hh / h; + } + + // Position the window in the center... + ulx = (width - ww) / 2; + uly = (length - hh) / 2; + +// fl_message("winpage=%d, ulx=%d, uly=%d, ww=%d, hh=%d", +// winpage, ulx, uly, ww, hh); + + // Draw a simulated window border... + int xborder = 4 * ww / w; + int yborder = 4 * hh / h; + + win_box(ulx - xborder, uly - 5 * yborder, + ww + 2 * xborder, hh + 6 * yborder); + + fl_color(0, 0, 255); + fl_rectf(ulx, uly - 4 * yborder, ww, 4 * yborder); + + fl_font(FL_HELVETICA_BOLD, 2 * yborder); + fl_color(255, 255, 255); + fl_draw(win->label() ? win->label() : "Window", + ulx + xborder, uly - 3 * yborder); + + int x = ulx + ww - 4 * xborder; + + win_box(x, uly - 4 * yborder, 4 * xborder, 4 * yborder); + fl_color(0, 0, 0); + fl_line(x + xborder, uly - yborder, + x + 3 * xborder, uly - 3 * yborder); + fl_line(x + xborder, uly - 3 * yborder, + x + 3 * xborder, uly - yborder); + x -= 4 * xborder; + + if (win->resizable()) { + win_box(x, uly - 4 * yborder, 4 * xborder, 4 * yborder); + fl_color(0, 0, 0); + fl_rect(x + xborder, uly - 3 * yborder, 2 * xborder, 2 * yborder); + x -= 4 * xborder; + } + + if (!win->modal()) { + win_box(x, uly - 4 * yborder, 4 * xborder, 4 * yborder); + fl_color(0, 0, 0); + fl_line(x + xborder, uly - yborder, x + 3 * xborder, uly - yborder); + x -= 4 * xborder; + } + + // Color image... + memset(&info, 0, sizeof(info)); + info.bmiHeader.biSize = sizeof(info); + info.bmiHeader.biWidth = w; + info.bmiHeader.biHeight = 1; + info.bmiHeader.biPlanes = 1; + info.bmiHeader.biBitCount = 24; + info.bmiHeader.biCompression = BI_RGB; + + for (int y = 0; y < h; y ++) { + StretchDIBits(dialog.hDC, ulx, uly + y * hh / h, ww, (hh + h - 1) / h, 0, 0, w, 1, + pixels + y * w * 3, &info, DIB_RGB_COLORS, SRCCOPY); + } + + delete[] pixels; + + // Show the page... + EndPage(dialog.hDC); + } + + // Finish up... + EndDoc(dialog.hDC); + + fl_gc = save_dc; + fl_window = save_win; + fl_pop_clip(); + + // Free the print DC and return... + DeleteDC(dialog.hDC); +} +#else +// Load and show the print dialog... +void print_menu_cb(Fl_Widget *, void *) { + if (!print_panel) make_print_panel(); + + print_load(); + + print_selection->deactivate(); + + for (Fl_Type *t = Fl_Type::first; t; t = t->next) { + if (t->selected && t->is_window()) { + print_selection->activate(); + break; + } + } + + print_all->setonly(); + print_all->do_callback(); + + print_panel->show(); +} + +// Quote a string for PostScript printing +static const char *ps_string(const char *s) { + char *bufptr; + static char buffer[2048]; + + + if (!s) { + buffer[0] = '\0'; + } else { + for (bufptr = buffer; bufptr < (buffer + sizeof(buffer) - 3) && *s;) { + if (*s == '(' || *s == ')' || *s == '\\') *bufptr++ = '\\'; + *bufptr++ = *s++; + } + + *bufptr = '\0'; + } + + return (buffer); +} + +// Actually print... +void print_cb(Fl_Return_Button *, void *) { + FILE *outfile; // Output file or pipe to print command + char command[1024]; // Print command + int copies; // Collated copies + int first, last; // First and last page + int page; // Current page + int winpage; // Current window page + int num_pages; // Number of pages + Fl_Type *t; // Current widget + int num_windows; // Number of windows + Fl_Window_Type *windows[1000]; // Windows to print + + // Show progress, deactivate controls... + print_panel_controls->deactivate(); + print_progress->show(); + + // Figure out how many pages we'll have to print... + if (print_collate_button->value()) copies = (int)print_copies->value(); + else copies = 1; + + if (print_pages->value()) { + // Get from and to page numbers... + if ((first = atoi(print_from->value())) < 1) first = 1; + if ((last = atoi(print_to->value())) < 1) last = 1000; + + if (first > last) { + // Swap first/last page + page = first; + first = last; + last = page; + } + } else { + // Print everything... + first = 1; + last = 1000; + } + + for (t = Fl_Type::first, num_windows = 0, winpage = 0; t; t = t->next) { + if (t->is_window()) { + winpage ++; + windows[num_windows] = (Fl_Window_Type *)t; + + if (print_all->value()) num_windows ++; + else if (print_pages->value() && winpage >= first && + winpage <= last) num_windows ++; + else if (print_selection->value() && t->selected) num_windows ++; + } + } + + num_pages = num_windows * copies; + + print_progress->minimum(0); + print_progress->maximum(num_pages); + print_progress->value(0); + Fl::check(); + + // Get the base filename... + const char *basename = strrchr(filename, '/'); + if (basename) basename ++; + else basename = filename; + + // Open the print stream... + if (print_choice->value()) { + // Pipe the output into the lp command... + const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); + + snprintf(command, sizeof(command), "lp -s -d %s -n %.0f -t '%s' -o media=%s", + printer, print_collate_button->value() ? 1.0 : print_copies->value(), + basename, print_page_size->text(print_page_size->value())); + outfile = popen(command, "w"); + } else { + // Print to file... + fl_file_chooser_ok_label("Print"); + const char *outname = fl_file_chooser("Print To", "PostScript (*.ps)", NULL, 1); + fl_file_chooser_ok_label(NULL); + + if (outname && !access(outname, 0)) { + if (fl_choice("The file \"%s\" already exists.\n" + "Do you want to replace it?", "Cancel", + "Replace", NULL, outname) == 0) outname = NULL; + } + + if (outname) outfile = fopen(outname, "w"); + else outfile = NULL; + } + + if (outfile) { + // Figure out the page size and margins... + int width, length; // Size of page + int left, bottom, // Bottom lefthand corner + right, top; // Top righthand corner + + if (print_page_size->value()) { + // A4 + width = 595; + length = 842; + } else { + // Letter + width = 612; + length = 792; + } + + int output_mode; + for (output_mode = 0; output_mode < 4; output_mode ++) { + if (print_output_mode[output_mode]->value()) break; + } + + if (output_mode & 1) { + // Landscape + left = 36; + bottom = 18; + right = length - 36; + top = width - 18; + } else { + // Portrait + left = 18; + bottom = 36; + right = width - 18; + top = length - 36; + } + + // Get the time and date... + time_t curtime = time(NULL); + struct tm *curdate = localtime(&curtime); + char date[1024]; + + strftime(date, sizeof(date), "%c", curdate); + + // Write the prolog... + fprintf(outfile, + "%%!PS-Adobe-3.0\n" + "%%%%BoundingBox: 18 36 %d %d\n" + "%%%%Pages: %d\n" + "%%%%LanguageLevel: 1\n" + "%%%%DocumentData: Clean7Bit\n" + "%%%%DocumentNeededResources: font Helvetica-Bold\n" + "%%%%Creator: FLUID %.4f\n" + "%%%%CreationDate: %s\n" + "%%%%Title: (%s)\n" + "%%%%EndComments\n" + "%%%%BeginProlog\n" + "%%languagelevel 1 eq {\n" + " /rectfill {\n" + " newpath 4 2 roll moveto dup 0 exch rlineto exch 0 rlineto\n" + " neg 0 exch rlineto closepath fill\n" + " } bind def\n" + " /rectstroke {\n" + " newpath 4 2 roll moveto dup 0 exch rlineto exch 0 rlineto\n" + " neg 0 exch rlineto closepath stroke\n" + " } bind def\n" + "%%} if\n" + "%%%%EndProlog\n" + "%%%%BeginSetup\n" + "%%%%BeginFeature: *PageSize %s\n" + "languagelevel 1 ne {\n" + " <</PageSize[%d %d]/ImagingBBox null>>setpagedevice\n" + "} {\n" + " %s\n" + "} ifelse\n" + "%%%%EndFeature\n" + "%%%%EndSetup\n", + width - 18, length - 36, + num_pages, + FL_VERSION, + date, + basename, + print_page_size->text(print_page_size->value()), + width, length, + print_page_size->value() ? "a4tray" : "lettertray"); + + // Print each of the windows... + char progress[255]; // Progress text + int copy; // Current copy + + for (copy = 0, page = 0; copy < copies; copy ++) { + for (winpage = 0; winpage < num_pages; winpage ++) { + // Start next page... + page ++; + sprintf(progress, "Printing page %d/%d...", page, num_pages); + print_progress->value(page); + print_progress->label(progress); + Fl::check(); + + // Add common page stuff... + fprintf(outfile, + "%%%%Page: %d %d\n" + "gsave\n", + page, page); + + if (output_mode & 1) { + // Landscape... + fprintf(outfile, "%d 0 translate 90 rotate\n", width); + } + + // Draw header... + fprintf(outfile, + "0 setgray\n" + "/Helvetica-Bold findfont 14 scalefont setfont\n" + "%d %d moveto (%s) show\n" + "%.1f %d moveto (%s) dup stringwidth pop -0.5 mul 0 rmoveto show\n" + "%d %d moveto (%d/%d) dup stringwidth pop neg 0 rmoveto show\n", + left, top - 15, ps_string(basename), + 0.5 * (left + right), top - 15, date, + right, top - 15, winpage + 1, num_windows); + + // Get window image... + uchar *pixels; // Window image data + int w, h; // Window image dimensions + float ww, hh; // Scaled size + float border; // Width of 1 pixel + float llx, lly, // Lower-lefthand corner + urx, ury; // Upper-righthand corner + Fl_Window *win; // Window widget + + win = (Fl_Window *)(windows[winpage]->o); + pixels = windows[winpage]->read_image(w, h); + + // Figure out the window size, first at 100 PPI and then scaled + // down if that is too big... + ww = w * 72.0 / 100.0; + hh = h * 72.0 / 100.0; + + if (ww > (right - left)) { + ww = right - left; + hh = h * ww / w; + } + + if (hh > (top - bottom - 36)) { + hh = top - bottom; + ww = w * hh / h; + } + + border = ww / w; + + // Position the window in the center... + llx = 0.5 * (right - left - ww); + lly = 0.5 * (top - bottom - hh); + urx = 0.5 * (right - left + ww); + ury = 0.5 * (top - bottom + hh); + + // Draw a simulated window border... + fprintf(outfile, + "0.75 setgray\n" // Gray background + "newpath %.2f %.2f %.2f 180 90 arcn\n" // Top left + "%.2f %.2f %.2f 90 0 arcn\n" // Top right + "%.2f %.2f %.2f 0 -90 arcn\n" // Bottom right + "%.2f %.2f %.2f -90 -180 arcn\n" // Bottom left + "closepath gsave fill grestore\n" // Fill + "0 setlinewidth 0 setgray stroke\n", // Outline + llx, ury + 12 * border, 4 * border, + urx, ury + 12 * border, 4 * border, + urx, lly, 4 * border, + llx, lly, 4 * border); + + // Title bar... + if (output_mode & 2) { + fputs("0.25 setgray\n", outfile); + } else { + fputs("0.1 0.2 0.6 setrgbcolor\n", outfile); + } + + fprintf(outfile, "%.2f %.2f %.2f %.2f rectfill\n", + llx + 12 * border, ury, + ww - (24 + 16 * (!win->modal() || win->resizable()) + + 16 * (!win->modal() && win->resizable())) * border, + 16 * border); + + if (win->resizable()) { + fprintf(outfile, + "%.2f %.2f %.2f -90 -180 arcn\n" // Bottom left + "0 %.2f rlineto %.2f 0 rlineto 0 -%.2f rlineto closepath fill\n" + "%.2f %.2f %.2f 0 -90 arcn\n" // Bottom right + "-%.2f 0 rlineto 0 %.2f rlineto %.2f 0 rlineto closepath fill\n", + llx, lly, 4 * border, + 12 * border, 16 * border, 16 * border, + urx, lly, 4 * border, + 12 * border, 16 * border, 16 * border); + } + + // Inside outline and button shading... + fprintf(outfile, + "%.2f setlinewidth 0.5 setgray\n" + "%.2f %.2f %.2f %.2f rectstroke\n" + "%.2f %.2f moveto 0 %.2f rlineto\n" + "%.2f %.2f moveto 0 %.2f rlineto\n", + border, + llx - 0.5 * border, lly - 0.5 * border, ww + border, hh + border, + llx + 12 * border, ury, 16 * border, + urx - 12 * border, ury, 16 * border); + + if (!win->modal() || win->resizable()) { + fprintf(outfile, "%.2f %.2f moveto 0 %.2f rlineto\n", + urx - 28 * border, ury, 16 * border); + } + + if (!win->modal() && win->resizable()) { + fprintf(outfile, "%.2f %.2f moveto 0 %.2f rlineto\n", + urx - 44 * border, ury, 16 * border); + } + + fprintf(outfile, "%.2f %.2f moveto %.2f 0 rlineto stroke\n", + llx - 3.5 * border, ury + 0.5 * border, ww + 7 * border); + + // Button icons... + fprintf(outfile, + "%.2f setlinewidth 0 setgray\n" + "%.2f %.2f moveto %.2f -%.2f rlineto %.2f %.2f rlineto\n" + "%.2f %.2f moveto -%.2f -%.2f rlineto 0 %.2f rmoveto %.2f -%.2f rlineto\n", + 2 * border, + llx, ury + 10 * border, 4 * border, 4 * border, 4 * border, 4 * border, + urx, ury + 12 * border, 8 * border, 8 * border, 8 * border, 8 * border, 8 * border); + + float x = urx - 16 * border; + + if (win->resizable()) { + // Maximize button + fprintf(outfile, + "%.2f %.2f moveto -%.2f 0 rlineto 0 -%.2f rlineto " + "%.2f 0 rlineto 0 %.2f rlineto\n", + x, ury + 12 * border, 8 * border, 8 * border, + 8 * border, 8 * border); + + x -= 16 * border; + } + + if (!win->modal()) { + // Minimize button + fprintf(outfile, + "%.2f %.2f moveto -%.2f 0 rlineto\n", + x, ury + 4 * border, 8 * border); + } + + fputs("stroke\n", outfile); + + if (win->label()) { + // Add window title... + fprintf(outfile, + "1 setgray\n" + "/Helvetica-Bold findfont %.2f scalefont setfont\n" + "(%s) %.2f %.2f moveto show\n", + 12 * border, + ps_string(win->label()), llx + 16 * border, ury + 4 * border); + } + + fprintf(outfile, + "gsave\n" + "%.2f %.2f translate %.2f %.2f scale\n", + llx, ury - border, border, border); + + if (output_mode & 2) { + // Grayscale image... + fprintf(outfile, + "/imgdata %d string def\n" + "%d %d 8[1 0 0 -1 0 1] " + "{currentfile imgdata readhexstring pop} image\n", + w, + w, h); + + uchar *ptr = pixels; + int i, count = w * h; + + for (i = 0; i < count; i ++, ptr += 3) { + fprintf(outfile, "%02X", + (31 * ptr[0] + 61 * ptr[1] + 8 * ptr[2]) / 100); + if (!(i % 40)) putc('\n', outfile); + } + } else { + // Color image... + fprintf(outfile, + "/imgdata %d string def\n" + "%d %d 8[1 0 0 -1 0 1] " + "{currentfile imgdata readhexstring pop} false 3 colorimage\n", + w * 3, + w, h); + + uchar *ptr = pixels; + int i, count = w * h; + + for (i = 0; i < count; i ++, ptr += 3) { + fprintf(outfile, "%02X%02X%02X", ptr[0], ptr[1], ptr[2]); + if (!(i % 13)) putc('\n', outfile); + } + } + + fputs("\ngrestore\n", outfile); + + delete[] pixels; + + // Show the page... + fputs("grestore showpage\n", outfile); + } + } + + // Finish up... + fputs("%%EOF\n", outfile); + + if (print_choice->value()) pclose(outfile); + else fclose(outfile); + } else { + // Unable to print... + fl_alert("Error printing: %s", strerror(errno)); + } + + // Hide progress, activate controls, hide print panel... + print_panel_controls->activate(); + print_progress->hide(); + print_panel->hide(); +} +#endif // WIN32 && !__CYGWIN__ + +//////////////////////////////////////////////////////////////// + +extern Fl_Menu_Item New_Menu[]; + +void toggle_widgetbin_cb(Fl_Widget *, void *); +void toggle_sourceview_cb(Fl_Double_Window *, void *); + +Fl_Menu_Item Main_Menu[] = { +{"&File",0,0,0,FL_SUBMENU}, + {"&New...", FL_CTRL+'n', new_cb, 0}, + {"&Open...", FL_CTRL+'o', open_cb, 0}, + {"&Insert...", FL_CTRL+'i', open_cb, (void*)1, FL_MENU_DIVIDER}, +#define SAVE_ITEM 4 + {"&Save", FL_CTRL+'s', save_cb, 0}, + {"Save &As...", FL_CTRL+FL_SHIFT+'s', save_cb, (void*)1}, + {"Sa&ve A Copy...", 0, save_cb, (void*)2}, + {"Save &Template...", 0, save_template_cb}, + {"&Revert...", 0, revert_cb, 0, FL_MENU_DIVIDER}, + {"&Print...", FL_CTRL+'p', print_menu_cb}, + {"Write &Code...", FL_CTRL+FL_SHIFT+'c', write_cb, 0}, + {"&Write Strings...", FL_CTRL+FL_SHIFT+'w', write_strings_cb, 0, FL_MENU_DIVIDER}, +#define HISTORY_ITEM 12 + {relative_history[0], FL_CTRL+'0', open_history_cb, absolute_history[0]}, + {relative_history[1], FL_CTRL+'1', open_history_cb, absolute_history[1]}, + {relative_history[2], FL_CTRL+'2', open_history_cb, absolute_history[2]}, + {relative_history[3], FL_CTRL+'3', open_history_cb, absolute_history[3]}, + {relative_history[4], FL_CTRL+'4', open_history_cb, absolute_history[4]}, + {relative_history[5], FL_CTRL+'5', open_history_cb, absolute_history[5]}, + {relative_history[6], FL_CTRL+'6', open_history_cb, absolute_history[6]}, + {relative_history[7], FL_CTRL+'7', open_history_cb, absolute_history[7]}, + {relative_history[8], FL_CTRL+'8', open_history_cb, absolute_history[8]}, + {relative_history[9], FL_CTRL+'9', open_history_cb, absolute_history[9], FL_MENU_DIVIDER}, + {"&Quit", FL_CTRL+'q', exit_cb}, + {0}, +{"&Edit",0,0,0,FL_SUBMENU}, + {"&Undo", FL_CTRL+'z', undo_cb}, + {"&Redo", FL_CTRL+FL_SHIFT+'z', redo_cb, 0, FL_MENU_DIVIDER}, + {"C&ut", FL_CTRL+'x', cut_cb}, + {"&Copy", FL_CTRL+'c', copy_cb}, + {"&Paste", FL_CTRL+'v', paste_cb}, + {"Dup&licate", FL_CTRL+'u', duplicate_cb}, + {"&Delete", FL_Delete, delete_cb, 0, FL_MENU_DIVIDER}, + {"Select &All", FL_CTRL+'a', select_all_cb}, + {"Select &None", FL_CTRL+FL_SHIFT+'a', select_none_cb, 0, FL_MENU_DIVIDER}, + {"Pr&operties...", FL_F+1, openwidget_cb}, + {"&Sort",0,sort_cb}, + {"&Earlier", FL_F+2, earlier_cb}, + {"&Later", FL_F+3, later_cb}, + {"&Group", FL_F+7, group_cb}, + {"Ung&roup", FL_F+8, ungroup_cb,0, FL_MENU_DIVIDER}, + {"Hide O&verlays",FL_CTRL+FL_SHIFT+'o',toggle_overlays}, +#define WIDGETBIN_ITEM 41 + {"Show Widget &Bin...",FL_ALT+'b',toggle_widgetbin_cb}, +#define SOURCEVIEW_ITEM 42 + {"Show Source Code...",FL_ALT+FL_SHIFT+'s', (Fl_Callback*)toggle_sourceview_cb, 0, FL_MENU_DIVIDER}, + {"Pro&ject Settings...",FL_ALT+'p',show_project_cb}, + {"GU&I Settings...",FL_ALT+FL_SHIFT+'p',show_settings_cb}, + {0}, +{"&New", 0, 0, (void *)New_Menu, FL_SUBMENU_POINTER}, +{"&Layout",0,0,0,FL_SUBMENU}, + {"&Align",0,0,0,FL_SUBMENU}, + {"&Left",0,(Fl_Callback *)align_widget_cb,(void*)10}, + {"&Center",0,(Fl_Callback *)align_widget_cb,(void*)11}, + {"&Right",0,(Fl_Callback *)align_widget_cb,(void*)12}, + {"&Top",0,(Fl_Callback *)align_widget_cb,(void*)13}, + {"&Middle",0,(Fl_Callback *)align_widget_cb,(void*)14}, + {"&Bottom",0,(Fl_Callback *)align_widget_cb,(void*)15}, + {0}, + {"&Space Evenly",0,0,0,FL_SUBMENU}, + {"&Across",0,(Fl_Callback *)align_widget_cb,(void*)20}, + {"&Down",0,(Fl_Callback *)align_widget_cb,(void*)21}, + {0}, + {"&Make Same Size",0,0,0,FL_SUBMENU}, + {"&Width",0,(Fl_Callback *)align_widget_cb,(void*)30}, + {"&Height",0,(Fl_Callback *)align_widget_cb,(void*)31}, + {"&Both",0,(Fl_Callback *)align_widget_cb,(void*)32}, + {0}, + {"&Center In Group",0,0,0,FL_SUBMENU}, + {"&Horizontal",0,(Fl_Callback *)align_widget_cb,(void*)40}, + {"&Vertical",0,(Fl_Callback *)align_widget_cb,(void*)41}, + {0}, + {"Set &Widget Size",0,0,0,FL_SUBMENU|FL_MENU_DIVIDER}, + {"&Tiny",FL_ALT+'1',(Fl_Callback *)widget_size_cb,(void*)8,0,FL_NORMAL_LABEL,FL_HELVETICA,8}, + {"&Small",FL_ALT+'2',(Fl_Callback *)widget_size_cb,(void*)11,0,FL_NORMAL_LABEL,FL_HELVETICA,11}, + {"&Normal",FL_ALT+'3',(Fl_Callback *)widget_size_cb,(void*)14,0,FL_NORMAL_LABEL,FL_HELVETICA,14}, + {"&Medium",FL_ALT+'4',(Fl_Callback *)widget_size_cb,(void*)18,0,FL_NORMAL_LABEL,FL_HELVETICA,18}, + {"&Large",FL_ALT+'5',(Fl_Callback *)widget_size_cb,(void*)24,0,FL_NORMAL_LABEL,FL_HELVETICA,24}, + {"&Huge",FL_ALT+'6',(Fl_Callback *)widget_size_cb,(void*)32,0,FL_NORMAL_LABEL,FL_HELVETICA,32}, + {0}, + {"&Grid and Size Settings...",FL_CTRL+'g',show_grid_cb}, + {0}, +{"&Shell",0,0,0,FL_SUBMENU}, + {"Execute &Command...",FL_ALT+'x',(Fl_Callback *)show_shell_window}, + {"Execute &Again...",FL_ALT+'g',(Fl_Callback *)do_shell_command}, + {0}, +{"&Help",0,0,0,FL_SUBMENU}, + {"&About FLUID...",0,about_cb}, + {"&On FLUID...",0,help_cb}, + {"&Manual...",0,manual_cb}, + {0}, +{0}}; + +#define BROWSERWIDTH 300 +#define BROWSERHEIGHT 500 +#define WINWIDTH 300 +#define MENUHEIGHT 25 +#define WINHEIGHT (BROWSERHEIGHT+MENUHEIGHT) + +extern void fill_in_New_Menu(); + +void scheme_cb(Fl_Choice *, void *) { + if (compile_only) + return; + + switch (scheme_choice->value()) { + case 0 : // Default + Fl::scheme(NULL); + break; + case 1 : // None + Fl::scheme("none"); + break; + case 2 : // Plastic + Fl::scheme("plastic"); + break; + } + + fluid_prefs.set("scheme", scheme_choice->value()); +} + +void toggle_widgetbin_cb(Fl_Widget *, void *) { + if (!widgetbin_panel) { + make_widgetbin(); + widgetbin_panel->callback(toggle_widgetbin_cb); + if (!position_window(widgetbin_panel,"widgetbin_pos", 1, 320, 30)) return; + } + + if (widgetbin_panel->visible()) { + widgetbin_panel->hide(); + Main_Menu[WIDGETBIN_ITEM].label("Show Widget &Bin..."); + } else { + widgetbin_panel->show(); + Main_Menu[WIDGETBIN_ITEM].label("Hide Widget &Bin"); + } +} + + +void toggle_sourceview_cb(Fl_Double_Window *, void *) { + if (!sourceview_panel) { + make_sourceview(); + sourceview_panel->callback((Fl_Callback*)toggle_sourceview_cb); + Fl_Preferences svp(fluid_prefs, "sourceview"); + int autorefresh; + svp.get("autorefresh", autorefresh, 1); + sv_autorefresh->value(autorefresh); + int autoposition; + svp.get("autoposition", autoposition, 1); + sv_autoposition->value(autoposition); + int tab; + svp.get("tab", tab, 0); + if (tab>=0 && tab<sv_tab->children()) sv_tab->value(sv_tab->child(tab)); + if (!position_window(sourceview_panel,"sourceview_pos", 0, 320, 120, 550, 500)) return; + } + + if (sourceview_panel->visible()) { + sourceview_panel->hide(); + Main_Menu[SOURCEVIEW_ITEM].label("Show Source Code..."); + } else { + sourceview_panel->show(); + Main_Menu[SOURCEVIEW_ITEM].label("Hide Source Code..."); + update_sourceview_cb(0,0); + } +} + +void toggle_sourceview_b_cb(Fl_Button*, void *) { + toggle_sourceview_cb(0,0); +} + +void make_main_window() { + fluid_prefs.get("snap", snap, 1); + fluid_prefs.get("gridx", gridx, 5); + fluid_prefs.get("gridy", gridy, 5); + fluid_prefs.get("show_guides", show_guides, 0); + fluid_prefs.get("widget_size", Fl_Widget_Type::default_size, 14); + + load_history(); + + make_layout_window(); + make_settings_window(); + make_shell_window(); + + if (!main_window) { + Fl_Widget *o; + main_window = new Fl_Double_Window(WINWIDTH,WINHEIGHT,"fluid"); + main_window->box(FL_NO_BOX); + o = make_widget_browser(0,MENUHEIGHT,BROWSERWIDTH,BROWSERHEIGHT); + o->box(FL_FLAT_BOX); + o->tooltip("Double-click to view or change an item."); + main_window->resizable(o); + main_menubar = new Fl_Menu_Bar(0,0,BROWSERWIDTH,MENUHEIGHT); + main_menubar->menu(Main_Menu); + main_menubar->global(); + fill_in_New_Menu(); + main_window->end(); + } +} + +// Load file history from preferences... +void load_history() { + int i; // Looping var + int max_files; + + + fluid_prefs.get("recent_files", max_files, 5); + if (max_files > 10) max_files = 10; + + for (i = 0; i < max_files; i ++) { + fluid_prefs.get( Fl_Preferences::Name("file%d", i), absolute_history[i], "", sizeof(absolute_history[i])); + if (absolute_history[i][0]) { + // Make a relative version of the filename for the menu... + fl_filename_relative(relative_history[i], sizeof(relative_history[i]), + absolute_history[i]); + + if (i == 9) Main_Menu[i + HISTORY_ITEM].flags = FL_MENU_DIVIDER; + else Main_Menu[i + HISTORY_ITEM].flags = 0; + } else break; + } + + for (; i < 10; i ++) { + if (i) Main_Menu[i + HISTORY_ITEM - 1].flags |= FL_MENU_DIVIDER; + Main_Menu[i + HISTORY_ITEM].hide(); + } +} + +// Update file history from preferences... +void update_history(const char *flname) { + int i; // Looping var + char absolute[1024]; + int max_files; + + + fluid_prefs.get("recent_files", max_files, 5); + if (max_files > 10) max_files = 10; + + fl_filename_absolute(absolute, sizeof(absolute), flname); + + for (i = 0; i < max_files; i ++) +#if defined(WIN32) || defined(__APPLE__) + if (!strcasecmp(absolute, absolute_history[i])) break; +#else + if (!strcmp(absolute, absolute_history[i])) break; +#endif // WIN32 || __APPLE__ + + if (i == 0) return; + + if (i >= max_files) i = max_files - 1; + + // Move the other flnames down in the list... + memmove(absolute_history + 1, absolute_history, + i * sizeof(absolute_history[0])); + memmove(relative_history + 1, relative_history, + i * sizeof(relative_history[0])); + + // Put the new file at the top... + strlcpy(absolute_history[0], absolute, sizeof(absolute_history[0])); + + fl_filename_relative(relative_history[0], sizeof(relative_history[0]), + absolute_history[0]); + + // Update the menu items as needed... + for (i = 0; i < max_files; i ++) { + fluid_prefs.set( Fl_Preferences::Name("file%d", i), absolute_history[i]); + if (absolute_history[i][0]) { + if (i == 9) Main_Menu[i + HISTORY_ITEM].flags = FL_MENU_DIVIDER; + else Main_Menu[i + HISTORY_ITEM].flags = 0; + } else break; + } + + for (; i < 10; i ++) { + fluid_prefs.set( Fl_Preferences::Name("file%d", i), ""); + if (i) Main_Menu[i + HISTORY_ITEM - 1].flags |= FL_MENU_DIVIDER; + Main_Menu[i + HISTORY_ITEM].hide(); + } +} + +// Shell command support... +#if (!defined(WIN32) || defined(__CYGWIN__)) && !defined(__MWERKS__) +// Support the full piped shell command... +static FILE *shell_pipe = 0; + +void +shell_pipe_cb(int, void*) { + char line[1024]; // Line from command output... + + if (fgets(line, sizeof(line), shell_pipe) != NULL) { + // Add the line to the output list... + shell_run_buffer->append(line); + } else { + // End of file; tell the parent... + Fl::remove_fd(fileno(shell_pipe)); + + pclose(shell_pipe); + shell_pipe = NULL; + shell_run_buffer->append("... END SHELL COMMAND ...\n"); + } + + shell_run_display->scroll(shell_run_display->count_lines(0, + shell_run_buffer->length(), 1), 0); +} + +void +do_shell_command(Fl_Return_Button*, void*) { + const char *command; // Command to run + + + shell_window->hide(); + + if (shell_pipe) { + fl_alert("Previous shell command still running!"); + return; + } + + if ((command = shell_command_input->value()) == NULL || !*command) { + fl_alert("No shell command entered!"); + return; + } + + if (shell_savefl_button->value()) { + save_cb(0, 0); + } + + if (shell_writecode_button->value()) { + compile_only = 1; + write_cb(0, 0); + compile_only = 0; + } + + if (shell_writemsgs_button->value()) { + compile_only = 1; + write_strings_cb(0, 0); + compile_only = 0; + } + + // Show the output window and clear things... + shell_run_buffer->text(""); + shell_run_buffer->append(command); + shell_run_buffer->append("\n"); + shell_run_window->label("Shell Command Running..."); + + if ((shell_pipe = popen((char *)command, "r")) == NULL) { + fl_alert("Unable to run shell command: %s", strerror(errno)); + return; + } + + shell_run_button->deactivate(); + shell_run_window->hotspot(shell_run_display); + shell_run_window->show(); + + Fl::add_fd(fileno(shell_pipe), shell_pipe_cb); + + while (shell_pipe) Fl::wait(); + + shell_run_button->activate(); + shell_run_window->label("Shell Command Complete"); + fl_beep(); + + while (shell_run_window->shown()) Fl::wait(); +} +#else +// Just do basic shell command stuff, no status window... +void +do_shell_command(Fl_Return_Button*, void*) { + const char *command; // Command to run + int status; // Status from command... + + + shell_window->hide(); + + if ((command = shell_command_input->value()) == NULL || !*command) { + fl_alert("No shell command entered!"); + return; + } + + if (shell_savefl_button->value()) { + save_cb(0, 0); + } + + if (shell_writecode_button->value()) { + compile_only = 1; + write_cb(0, 0); + compile_only = 0; + } + + if (shell_writemsgs_button->value()) { + compile_only = 1; + write_strings_cb(0, 0); + compile_only = 0; + } + + if ((status = system(command)) != 0) { + fl_alert("Shell command returned status %d!", status); + } else if (completion_button->value()) { + fl_message("Shell command completed successfully!"); + } +} +#endif // (!WIN32 || __CYGWIN__) && !__MWERKS__ + + +void +show_shell_window() { + shell_window->hotspot(shell_command_input); + shell_window->show(); +} + +void set_filename(const char *c) { + if (filename) free((void *)filename); + filename = c ? strdup(c) : NULL; + + if (filename) update_history(filename); + + set_modflag(modflag); +} + +// +// The Source View system offers an immediate preview of the code +// files that will be generated by FLUID. It also marks the code +// generated for the last selected item in the header and the source +// file. +// +// Can we patent this? ;-) - Matt, mm@matthiasm.com +// + +// +// Update the header and source code highlighting depending on the +// currently selected object +// +void update_sourceview_position() +{ + if (!sourceview_panel || !sourceview_panel->visible()) + return; + if (sv_autoposition->value()==0) + return; + if (sourceview_panel && sourceview_panel->visible() && Fl_Type::current) { + int pos0, pos1; + if (sv_source->visible_r()) { + pos0 = Fl_Type::current->code_line; + pos1 = Fl_Type::current->code_line_end; + if (pos0>=0) { + if (pos1<pos0) + pos1 = pos0; + sv_source->buffer()->highlight(pos0, pos1); + int line = sv_source->buffer()->count_lines(0, pos0); + sv_source->scroll(line, 0); + } + } + if (sv_header->visible_r()) { + pos0 = Fl_Type::current->header_line; + pos1 = Fl_Type::current->header_line_end; + if (pos0>=0) { + if (pos1<pos0) + pos1 = pos0; + sv_header->buffer()->highlight(pos0, pos1); + int line = sv_header->buffer()->count_lines(0, pos0); + sv_header->scroll(line, 0); + } + } + } +} + +void update_sourceview_position_cb(Fl_Tabs*, void*) +{ + update_sourceview_position(); +} + +static char *sv_source_filename = 0; +static char *sv_header_filename = 0; + +// +// Generate a header and source file in a temporary directory and +// load those into the Code Viewer widgets. +// +void update_sourceview_cb(Fl_Button*, void*) +{ + if (!sourceview_panel || !sourceview_panel->visible()) + return; + // generate space for the source and header file filenames + if (!sv_source_filename) { + sv_source_filename = (char*)malloc(FL_PATH_MAX); + fluid_prefs.getUserdataPath(sv_source_filename, FL_PATH_MAX); + strlcat(sv_source_filename, "source_view_tmp.cxx", FL_PATH_MAX); + } + if (!sv_header_filename) { + sv_header_filename = (char*)malloc(FL_PATH_MAX); + fluid_prefs.getUserdataPath(sv_header_filename, FL_PATH_MAX); + strlcat(sv_header_filename, "source_view_tmp.h", FL_PATH_MAX); + } + + strlcpy(i18n_program, fl_filename_name(sv_source_filename), sizeof(i18n_program)); + fl_filename_setext(i18n_program, sizeof(i18n_program), ""); + const char *code_file_name_bak = code_file_name; + code_file_name = sv_source_filename; + const char *header_file_name_bak = header_file_name; + header_file_name = sv_header_filename; + + // generate the code and load the files + write_sourceview = 1; + // generate files + if (write_code(sv_source_filename, sv_header_filename)) + { + // load file into source editor + int pos = sv_source->top_line(); + sv_source->buffer()->loadfile(sv_source_filename); + sv_source->scroll(pos, 0); + // load file into header editor + pos = sv_header->top_line(); + sv_header->buffer()->loadfile(sv_header_filename); + sv_header->scroll(pos, 0); + // update the source code highlighting + update_sourceview_position(); + } + write_sourceview = 0; + + code_file_name = code_file_name_bak; + header_file_name = header_file_name_bak; +} + +void update_sourceview_timer(void*) +{ + update_sourceview_cb(0,0); +} + +// Set the "modified" flag and update the title of the main window... +void set_modflag(int mf) { + const char *basename; + static char title[1024]; + + modflag = mf; + + if (main_window) { + if (!filename) basename = "Untitled.fl"; + else if ((basename = strrchr(filename, '/')) != NULL) basename ++; +#if defined(WIN32) || defined(__EMX__) + else if ((basename = strrchr(filename, '\\')) != NULL) basename ++; +#endif // WIN32 || __EMX__ + else basename = filename; + + if (modflag) { + snprintf(title, sizeof(title), "%s (modified)", basename); + main_window->label(title); + } else main_window->label(basename); + } + // if the UI was modified in any way, update the Source View panel + if (sourceview_panel && sourceview_panel->visible() && sv_autorefresh->value()) + { + // we will only update ealiest 0.5 seconds after the last change, and only + // if no other change was made, so dragging a widget will not generate any + // CPU load + Fl::remove_timeout(update_sourceview_timer, 0); + Fl::add_timeout(0.5, update_sourceview_timer, 0); + } + + // Enable/disable the Save menu item... + if (modflag) Main_Menu[SAVE_ITEM].activate(); + else Main_Menu[SAVE_ITEM].deactivate(); +} + +//////////////////////////////////////////////////////////////// + +static int arg(int argc, char** argv, int& i) { + if (argv[i][1] == 'c' && !argv[i][2]) {compile_only = 1; i++; return 1;} + if (argv[i][1] == 'c' && argv[i][2] == 's' && !argv[i][3]) {compile_only = 1; compile_strings = 1; i++; return 1;} + if (argv[i][1] == 'o' && !argv[i][2] && i+1 < argc) { + code_file_name = argv[i+1]; + code_file_set = 1; + i += 2; + return 2; + } + if (argv[i][1] == 'h' && !argv[i][2]) { + header_file_name = argv[i+1]; + header_file_set = 1; + i += 2; + return 2; + } + return 0; +} + +#if ! (defined(WIN32) && !defined (__CYGWIN__)) + +int quit_flag = 0; +#include <signal.h> +#ifdef _sigargs +#define SIGARG _sigargs +#else +#ifdef __sigargs +#define SIGARG __sigargs +#else +#define SIGARG int // you may need to fix this for older systems +#endif +#endif + +extern "C" { +static void sigint(SIGARG) { + signal(SIGINT,sigint); + quit_flag = 1; +} +} +#endif + +int main(int argc,char **argv) { + int i = 1; + if (!Fl::args(argc,argv,i,arg) || i < argc-1) { + fprintf(stderr,"usage: %s <switches> name.fl\n" +" -c : write .cxx and .h and exit\n" +" -cs : write .cxx and .h and strings and exit\n" +" -o <name> : .cxx output filename, or extension if <name> starts with '.'\n" +" -h <name> : .h output filename, or extension if <name> starts with '.'\n" +"%s\n", argv[0], Fl::help); + return 1; + } + const char *c = argv[i]; + + fl_register_images(); + + make_main_window(); + +#ifdef __APPLE__ + fl_open_callback(apple_open_cb); +#endif // __APPLE__ + + if (c) set_filename(c); + if (!compile_only) { + Fl::visual((Fl_Mode)(FL_DOUBLE|FL_INDEX)); + Fl_File_Icon::load_system_icons(); + main_window->callback(exit_cb); + position_window(main_window,"main_window_pos", 1, 10, 30, WINWIDTH, WINHEIGHT ); + main_window->show(argc,argv); + toggle_widgetbin_cb(0,0); + toggle_sourceview_cb(0,0); + if (!c && openlast_button->value() && absolute_history[0][0]) { + // Open previous file when no file specified... + open_history_cb(0, absolute_history[0]); + } + } + undo_suspend(); + if (c && !read_file(c,0)) { + if (compile_only) { + fprintf(stderr,"%s : %s\n", c, strerror(errno)); + exit(1); + } + fl_message("Can't read %s: %s", c, strerror(errno)); + } + undo_resume(); + if (compile_only) { + if (compile_strings) write_strings_cb(0,0); + write_cb(0,0); + exit(0); + } + set_modflag(0); + undo_clear(); +#ifndef WIN32 + signal(SIGINT,sigint); +#endif + + grid_cb(horizontal_input, 0); // Makes sure that windows get snap params... + +#ifdef WIN32 + Fl::run(); +#else + while (!quit_flag) Fl::wait(); + + if (quit_flag) exit_cb(0,0); +#endif // WIN32 + + undo_clear(); + + return (0); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/fluid.desktop b/Utilities/FLTK/fluid/fluid.desktop new file mode 100644 index 0000000000..61a531db6f --- /dev/null +++ b/Utilities/FLTK/fluid/fluid.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Name=FLUID +Comment=FLTK GUI Designer +TryExec=fluid +Exec=fluid %F +Icon=fluid +Terminal=false +Type=Application +MimeType=application/x-fluid +Encoding=UTF-8 +Categories=Development diff --git a/Utilities/FLTK/fluid/function_panel.cxx b/Utilities/FLTK/fluid/function_panel.cxx new file mode 100644 index 0000000000..43c6ccf880 --- /dev/null +++ b/Utilities/FLTK/fluid/function_panel.cxx @@ -0,0 +1,933 @@ +// +// "$Id$" +// +// Code dialogs for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// generated by Fast Light User Interface Designer (fluid) version 1.0107 + +#include "function_panel.h" +#include <FL/Fl_Pixmap.H> +#include "Fl_Type.h" +#include "undo.h" +extern class Fl_Pixmap *pixmap[]; +extern class Fl_Type *Fl_Type_make(const char*); +extern void select_only(Fl_Type*); + +Fl_Double_Window *function_panel=(Fl_Double_Window *)0; + +Fl_Light_Button *f_public_button=(Fl_Light_Button *)0; + +Fl_Light_Button *f_c_button=(Fl_Light_Button *)0; + +Fl_Input *f_name_input=(Fl_Input *)0; + +Fl_Input *f_return_type_input=(Fl_Input *)0; + +Fl_Return_Button *f_panel_ok=(Fl_Return_Button *)0; + +Fl_Button *f_panel_cancel=(Fl_Button *)0; + +Fl_Double_Window* make_function_panel() { + Fl_Double_Window* w; + { Fl_Double_Window* o = function_panel = new Fl_Double_Window(290, 150, "Function/Method Properties"); + w = o; + { Fl_Group* o = new Fl_Group(10, 10, 270, 20); + { Fl_Light_Button* o = f_public_button = new Fl_Light_Button(10, 10, 60, 20, "public"); + o->tooltip("Make the function or method publicly accessible."); + o->labelsize(11); + o->when(FL_WHEN_NEVER); + } + { Fl_Light_Button* o = f_c_button = new Fl_Light_Button(80, 10, 80, 20, "C declaration"); + o->tooltip("Declare with a C interface instead of C++."); + o->labelsize(11); + } + { Fl_Box* o = new Fl_Box(170, 10, 110, 20); + Fl_Group::current()->resizable(o); + } + o->end(); + } + { Fl_Input* o = f_name_input = new Fl_Input(10, 50, 270, 20, "Name(args): (blank for main())"); + o->tooltip("The name of the function or method."); + o->labelfont(1); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->align(FL_ALIGN_TOP_LEFT); + o->when(FL_WHEN_NEVER); + Fl_Group::current()->resizable(o); + } + { Fl_Input* o = f_return_type_input = new Fl_Input(10, 90, 270, 20, "Return Type: (blank to return outermost widget)"); + o->tooltip("The return type of the function or method."); + o->labelfont(1); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->align(FL_ALIGN_TOP_LEFT); + o->when(FL_WHEN_NEVER); + } + { Fl_Group* o = new Fl_Group(10, 120, 270, 20); + { Fl_Return_Button* o = f_panel_ok = new Fl_Return_Button(170, 120, 50, 20, "OK"); + o->tooltip("Apply the changes."); + o->labelsize(11); + w->hotspot(o); + } + { Fl_Button* o = f_panel_cancel = new Fl_Button(230, 120, 50, 20, "Cancel"); + o->tooltip("Cancel the changes."); + o->shortcut(0xff1b); + o->labelsize(11); + } + { Fl_Box* o = new Fl_Box(10, 120, 150, 20); + Fl_Group::current()->resizable(o); + } + o->end(); + } + o->size_range(o->w(), o->h(), Fl::w(), o->h()); + o->set_modal(); + o->end(); + } + return w; +} + +Fl_Double_Window *code_panel=(Fl_Double_Window *)0; + +CodeEditor *code_input=(CodeEditor *)0; + +Fl_Return_Button *code_panel_ok=(Fl_Return_Button *)0; + +Fl_Button *code_panel_cancel=(Fl_Button *)0; + +Fl_Double_Window* make_code_panel() { + Fl_Double_Window* w; + { Fl_Double_Window* o = code_panel = new Fl_Double_Window(540, 180, "Code Properties"); + w = o; + o->labelsize(11); + { CodeEditor* o = code_input = new CodeEditor(10, 10, 520, 130); + o->box(FL_DOWN_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_SELECTION_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(11); + o->labelcolor(FL_FOREGROUND_COLOR); + o->textfont(4); + o->textsize(11); + o->align(FL_ALIGN_TOP); + o->when(FL_WHEN_RELEASE); + Fl_Group::current()->resizable(o); + o->when(FL_WHEN_ENTER_KEY_CHANGED|FL_WHEN_RELEASE); + } + { Fl_Group* o = new Fl_Group(10, 150, 520, 20); + o->labelsize(11); + { Fl_Return_Button* o = code_panel_ok = new Fl_Return_Button(400, 150, 60, 20, "OK"); + o->labelsize(11); + w->hotspot(o); + } + { Fl_Button* o = code_panel_cancel = new Fl_Button(470, 150, 60, 20, "Cancel"); + o->shortcut(0xff1b); + o->labelsize(11); + } + { Fl_Box* o = new Fl_Box(10, 150, 380, 20); + o->labelsize(11); + Fl_Group::current()->resizable(o); + } + o->end(); + } + o->size_range(200, 150); + o->set_modal(); + o->end(); + } + return w; +} + +Fl_Double_Window *codeblock_panel=(Fl_Double_Window *)0; + +Fl_Input *code_before_input=(Fl_Input *)0; + +Fl_Input *code_after_input=(Fl_Input *)0; + +Fl_Return_Button *codeblock_panel_ok=(Fl_Return_Button *)0; + +Fl_Button *codeblock_panel_cancel=(Fl_Button *)0; + +Fl_Double_Window* make_codeblock_panel() { + Fl_Double_Window* w; + { Fl_Double_Window* o = codeblock_panel = new Fl_Double_Window(300, 115, "Code Block Properties"); + w = o; + o->labelsize(11); + { Fl_Input* o = code_before_input = new Fl_Input(10, 15, 280, 20, "Conditional code block"); + o->tooltip("#ifdef or similar conditional code block."); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->align(FL_ALIGN_TOP_LEFT); + o->when(FL_WHEN_NEVER); + } + { Fl_Input* o = code_after_input = new Fl_Input(10, 55, 280, 20, "\"{...child code...}\" is inserted here"); + o->tooltip("#endif or similar conditional code block."); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->align(FL_ALIGN_TOP_LEFT); + o->when(FL_WHEN_NEVER); + Fl_Group::current()->resizable(o); + } + { Fl_Group* o = new Fl_Group(10, 85, 280, 20); + { Fl_Return_Button* o = codeblock_panel_ok = new Fl_Return_Button(160, 85, 60, 20, "OK"); + o->labelsize(11); + w->hotspot(o); + } + { Fl_Button* o = codeblock_panel_cancel = new Fl_Button(230, 85, 60, 20, "Cancel"); + o->shortcut(0xff1b); + o->labelsize(11); + } + { Fl_Box* o = new Fl_Box(10, 85, 140, 20); + Fl_Group::current()->resizable(o); + } + o->end(); + } + o->size_range(o->w(), o->h(), Fl::w(), o->h()); + o->set_modal(); + o->end(); + } + return w; +} + +Fl_Double_Window *declblock_panel=(Fl_Double_Window *)0; + +Fl_Input *decl_before_input=(Fl_Input *)0; + +Fl_Input *decl_after_input=(Fl_Input *)0; + +Fl_Return_Button *declblock_panel_ok=(Fl_Return_Button *)0; + +Fl_Button *declblock_panel_cancel=(Fl_Button *)0; + +Fl_Light_Button *declblock_public_button=(Fl_Light_Button *)0; + +Fl_Double_Window* make_declblock_panel() { + Fl_Double_Window* w; + { Fl_Double_Window* o = declblock_panel = new Fl_Double_Window(300, 135, "Declaration Block Properties"); + w = o; + o->labelsize(11); + { Fl_Input* o = decl_before_input = new Fl_Input(10, 40, 280, 20); + o->tooltip("#ifdef or similar conditional declaration block."); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->align(FL_ALIGN_TOP_LEFT); + o->when(FL_WHEN_NEVER); + Fl_Group::current()->resizable(o); + } + { Fl_Input* o = decl_after_input = new Fl_Input(10, 75, 280, 20, "\"\\n...child code...\\n\" is inserted here"); + o->tooltip("#endif or similar declaration code block."); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->align(FL_ALIGN_TOP_LEFT); + o->when(FL_WHEN_NEVER); + } + { Fl_Group* o = new Fl_Group(10, 105, 280, 20); + { Fl_Return_Button* o = declblock_panel_ok = new Fl_Return_Button(160, 105, 60, 20, "OK"); + o->labelsize(11); + w->hotspot(o); + } + { Fl_Button* o = declblock_panel_cancel = new Fl_Button(230, 105, 60, 20, "Cancel"); + o->shortcut(0xff1b); + o->labelsize(11); + } + { Fl_Box* o = new Fl_Box(10, 105, 140, 20); + Fl_Group::current()->resizable(o); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(10, 10, 280, 20); + { Fl_Light_Button* o = declblock_public_button = new Fl_Light_Button(10, 10, 60, 20, "public"); + o->tooltip("Make the declaration publicly accessible."); + o->labelsize(11); + o->when(FL_WHEN_NEVER); + } + { Fl_Box* o = new Fl_Box(80, 10, 210, 20); + Fl_Group::current()->resizable(o); + } + o->end(); + } + o->size_range(o->w(), o->h(), Fl::w(), o->h()); + o->set_modal(); + o->end(); + } + return w; +} + +Fl_Double_Window *decl_panel=(Fl_Double_Window *)0; + +Fl_Light_Button *decl_public_button=(Fl_Light_Button *)0; + +Fl_Input *decl_input=(Fl_Input *)0; + +Fl_Return_Button *decl_panel_ok=(Fl_Return_Button *)0; + +Fl_Button *decl_panel_cancel=(Fl_Button *)0; + +Fl_Double_Window* make_decl_panel() { + Fl_Double_Window* w; + { Fl_Double_Window* o = decl_panel = new Fl_Double_Window(290, 150, "Declaration Properties"); + w = o; + { Fl_Group* o = new Fl_Group(10, 10, 270, 20); + { Fl_Light_Button* o = decl_public_button = new Fl_Light_Button(10, 10, 60, 20, "public"); + o->tooltip("Make the declaration publicly accessible."); + o->labelsize(11); + o->when(FL_WHEN_NEVER); + } + { Fl_Box* o = new Fl_Box(80, 10, 200, 20); + Fl_Group::current()->resizable(o); + } + o->end(); + } + { Fl_Input* o = decl_input = new Fl_Input(10, 40, 270, 20, "Can be any declaration, like \"int x;\", an external symbol like \"extern int\ + foo();\", a #directive like \"#include <foo.h>\", a comment like \"//foo\" or\ + \"/*foo*/\", or typedef like \"typedef char byte;\" or \"using std::list;\"."); + o->tooltip("Declaration text."); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->align(134); + o->when(FL_WHEN_NEVER); + Fl_Group::current()->resizable(o); + } + { Fl_Group* o = new Fl_Group(10, 120, 270, 20); + { Fl_Return_Button* o = decl_panel_ok = new Fl_Return_Button(150, 120, 60, 20, "OK"); + o->labelsize(11); + w->hotspot(o); + } + { Fl_Button* o = decl_panel_cancel = new Fl_Button(220, 120, 60, 20, "Cancel"); + o->shortcut(0xff1b); + o->labelsize(11); + } + { Fl_Box* o = new Fl_Box(10, 120, 130, 20); + Fl_Group::current()->resizable(o); + } + o->end(); + } + o->size_range(o->w(), o->h(), Fl::w(), o->h()); + o->end(); + } + return w; +} + +Fl_Double_Window *class_panel=(Fl_Double_Window *)0; + +Fl_Light_Button *c_public_button=(Fl_Light_Button *)0; + +Fl_Input *c_name_input=(Fl_Input *)0; + +Fl_Input *c_subclass_input=(Fl_Input *)0; + +Fl_Return_Button *c_panel_ok=(Fl_Return_Button *)0; + +Fl_Button *c_panel_cancel=(Fl_Button *)0; + +Fl_Double_Window* make_class_panel() { + Fl_Double_Window* w; + { Fl_Double_Window* o = class_panel = new Fl_Double_Window(300, 140, "Class Properties"); + w = o; + o->labelsize(11); + { Fl_Group* o = new Fl_Group(10, 10, 280, 20); + { Fl_Light_Button* o = c_public_button = new Fl_Light_Button(10, 10, 60, 20, "public"); + o->tooltip("Make the class publicly accessible."); + o->labelsize(11); + o->when(FL_WHEN_NEVER); + } + { Fl_Box* o = new Fl_Box(80, 10, 210, 20); + Fl_Group::current()->resizable(o); + } + o->end(); + } + { Fl_Input* o = c_name_input = new Fl_Input(10, 45, 280, 20, "Name:"); + o->tooltip("Name of class."); + o->labelfont(1); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->align(FL_ALIGN_TOP_LEFT); + o->when(FL_WHEN_NEVER); + Fl_Group::current()->resizable(o); + } + { Fl_Input* o = c_subclass_input = new Fl_Input(10, 80, 280, 20, "Subclass of (text between : and {)"); + o->tooltip("Name of subclass."); + o->labelfont(1); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->align(FL_ALIGN_TOP_LEFT); + o->when(FL_WHEN_NEVER); + } + { Fl_Group* o = new Fl_Group(10, 110, 280, 20); + { Fl_Return_Button* o = c_panel_ok = new Fl_Return_Button(160, 110, 60, 20, "OK"); + o->labelsize(11); + w->hotspot(o); + } + { Fl_Button* o = c_panel_cancel = new Fl_Button(230, 110, 60, 20, "Cancel"); + o->shortcut(0xff1b); + o->labelsize(11); + } + { Fl_Box* o = new Fl_Box(10, 110, 140, 20); + Fl_Group::current()->resizable(o); + } + o->end(); + } + o->size_range(o->w(), o->h(), Fl::w(), o->h()); + o->set_modal(); + o->end(); + } + return w; +} + +Fl_Double_Window *comment_panel=(Fl_Double_Window *)0; + +CodeEditor *comment_input=(CodeEditor *)0; + +Fl_Return_Button *comment_panel_ok=(Fl_Return_Button *)0; + +Fl_Button *comment_panel_cancel=(Fl_Button *)0; + +Fl_Light_Button *comment_in_source=(Fl_Light_Button *)0; + +Fl_Light_Button *comment_in_header=(Fl_Light_Button *)0; + +Fl_Menu_Button *comment_predefined=(Fl_Menu_Button *)0; + +Fl_Button *comment_load=(Fl_Button *)0; + +Fl_Double_Window* make_comment_panel() { + Fl_Double_Window* w; + { Fl_Double_Window* o = comment_panel = new Fl_Double_Window(550, 280, "Comment Properties"); + w = o; + o->labelsize(11); + { CodeEditor* o = comment_input = new CodeEditor(110, 10, 430, 230); + o->box(FL_DOWN_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_SELECTION_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(11); + o->labelcolor(FL_FOREGROUND_COLOR); + o->textfont(4); + o->textsize(11); + o->align(FL_ALIGN_TOP); + o->when(FL_WHEN_RELEASE); + Fl_Group::current()->resizable(o); + o->when(FL_WHEN_ENTER_KEY_CHANGED|FL_WHEN_RELEASE); + } + { Fl_Group* o = new Fl_Group(110, 250, 430, 20); + o->labelsize(11); + { Fl_Return_Button* o = comment_panel_ok = new Fl_Return_Button(370, 250, 80, 20, "OK"); + o->labelsize(11); + w->hotspot(o); + } + { Fl_Button* o = comment_panel_cancel = new Fl_Button(460, 250, 80, 20, "Cancel"); + o->shortcut(0xff1b); + o->labelsize(11); + } + { Fl_Box* o = new Fl_Box(110, 250, 250, 20); + o->labelsize(11); + Fl_Group::current()->resizable(o); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(10, 10, 90, 243); + o->labelsize(11); + { Fl_Light_Button* o = comment_in_source = new Fl_Light_Button(10, 10, 90, 20, "In Source"); + o->tooltip("Put the comment into the source (.cxx) file."); + o->labelsize(11); + o->when(FL_WHEN_NEVER); + } + { Fl_Light_Button* o = comment_in_header = new Fl_Light_Button(10, 40, 90, 20, "In Header"); + o->tooltip("Put the comment into the header (.h) file."); + o->labelsize(11); + o->when(FL_WHEN_NEVER); + } + { Fl_Menu_Button* o = comment_predefined = new Fl_Menu_Button(10, 70, 90, 20, "Predefined"); + o->labelsize(11); + o->textsize(11); + } + { Fl_Button* o = comment_load = new Fl_Button(10, 100, 90, 20, "Import..."); + o->labelsize(11); + } + { Fl_Box* o = new Fl_Box(10, 132, 90, 121); + o->labelsize(11); + Fl_Group::current()->resizable(o); + } + o->end(); + } + o->size_range(320, 180); + o->set_modal(); + o->end(); + } + return w; +} + +void type_make_cb(Fl_Widget*w,void*d) { + undo_checkpoint(); + Fl_Type *t = Fl_Type_make((char*)d); + if (t) { + select_only(t); + set_modflag(1); + t->open(); + } else { + undo_current --; + undo_last --; + } +} + +Fl_Window *widgetbin_panel=(Fl_Window *)0; + +Fl_Window* make_widgetbin() { + Fl_Window* w; + { Fl_Window* o = widgetbin_panel = new Fl_Window(520, 85, "Widget Bin"); + w = o; + { Fl_Group* o = new Fl_Group(3, 3, 79, 79); + o->box(FL_THIN_DOWN_BOX); + { Fl_Button* o = new Fl_Button(5, 5, 25, 25); + o->tooltip("Function"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Function")); + o->image(pixmap[7]); + } + { Fl_Button* o = new Fl_Button(30, 5, 25, 25); + o->tooltip("Class"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Class")); + o->image(pixmap[12]); + } + { Fl_Button* o = new Fl_Button(55, 5, 25, 25); + o->tooltip("Comment"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("comment")); + o->image(pixmap[46]); + } + { Fl_Button* o = new Fl_Button(5, 30, 25, 25); + o->tooltip("Code"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Code")); + o->image(pixmap[8]); + } + { Fl_Button* o = new Fl_Button(30, 30, 25, 25); + o->tooltip("Code Block"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("CodeBlock")); + o->image(pixmap[9]); + } + { Fl_Button* o = new Fl_Button(55, 30, 25, 25); + o->tooltip("Widget Class"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("widget_class")); + o->image(pixmap[48]); + } + { Fl_Button* o = new Fl_Button(5, 55, 25, 25); + o->tooltip("Declaration"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("decl")); + o->image(pixmap[10]); + } + { Fl_Button* o = new Fl_Button(30, 55, 25, 25); + o->tooltip("Declaration Block"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("declblock")); + o->image(pixmap[11]); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(83, 3, 79, 79); + o->box(FL_THIN_DOWN_BOX); + { Fl_Button* o = new Fl_Button(85, 5, 25, 25); + o->tooltip("Window"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Window")); + o->image(pixmap[1]); + } + { Fl_Button* o = new Fl_Button(110, 5, 25, 25); + o->tooltip("Group"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Group")); + o->image(pixmap[6]); + } + { Fl_Button* o = new Fl_Button(135, 5, 25, 25); + o->tooltip("Pack"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Pack")); + o->image(pixmap[22]); + } + { Fl_Button* o = new Fl_Button(85, 30, 25, 25); + o->tooltip("Tabs"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Tabs")); + o->image(pixmap[13]); + } + { Fl_Button* o = new Fl_Button(110, 30, 25, 25); + o->tooltip("Scroll"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Scroll")); + o->image(pixmap[19]); + } + { Fl_Button* o = new Fl_Button(85, 55, 25, 25); + o->tooltip("Tile"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Tile")); + o->image(pixmap[20]); + } + { Fl_Button* o = new Fl_Button(110, 55, 25, 25); + o->tooltip("Wizard"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Wizard")); + o->image(pixmap[21]); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(163, 3, 54, 79); + o->box(FL_THIN_DOWN_BOX); + { Fl_Button* o = new Fl_Button(165, 5, 25, 25); + o->tooltip("Button"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Button")); + o->image(pixmap[2]); + } + { Fl_Button* o = new Fl_Button(190, 5, 25, 25); + o->tooltip("Return Button"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Return_Button")); + o->image(pixmap[23]); + } + { Fl_Button* o = new Fl_Button(165, 30, 25, 25); + o->tooltip("Light Button"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Light_Button")); + o->image(pixmap[24]); + } + { Fl_Button* o = new Fl_Button(190, 30, 25, 25); + o->tooltip("Repeat Button"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Repeat_Button")); + o->image(pixmap[25]); + } + { Fl_Button* o = new Fl_Button(165, 55, 25, 25); + o->tooltip("Check Button"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Check_Button")); + o->image(pixmap[3]); + } + { Fl_Button* o = new Fl_Button(190, 55, 25, 25); + o->tooltip("Round Button"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Round_Button")); + o->image(pixmap[4]); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(218, 3, 104, 79); + o->box(FL_THIN_DOWN_BOX); + { Fl_Button* o = new Fl_Button(220, 5, 25, 25); + o->tooltip("Slider"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Slider")); + o->image(pixmap[37]); + } + { Fl_Button* o = new Fl_Button(245, 5, 25, 25); + o->tooltip("Scroll Bar"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Scrollbar")); + o->image(pixmap[38]); + } + { Fl_Button* o = new Fl_Button(270, 5, 25, 25); + o->tooltip("Value Slider"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Value_Slider")); + o->image(pixmap[39]); + } + { Fl_Button* o = new Fl_Button(295, 5, 25, 25); + o->tooltip("Value Output"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Value_Output")); + o->image(pixmap[45]); + } + { Fl_Button* o = new Fl_Button(220, 30, 25, 25); + o->tooltip("Adjuster"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Adjuster")); + o->image(pixmap[40]); + } + { Fl_Button* o = new Fl_Button(245, 30, 25, 25); + o->tooltip("Counter"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Counter")); + o->image(pixmap[41]); + } + { Fl_Button* o = new Fl_Button(270, 30, 25, 25); + o->tooltip("Dial"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Dial")); + o->image(pixmap[42]); + } + { Fl_Button* o = new Fl_Button(220, 55, 25, 25); + o->tooltip("Roller"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Roller")); + o->image(pixmap[43]); + } + { Fl_Button* o = new Fl_Button(245, 55, 25, 25); + o->tooltip("Spinner"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Spinner")); + o->image(pixmap[47]); + } + { Fl_Button* o = new Fl_Button(270, 55, 25, 25); + o->tooltip("Value Input"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Value_Input")); + o->image(pixmap[44]); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(323, 3, 54, 79); + o->box(FL_THIN_DOWN_BOX); + { Fl_Button* o = new Fl_Button(325, 5, 25, 25); + o->tooltip("Input"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Input")); + o->image(pixmap[14]); + } + { Fl_Button* o = new Fl_Button(350, 5, 25, 25); + o->tooltip("Output"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Output")); + o->image(pixmap[27]); + } + { Fl_Button* o = new Fl_Button(325, 30, 25, 25); + o->tooltip("Text Edit"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Text_Editor")); + o->image(pixmap[29]); + } + { Fl_Button* o = new Fl_Button(350, 30, 25, 25); + o->tooltip("Text Display"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Text_Display")); + o->image(pixmap[28]); + } + { Fl_Button* o = new Fl_Button(325, 55, 25, 25); + o->tooltip("File Input"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_File_Input")); + o->image(pixmap[30]); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(378, 3, 54, 79); + o->box(FL_THIN_DOWN_BOX); + { Fl_Button* o = new Fl_Button(380, 5, 25, 25); + o->tooltip("Menu Bar"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Menu_Bar")); + o->image(pixmap[17]); + } + { Fl_Button* o = new Fl_Button(405, 5, 25, 25); + o->tooltip("Input Choice"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Input_Choice")); + o->image(pixmap[15]); + } + { Fl_Button* o = new Fl_Button(380, 30, 25, 25); + o->tooltip("Menu Button"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Menu_Button")); + o->image(pixmap[26]); + } + { Fl_Button* o = new Fl_Button(405, 30, 25, 25); + o->tooltip("Menu Item"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("menuitem")); + o->image(pixmap[16]); + } + { Fl_Button* o = new Fl_Button(380, 55, 25, 25); + o->tooltip("Choice"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Choice")); + o->image(pixmap[15]); + } + { Fl_Button* o = new Fl_Button(405, 55, 25, 25); + o->tooltip("Sub Menu"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("submenu")); + o->image(pixmap[18]); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(433, 3, 29, 79); + o->box(FL_THIN_DOWN_BOX); + { Fl_Button* o = new Fl_Button(435, 5, 25, 25); + o->tooltip("Browser"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Browser")); + o->image(pixmap[31]); + } + { Fl_Button* o = new Fl_Button(435, 30, 25, 25); + o->tooltip("Check Browser"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Check_Browser")); + o->image(pixmap[32]); + } + { Fl_Button* o = new Fl_Button(435, 55, 25, 25); + o->tooltip("File Browser"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_File_Browser")); + o->image(pixmap[33]); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(463, 3, 54, 79); + o->box(FL_THIN_DOWN_BOX); + { Fl_Button* o = new Fl_Button(465, 5, 25, 25); + o->tooltip("Box"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Box")); + o->image(pixmap[5]); + } + { Fl_Button* o = new Fl_Button(490, 5, 25, 25); + o->tooltip("Clock"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Clock")); + o->image(pixmap[34]); + } + { Fl_Button* o = new Fl_Button(465, 30, 25, 25); + o->tooltip("Help Browser"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Help_View")); + o->image(pixmap[35]); + } + { Fl_Button* o = new Fl_Button(465, 55, 25, 25); + o->tooltip("Progress"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Progress")); + o->image(pixmap[36]); + } + o->end(); + } + o->set_non_modal(); + o->end(); + } + return w; +} + +Fl_Double_Window *sourceview_panel=(Fl_Double_Window *)0; + +Fl_Tabs *sv_tab=(Fl_Tabs *)0; + +CodeEditor *sv_source=(CodeEditor *)0; + +CodeEditor *sv_header=(CodeEditor *)0; + +Fl_Light_Button *sv_autorefresh=(Fl_Light_Button *)0; + +Fl_Light_Button *sv_autoposition=(Fl_Light_Button *)0; + +Fl_Double_Window* make_sourceview() { + Fl_Double_Window* w; + { Fl_Double_Window* o = sourceview_panel = new Fl_Double_Window(520, 490, "Code View"); + w = o; + o->callback((Fl_Callback*)toggle_sourceview_cb); + { Fl_Tabs* o = sv_tab = new Fl_Tabs(10, 10, 500, 440); + o->selection_color((Fl_Color)4); + o->labelcolor(FL_BACKGROUND2_COLOR); + o->callback((Fl_Callback*)update_sourceview_position_cb); + { Fl_Group* o = new Fl_Group(10, 35, 500, 415, "Source"); + o->labelsize(13); + o->hide(); + { CodeEditor* o = sv_source = new CodeEditor(20, 50, 480, 390); + o->box(FL_DOWN_FRAME); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_SELECTION_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); + o->textfont(4); + o->textsize(11); + o->align(FL_ALIGN_TOP); + o->when(FL_WHEN_RELEASE); + Fl_Group::current()->resizable(o); + } + o->end(); + Fl_Group::current()->resizable(o); + } + { Fl_Group* o = new Fl_Group(10, 35, 500, 415, "Header"); + o->labelsize(13); + { CodeEditor* o = sv_header = new CodeEditor(20, 50, 480, 390); + o->box(FL_DOWN_FRAME); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_SELECTION_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); + o->textfont(4); + o->textsize(11); + o->align(FL_ALIGN_TOP); + o->when(FL_WHEN_RELEASE); + Fl_Group::current()->resizable(o); + } + o->end(); + } + o->end(); + Fl_Group::current()->resizable(o); + } + { Fl_Group* o = new Fl_Group(10, 460, 500, 20); + { Fl_Button* o = new Fl_Button(10, 460, 61, 20, "Refresh"); + o->labelsize(11); + o->callback((Fl_Callback*)update_sourceview_cb); + } + { Fl_Light_Button* o = sv_autorefresh = new Fl_Light_Button(76, 460, 91, 20, "Auto-Refresh"); + o->labelsize(11); + o->callback((Fl_Callback*)update_sourceview_cb); + } + { Fl_Light_Button* o = sv_autoposition = new Fl_Light_Button(172, 460, 89, 20, "Auto-Position"); + o->labelsize(11); + } + { Fl_Button* o = new Fl_Button(460, 460, 50, 20, "Close"); + o->labelsize(11); + o->callback((Fl_Callback*)toggle_sourceview_b_cb); + } + { Fl_Box* o = new Fl_Box(265, 460, 190, 20); + Fl_Group::current()->resizable(o); + } + o->end(); + } + o->size_range(384, 120); + o->end(); + } + return w; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/function_panel.fl b/Utilities/FLTK/fluid/function_panel.fl new file mode 100644 index 0000000000..05528ce52a --- /dev/null +++ b/Utilities/FLTK/fluid/function_panel.fl @@ -0,0 +1,752 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +comment {// +// "$Id: function_panel.fl 4638 2005-11-04 15:16:24Z matt $" +// +// Code dialogs for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +} {in_source in_header +} + +decl {\#include <FL/Fl_Pixmap.H>} {} + +decl {\#include "Fl_Type.h"} {} + +decl {\#include "undo.h"} {} + +decl {extern class Fl_Pixmap *pixmap[];} {} + +decl {extern class Fl_Type *Fl_Type_make(const char*);} {} + +decl {extern void select_only(Fl_Type*);} {} + +Function {make_function_panel()} {open +} { + Fl_Window function_panel { + label {Function/Method Properties} + xywh {419 200 290 150} type Double hide resizable + code0 {o->size_range(o->w(), o->h(), Fl::w(), o->h());} modal + } { + Fl_Group {} {open + xywh {10 10 270 20} + } { + Fl_Light_Button f_public_button { + label public + tooltip {Make the function or method publicly accessible.} xywh {10 10 60 20} labelsize 11 when 0 + } + Fl_Light_Button f_c_button { + label {C declaration} + tooltip {Declare with a C interface instead of C++.} xywh {80 10 80 20} labelsize 11 + } + Fl_Box {} { + xywh {170 10 110 20} resizable + } + } + Fl_Input f_name_input { + label {Name(args): (blank for main())} + tooltip {The name of the function or method.} xywh {10 50 270 20} labelfont 1 labelsize 11 align 5 when 0 textfont 4 textsize 11 resizable + } + Fl_Input f_return_type_input { + label {Return Type: (blank to return outermost widget)} + tooltip {The return type of the function or method.} xywh {10 90 270 20} labelfont 1 labelsize 11 align 5 when 0 textfont 4 textsize 11 + } + Fl_Group {} {open + xywh {10 120 270 20} + } { + Fl_Return_Button f_panel_ok { + label OK + tooltip {Apply the changes.} xywh {170 120 50 20} labelsize 11 hotspot + } + Fl_Button f_panel_cancel { + label Cancel + tooltip {Cancel the changes.} xywh {230 120 50 20} shortcut 0xff1b labelsize 11 + } + Fl_Box {} { + xywh {10 120 150 20} resizable + } + } + } +} + +Function {make_code_panel()} {open +} { + Fl_Window code_panel { + label {Code Properties} + xywh {353 262 540 180} type Double labelsize 11 hide resizable + code0 {o->size_range(200, 150);} modal + } { + Fl_Text_Editor code_input { + xywh {10 10 520 130} box DOWN_BOX labelsize 11 textfont 4 textsize 11 resizable + code0 {o->when(FL_WHEN_ENTER_KEY_CHANGED|FL_WHEN_RELEASE);} + code1 {\#include "CodeEditor.h"} + class CodeEditor + } + Fl_Group {} {open + xywh {10 150 520 20} labelsize 11 + } { + Fl_Return_Button code_panel_ok { + label OK + xywh {400 150 60 20} labelsize 11 hotspot + } + Fl_Button code_panel_cancel { + label Cancel + xywh {470 150 60 20} shortcut 0xff1b labelsize 11 + } + Fl_Box {} { + xywh {10 150 380 20} labelsize 11 resizable + } + } + } +} + +Function {make_codeblock_panel()} {open +} { + Fl_Window codeblock_panel { + label {Code Block Properties} + xywh {468 221 300 115} type Double labelsize 11 hide resizable + code0 {o->size_range(o->w(), o->h(), Fl::w(), o->h());} modal + } { + Fl_Input code_before_input { + label {Conditional code block} + tooltip {\#ifdef or similar conditional code block.} xywh {10 15 280 20} labelsize 11 align 5 when 0 textfont 4 textsize 11 + } + Fl_Input code_after_input { + label {"{...child code...}" is inserted here} + tooltip {\#endif or similar conditional code block.} xywh {10 55 280 20} labelsize 11 align 5 when 0 textfont 4 textsize 11 resizable + } + Fl_Group {} {open + xywh {10 85 280 20} + } { + Fl_Return_Button codeblock_panel_ok { + label OK + xywh {160 85 60 20} labelsize 11 hotspot + } + Fl_Button codeblock_panel_cancel { + label Cancel + xywh {230 85 60 20} shortcut 0xff1b labelsize 11 + } + Fl_Box {} { + xywh {10 85 140 20} resizable + } + } + } +} + +Function {make_declblock_panel()} {open +} { + Fl_Window declblock_panel { + label {Declaration Block Properties} + xywh {428 215 300 135} type Double labelsize 11 hide resizable + code0 {o->size_range(o->w(), o->h(), Fl::w(), o->h());} modal + } { + Fl_Input decl_before_input { + tooltip {\#ifdef or similar conditional declaration block.} xywh {10 40 280 20} labelsize 11 align 5 when 0 textfont 4 textsize 11 resizable + } + Fl_Input decl_after_input { + label {"\\n...child code...\\n" is inserted here} + tooltip {\#endif or similar declaration code block.} xywh {10 75 280 20} labelsize 11 align 5 when 0 textfont 4 textsize 11 + } + Fl_Group {} {open + xywh {10 105 280 20} + } { + Fl_Return_Button declblock_panel_ok { + label OK + xywh {160 105 60 20} labelsize 11 hotspot + } + Fl_Button declblock_panel_cancel { + label Cancel + xywh {230 105 60 20} shortcut 0xff1b labelsize 11 + } + Fl_Box {} { + xywh {10 105 140 20} resizable + } + } + Fl_Group {} {open + xywh {10 10 280 20} + } { + Fl_Light_Button declblock_public_button { + label public + tooltip {Make the declaration publicly accessible.} xywh {10 10 60 20} labelsize 11 when 0 + } + Fl_Box {} { + xywh {80 10 210 20} resizable + } + } + } +} + +Function {make_decl_panel()} {open +} { + Fl_Window decl_panel { + label {Declaration Properties} + xywh {412 206 290 150} type Double hide resizable + code0 {o->size_range(o->w(), o->h(), Fl::w(), o->h());} + } { + Fl_Group {} {open + xywh {10 10 270 20} + } { + Fl_Light_Button decl_public_button { + label public + tooltip {Make the declaration publicly accessible.} xywh {10 10 60 20} labelsize 11 when 0 + } + Fl_Box {} { + xywh {80 10 200 20} resizable + } + } + Fl_Input decl_input { + label {Can be any declaration, like "int x;", an external symbol like "extern int foo();", a \#directive like "\#include <foo.h>", a comment like "//foo" or "/*foo*/", or typedef like "typedef char byte;" or "using std::list;".} + tooltip {Declaration text.} xywh {10 40 270 20} labelsize 11 align 134 when 0 textfont 4 textsize 11 resizable + } + Fl_Group {} {open + xywh {10 120 270 20} + } { + Fl_Return_Button decl_panel_ok { + label OK + xywh {150 120 60 20} labelsize 11 hotspot + } + Fl_Button decl_panel_cancel { + label Cancel + xywh {220 120 60 20} shortcut 0xff1b labelsize 11 + } + Fl_Box {} { + xywh {10 120 130 20} resizable + } + } + } +} + +Function {make_class_panel()} {open +} { + Fl_Window class_panel { + label {Class Properties} + xywh {449 218 300 140} type Double labelsize 11 hide resizable + code0 {o->size_range(o->w(), o->h(), Fl::w(), o->h());} modal + } { + Fl_Group {} {open + xywh {10 10 280 20} + } { + Fl_Light_Button c_public_button { + label public + tooltip {Make the class publicly accessible.} xywh {10 10 60 20} labelsize 11 when 0 + } + Fl_Box {} { + xywh {80 10 210 20} resizable + } + } + Fl_Input c_name_input { + label {Name:} + tooltip {Name of class.} xywh {10 45 280 20} labelfont 1 labelsize 11 align 5 when 0 textfont 4 textsize 11 resizable + } + Fl_Input c_subclass_input { + label {Subclass of (text between : and \{)} + tooltip {Name of subclass.} xywh {10 80 280 20} labelfont 1 labelsize 11 align 5 when 0 textfont 4 textsize 11 + } + Fl_Group {} {open + xywh {10 110 280 20} + } { + Fl_Return_Button c_panel_ok { + label OK + xywh {160 110 60 20} labelsize 11 hotspot + } + Fl_Button c_panel_cancel { + label Cancel + xywh {230 110 60 20} shortcut 0xff1b labelsize 11 + } + Fl_Box {} { + xywh {10 110 140 20} resizable + } + } + } +} + +Function {make_comment_panel()} {open +} { + Fl_Window comment_panel { + label {Comment Properties} + xywh {422 190 550 280} type Double labelsize 11 hide resizable + code0 {o->size_range(320, 180);} modal + } { + Fl_Text_Editor comment_input { + xywh {110 10 430 230} box DOWN_BOX labelsize 11 textfont 4 textsize 11 resizable + code0 {o->when(FL_WHEN_ENTER_KEY_CHANGED|FL_WHEN_RELEASE);} + class CodeEditor + } + Fl_Group {} {open + xywh {110 250 430 20} labelsize 11 + } { + Fl_Return_Button comment_panel_ok { + label OK + xywh {370 250 80 20} labelsize 11 hotspot + } + Fl_Button comment_panel_cancel { + label Cancel + xywh {460 250 80 20} shortcut 0xff1b labelsize 11 + } + Fl_Box {} { + xywh {110 250 250 20} labelsize 11 resizable + } + } + Fl_Group {} {open + xywh {10 10 90 243} labelsize 11 + } { + Fl_Light_Button comment_in_source { + label {In Source} + tooltip {Put the comment into the source (.cxx) file.} xywh {10 10 90 20} labelsize 11 when 0 + } + Fl_Light_Button comment_in_header { + label {In Header} + tooltip {Put the comment into the header (.h) file.} xywh {10 40 90 20} labelsize 11 when 0 + } + Fl_Menu_Button comment_predefined { + label Predefined open + xywh {10 70 90 20} labelsize 11 textsize 11 + } {} + Fl_Button comment_load { + label {Import...} + xywh {10 100 90 20} labelsize 11 + } + Fl_Box {} { + xywh {10 132 90 121} labelsize 11 resizable + } + } + } +} + +Function {type_make_cb(Fl_Widget*w,void*d)} {open return_type void +} { + code {undo_checkpoint(); + Fl_Type *t = Fl_Type_make((char*)d); + if (t) { + select_only(t); + set_modflag(1); + t->open(); + } else { + undo_current --; + undo_last --; + }} {} +} + +Function {make_widgetbin()} {open +} { + Fl_Window widgetbin_panel { + label {Widget Bin} + xywh {413 185 520 85} type Single non_modal visible + } { + Fl_Group {} { + xywh {3 3 79 79} box THIN_DOWN_BOX + } { + Fl_Button {} { + user_data {"Function"} + callback type_make_cb + tooltip Function xywh {5 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[7]);} + } + Fl_Button {} { + user_data {"Class"} + callback type_make_cb + tooltip Class xywh {30 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[12]);} + } + Fl_Button {} { + user_data {"comment"} + callback type_make_cb + tooltip Comment xywh {55 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[46]);} + } + Fl_Button {} { + user_data {"Code"} + callback type_make_cb + tooltip Code xywh {5 30 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[8]);} + } + Fl_Button {} { + user_data {"CodeBlock"} + callback type_make_cb + tooltip {Code Block} xywh {30 30 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[9]);} + } + Fl_Button {} { + user_data {"widget_class"} + callback type_make_cb + tooltip {Widget Class} xywh {55 30 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[48]);} + } + Fl_Button {} { + user_data {"decl"} + callback type_make_cb + tooltip Declaration xywh {5 55 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[10]);} + } + Fl_Button {} { + user_data {"declblock"} + callback type_make_cb selected + tooltip {Declaration Block} xywh {30 55 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[11]);} + } + } + Fl_Group {} { + xywh {83 3 79 79} box THIN_DOWN_BOX + } { + Fl_Button {} { + user_data {"Fl_Window"} + callback type_make_cb + tooltip Window xywh {85 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[1]);} + } + Fl_Button {} { + user_data {"Fl_Group"} + callback type_make_cb + tooltip Group xywh {110 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[6]);} + } + Fl_Button {} { + user_data {"Fl_Pack"} + callback type_make_cb + tooltip Pack xywh {135 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[22]);} + } + Fl_Button {} { + user_data {"Fl_Tabs"} + callback type_make_cb + tooltip Tabs xywh {85 30 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[13]);} + } + Fl_Button {} { + user_data {"Fl_Scroll"} + callback type_make_cb + tooltip Scroll xywh {110 30 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[19]);} + } + Fl_Button {} { + user_data {"Fl_Tile"} + callback type_make_cb + tooltip Tile xywh {85 55 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[20]);} + } + Fl_Button {} { + user_data {"Fl_Wizard"} + callback type_make_cb + tooltip Wizard xywh {110 55 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[21]);} + } + } + Fl_Group {} { + xywh {163 3 54 79} box THIN_DOWN_BOX + } { + Fl_Button {} { + user_data {"Fl_Button"} + callback type_make_cb + tooltip Button xywh {165 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[2]);} + } + Fl_Button {} { + user_data {"Fl_Return_Button"} + callback type_make_cb + tooltip {Return Button} xywh {190 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[23]);} + } + Fl_Button {} { + user_data {"Fl_Light_Button"} + callback type_make_cb + tooltip {Light Button} xywh {165 30 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[24]);} + } + Fl_Button {} { + user_data {"Fl_Repeat_Button"} + callback type_make_cb + tooltip {Repeat Button} xywh {190 30 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[25]);} + } + Fl_Button {} { + user_data {"Fl_Check_Button"} + callback type_make_cb + tooltip {Check Button} xywh {165 55 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[3]);} + } + Fl_Button {} { + user_data {"Fl_Round_Button"} + callback type_make_cb + tooltip {Round Button} xywh {190 55 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[4]);} + } + } + Fl_Group {} { + xywh {218 3 104 79} box THIN_DOWN_BOX + } { + Fl_Button {} { + user_data {"Fl_Slider"} + callback type_make_cb + tooltip Slider xywh {220 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[37]);} + } + Fl_Button {} { + user_data {"Fl_Scrollbar"} + callback type_make_cb + tooltip {Scroll Bar} xywh {245 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[38]);} + } + Fl_Button {} { + user_data {"Fl_Value_Slider"} + callback type_make_cb + tooltip {Value Slider} xywh {270 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[39]);} + } + Fl_Button {} { + user_data {"Fl_Value_Output"} + callback type_make_cb + tooltip {Value Output} xywh {295 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[45]);} + } + Fl_Button {} { + user_data {"Fl_Adjuster"} + callback type_make_cb + tooltip Adjuster xywh {220 30 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[40]);} + } + Fl_Button {} { + user_data {"Fl_Counter"} + callback type_make_cb + tooltip Counter xywh {245 30 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[41]);} + } + Fl_Button {} { + user_data {"Fl_Dial"} + callback type_make_cb + tooltip Dial xywh {270 30 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[42]);} + } + Fl_Button {} { + user_data {"Fl_Roller"} + callback type_make_cb + tooltip Roller xywh {220 55 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[43]);} + } + Fl_Button {} { + user_data {"Fl_Spinner"} + callback type_make_cb + tooltip Spinner xywh {245 55 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[47]);} + } + Fl_Button {} { + user_data {"Fl_Value_Input"} + callback type_make_cb + tooltip {Value Input} xywh {270 55 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[44]);} + } + } + Fl_Group {} { + xywh {323 3 54 79} box THIN_DOWN_BOX + } { + Fl_Button {} { + user_data {"Fl_Input"} + callback type_make_cb + tooltip Input xywh {325 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[14]);} + } + Fl_Button {} { + user_data {"Fl_Output"} + callback type_make_cb + tooltip Output xywh {350 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[27]);} + } + Fl_Button {} { + user_data {"Fl_Text_Editor"} + callback type_make_cb + tooltip {Text Edit} xywh {325 30 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[29]);} + } + Fl_Button {} { + user_data {"Fl_Text_Display"} + callback type_make_cb + tooltip {Text Display} xywh {350 30 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[28]);} + } + Fl_Button {} { + user_data {"Fl_File_Input"} + callback type_make_cb + tooltip {File Input} xywh {325 55 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[30]);} + } + } + Fl_Group {} { + xywh {378 3 54 79} box THIN_DOWN_BOX + } { + Fl_Button {} { + user_data {"Fl_Menu_Bar"} + callback type_make_cb + tooltip {Menu Bar} xywh {380 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[17]);} + } + Fl_Button {} { + user_data {"Fl_Input_Choice"} + callback type_make_cb + tooltip {Input Choice} xywh {405 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[15]);} + } + Fl_Button {} { + user_data {"Fl_Menu_Button"} + callback type_make_cb + tooltip {Menu Button} xywh {380 30 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[26]);} + } + Fl_Button {} { + user_data {"menuitem"} + callback type_make_cb + tooltip {Menu Item} xywh {405 30 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[16]);} + } + Fl_Button {} { + user_data {"Fl_Choice"} + callback type_make_cb + tooltip Choice xywh {380 55 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[15]);} + } + Fl_Button {} { + user_data {"submenu"} + callback type_make_cb + tooltip {Sub Menu} xywh {405 55 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[18]);} + } + } + Fl_Group {} { + xywh {433 3 29 79} box THIN_DOWN_BOX + } { + Fl_Button {} { + user_data {"Fl_Browser"} + callback type_make_cb + tooltip Browser xywh {435 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[31]);} + } + Fl_Button {} { + user_data {"Fl_Check_Browser"} + callback type_make_cb + tooltip {Check Browser} xywh {435 30 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[32]);} + } + Fl_Button {} { + user_data {"Fl_File_Browser"} + callback type_make_cb + tooltip {File Browser} xywh {435 55 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[33]);} + } + } + Fl_Group {} { + xywh {463 3 54 79} box THIN_DOWN_BOX + } { + Fl_Button {} { + user_data {"Fl_Box"} + callback type_make_cb + tooltip Box xywh {465 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[5]);} + } + Fl_Button {} { + user_data {"Fl_Clock"} + callback type_make_cb + tooltip Clock xywh {490 5 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[34]);} + } + Fl_Button {} { + user_data {"Fl_Help_View"} + callback type_make_cb + tooltip {Help Browser} xywh {465 30 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[35]);} + } + Fl_Button {} { + user_data {"Fl_Progress"} + callback type_make_cb + tooltip Progress xywh {465 55 25 25} box THIN_UP_BOX + code0 {o->image(pixmap[36]);} + } + } + } +} + +Function {make_sourceview()} {open +} { + Fl_Window sourceview_panel { + label {Code View} + callback toggle_sourceview_cb + xywh {533 374 520 490} type Double resizable size_range {384 120 0 0} visible + } { + Fl_Tabs sv_tab { + callback update_sourceview_position_cb + xywh {10 10 500 440} selection_color 4 labelcolor 7 resizable + } { + Fl_Group {} { + label Source open + xywh {10 35 500 415} labelsize 13 hide resizable + } { + Fl_Text_Editor sv_source { + xywh {20 50 480 390} textfont 4 textsize 11 resizable + code0 {\#include "CodeEditor.h"} + class CodeEditor + } + } + Fl_Group {} { + label Header open + xywh {10 35 500 415} labelsize 13 + } { + Fl_Text_Editor sv_header { + xywh {20 50 480 390} textfont 4 textsize 11 resizable + code0 {\#include "CodeEditor.h"} + class CodeEditor + } + } + } + Fl_Group {} { + xywh {10 460 500 20} + } { + Fl_Button {} { + label Refresh + callback update_sourceview_cb + xywh {10 460 61 20} labelsize 11 + } + Fl_Light_Button sv_autorefresh { + label {Auto-Refresh} + xywh {76 460 91 20} labelsize 11 + code0 {o->callback((Fl_Callback*)update_sourceview_cb);} + } + Fl_Light_Button sv_autoposition { + label {Auto-Position} + xywh {172 460 89 20} labelsize 11 + } + Fl_Button {} { + label Close + callback toggle_sourceview_b_cb + xywh {460 460 50 20} labelsize 11 + } + Fl_Box {} { + xywh {265 460 190 20} resizable + } + } + } +} + +comment { +// +// End of "$Id: function_panel.fl 4638 2005-11-04 15:16:24Z matt $". +//} {in_source in_header +} diff --git a/Utilities/FLTK/fluid/function_panel.h b/Utilities/FLTK/fluid/function_panel.h new file mode 100644 index 0000000000..cd8c5254c7 --- /dev/null +++ b/Utilities/FLTK/fluid/function_panel.h @@ -0,0 +1,111 @@ +// +// "$Id$" +// +// Code dialogs for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// generated by Fast Light User Interface Designer (fluid) version 1.0107 + +#ifndef function_panel_h +#define function_panel_h +#include <FL/Fl.H> +#include <FL/Fl_Double_Window.H> +extern Fl_Double_Window *function_panel; +#include <FL/Fl_Group.H> +#include <FL/Fl_Light_Button.H> +extern Fl_Light_Button *f_public_button; +extern Fl_Light_Button *f_c_button; +#include <FL/Fl_Box.H> +#include <FL/Fl_Input.H> +extern Fl_Input *f_name_input; +extern Fl_Input *f_return_type_input; +#include <FL/Fl_Return_Button.H> +extern Fl_Return_Button *f_panel_ok; +#include <FL/Fl_Button.H> +extern Fl_Button *f_panel_cancel; +Fl_Double_Window* make_function_panel(); +extern Fl_Double_Window *code_panel; +#include "CodeEditor.h" +extern CodeEditor *code_input; +extern Fl_Return_Button *code_panel_ok; +extern Fl_Button *code_panel_cancel; +Fl_Double_Window* make_code_panel(); +extern Fl_Double_Window *codeblock_panel; +extern Fl_Input *code_before_input; +extern Fl_Input *code_after_input; +extern Fl_Return_Button *codeblock_panel_ok; +extern Fl_Button *codeblock_panel_cancel; +Fl_Double_Window* make_codeblock_panel(); +extern Fl_Double_Window *declblock_panel; +extern Fl_Input *decl_before_input; +extern Fl_Input *decl_after_input; +extern Fl_Return_Button *declblock_panel_ok; +extern Fl_Button *declblock_panel_cancel; +extern Fl_Light_Button *declblock_public_button; +Fl_Double_Window* make_declblock_panel(); +extern Fl_Double_Window *decl_panel; +extern Fl_Light_Button *decl_public_button; +extern Fl_Input *decl_input; +extern Fl_Return_Button *decl_panel_ok; +extern Fl_Button *decl_panel_cancel; +Fl_Double_Window* make_decl_panel(); +extern Fl_Double_Window *class_panel; +extern Fl_Light_Button *c_public_button; +extern Fl_Input *c_name_input; +extern Fl_Input *c_subclass_input; +extern Fl_Return_Button *c_panel_ok; +extern Fl_Button *c_panel_cancel; +Fl_Double_Window* make_class_panel(); +extern Fl_Double_Window *comment_panel; +extern CodeEditor *comment_input; +extern Fl_Return_Button *comment_panel_ok; +extern Fl_Button *comment_panel_cancel; +extern Fl_Light_Button *comment_in_source; +extern Fl_Light_Button *comment_in_header; +#include <FL/Fl_Menu_Button.H> +extern Fl_Menu_Button *comment_predefined; +extern Fl_Button *comment_load; +Fl_Double_Window* make_comment_panel(); +void type_make_cb(Fl_Widget*w,void*d); +#include <FL/Fl_Window.H> +extern Fl_Window *widgetbin_panel; +extern void type_make_cb(Fl_Button*, void*); +Fl_Window* make_widgetbin(); +extern void toggle_sourceview_cb(Fl_Double_Window*, void*); +extern Fl_Double_Window *sourceview_panel; +#include <FL/Fl_Tabs.H> +extern void update_sourceview_position_cb(Fl_Tabs*, void*); +extern Fl_Tabs *sv_tab; +extern CodeEditor *sv_source; +extern CodeEditor *sv_header; +extern void update_sourceview_cb(Fl_Button*, void*); +extern Fl_Light_Button *sv_autorefresh; +extern Fl_Light_Button *sv_autoposition; +extern void toggle_sourceview_b_cb(Fl_Button*, void*); +Fl_Double_Window* make_sourceview(); +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/icons/fluid-128.png b/Utilities/FLTK/fluid/icons/fluid-128.png new file mode 100644 index 0000000000000000000000000000000000000000..cf9cf406e17201dbf7ea5edef85fb910e248f539 GIT binary patch literal 10179 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg4mJh`#x0hCu?!3hY)RhkE)2#DGa3FLU=qE} zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns}TW#-~GmbGPy1{uRq;u=xnoS&PUnpeW` z?aZ|O3=9eko-U3d6}R5bEw2c1y?&s+Ji5&Mrmyl87NIKlr5+RGSe`ECjM(t$R^`?3 zK#{4_1iDzO-z#t_E$F!6*wxj*x<ve?kV6*N%H7uY<%_r9Ih(hM(^Fx>XPfUg@9r*s zer}HC^D~y|Y3CY?SQt5616zLmz3k9h;u^AH!`azQo~L6u6dC^MWODx#vt#Jd$>jd> zPJg8~W5LudtUKRrzrBo;F(&8|S4>@Ohu+1@D_5@Ecb<FoRV^=*mb{GL)0T-Ya^e5o zv|Fh@MXQeg{_H(Ydl)}F<&(If@<Do1wT9ONuBaGw2{ZPINe(+dhp)IS*kD(>KlSB1 zy9F;2{(H^1s(s<KpbEDlOVdZorgr|WG~s8RZ`*~R?oF9~qg2K5!-YD>P2%!h=MOXR z81_8+T$sPeN2{U7dBViDiuYXk^C!nXc;~q3QAk6hO7~H@f0nx>=ll%V%bGHuWjb@; z`-Tr$o48H&K87(!G?>kcU(WB)8+Om{=HsX7Axh6#TKtxOp31Ju+<o+sw~gxh1&+;Z ziW3V0Dj$?sEe)6v^QF5f?7}kN*%P9qwlsO`P5gA&a^nlGDM}VW(E&pJLSEdzcFMoA z<$g5p>lF#9Z|(f@av@?XOafEHT|RL|rrk^1u`ksjQeeyLrW8dr-Cc(d?^EG++$0dW zGfjWBe-Z1FZpC*@`>r3j$?ei#zF+*#_Or$PDT*^*2t=uT^ZF~3@cCkzhVbXWb+h>o zJeu9UIjP=%gUjNcsD7h2%3n2Y_c0w+_Bo=$s_J^+qVI%C37$lO`+P0jeYwoRJEjQB zwP<K8;FuKqpvcM5tmURtx<ur`$b&BPFWzB2vy#KoI5codLvg=X`ed)5nd?M&Gg3E3 z1OzR38(px>;cz`e<<s6q+pn*#a(6IJ-Q+fHiIKCW)Pi6U-IrUcqd#8`yeDx&)~X~U zP$DDr-Q-w<AAdfd_cpI@U1jiVf6Y@n&CI0|+AW=|qL*Gvu4cX;zcI;mX2Riz|37WZ z=S-ZZ)bwh>KCZR=W@^(*ysm20#O+=_rK$M1&<tyXCz>}O+B<Ie&2F*PzwZA3V1byY zhxbi=@TF+sj3o!=J-v{^kX6g{WB(#41rM>R@29_>%c<NR7QJuB^E$cz2^=b0ri=dn zyZ6tX4~jeHbX+koh!ULK`{8<yTkI#D`TwpQTfF4-N%sSy$<uyZYCGus(5m^+5vJVb zYVC_-_A|_KHC}P^dc>UE6TOvfD?k4-%sQaYQ1ju&bCVT6*}m^FVmcGZaAmK`#Ov#K zPPPAj?fQyK3}0%);!buksA;@<GVzV|y_^0~8}99%A~rGmW|AzcoA*zHZRbmLc0@eP z5t)=Cf5x(5dc&HojD`>4JO6HZCUiAZV`&WE9qFY{{$89a_W$j@X;K$&I<1seVEI$| z<c`2XjWmuaTn8N@4@R0NT>bax?Tez^1BdTBzMeH<(<d2Ig=0*w`wuL67wQsW=q%9n z`P=4CS#SQjW*%4lx@KBu*1ZQu4@G@g6}sB%N=HDuLyx@uz6)nHy2HhGEX=;XE-$HM zYUugcgMS$FUa#m__~T2?%?;8Uj70P!-$zcE$6hbPW~f=RO(&1TM1Q-_)XN`cHXUNE z_tvg?e>;D_ZrFXDOGcaG&3fA7zucPf*{u00$2Nl(f#xoIeXG97G;CDiEnu=*zp73w zZRV;vW_f1wb|V(%+IT%R%^I@}?C$RF-rgF|OA<<agC0DIJOAGN_dT`ub1k2lozCN$ z$|kluK2Iq9$MXsk=jZ31PYvB}kRK}j(uSwy6#KU9w(9z{TC+Fnc->ZeoqO!O$)4qU zz1rV}lVjrkzj)F7srbe5d)58_UjID*H0XWrX|ck~{GDstCp~$uXv``+S8n;*TMU9c z%s~YvyN{i9{`C0R(S+4Y&+X-v-1@?mPp+G3u2=A(qmOd`Rz8`#km1ko3Z}Em>vaEj zuj99xd(9%${ltF8!;DKe*fVtaOxhRK@S<vu;S)un_mz^@zhuP4Twy-6+IYv$>o)%n za~u)T&XuoWS`;GInJ3Voz<R*;AMcFywU!I?q7%B)ufDyz^Yv1}3H59ZY`h{Ota9^8 zrJtlTefWFiB}0zQm5%gk+XL43OPInPA2h!EziN5=rD)p+x*6r$mwosDDs%X@d}y-& zS@(l8x!JF<?mXjM6soPo>GzL!tM$SCvmNuN-1zl8yd#@Wz0B!t-=)K{b4*)>PKYY2 zc^=Uy|Ifzx_LRT0XBgAWG_F%Ok{_ICj@qhq#OfTsnwmDltRU8>{K9wR?gho@9f-Oq zxIwry+0)Ojk3+OZY@Yhm^v67+4Gm`<lqa8TxtVj!KvHk5;{P9?JHjh<4zY)<;|>tb z6OW5>KKH4MDc8yPW$e_stlt=v3=J<j-#e-OWa`xTHI<qTx3#RfH5jbqm#%546G=}^ zXMEV-@Ofpgs3W7EJh!F7l`1}=D}VXgjS}yD=yG;&4RFwHNIN^L^-sh6*8P8*CNQc^ z*34);+%K}v{Mc{P-J60NBo|~}4qAP;TFaQpCy$GRn_FA*W<}~TK`qTcFXo*#Ha2$6 zOt`SXao?{4zEf9zW)djdz4rv)x;yGElXP6x&s5ZQ?fX2J_1f;|fA8Fhxpet*v)C5@ z>Dn>5S)R*_c5i>MGrsvY>*02O_MLZQrz~w<F(uGe&|z8ht>;fg^Y_ouZ0N|mU?SG{ z{J=_?0+G$xX4=}^v(G+TttfSlz3Bc^wTo}w<OGHlyp(ow@tOQw=+Di?g^!Qz%Sp7I zE~3D|!^X_Y+88?_FFXH?sDRv}$EVF?XC0}ke{aD!(_h4sm-SUoa3V(p+ZU#Y&1t-{ zRwWz}C-S3JnP<18aqPUQe269T=Y|hf5>hS`bMEdkl{U-KD6RL}pS<i@YQg(oN!-6* z{dmguKd<e&?QS>Yh7+G=u<rX_^6%UHt#iwFz6gDu{qOp-%oBEcwm<q}PS_uQ*;8*> zva4nD^u-R>9`Zc8S#G6ZKl|6U-Yr|!H_mV?I;pr!u^~1${p=<uhb>VLr_NaXq+7^( z_j7f>-d?9AFMfXfZL{l$zG}J`)5G>@3PHLZD+TA=+{*XK`Tpsv%g=>(ga})n3@mt2 ze&YPc`N9{)=eYUsrhi{NeN*Mx#I1FV|8KKCF1A%;n^3*&*afi#mJHwjaBhwI-Lq@5 z`S1IlQ!MB1j^8P$lvQ{)z54;TaOHbfh6z9BzZ3|KUw6?`R$)%jLeF%Ty>aXQbEs=n z{k*Ljv1`5lsmU{oV%6`xisdiad0-~HAA5R`FvAP;hm0L7`4h|Z&7}`LQLq(ezj^%d zm4n>;X(2DWE<9wtAhXvq?8WU$MFsuI)mCR%9?V_3*D=4TDM!jJ@A#7Q>gx|2IN0QU zP^^FB1B;|hf)lgaV&fgZ8D4TbuB;~gGFyUOy{tibzTVaSE<R=xO*O^(av0JXH!f4| z@Z^eq=hd`V+aNVh{mcaY%1`g_CHS+{HWb#pnW1kwhp~=Rl+pgtw<C5lIfXwlMQYu- z`Z1Yd+W)H_pAuq>HyqjYTCh^&MA6&XpXwr5)PtT_?wsdu!*Y@L#r;p|SvQyVe*XLI zT|zhe+==twNh>Ws_&UD*gjLV`pFGFsuQ+-?vv5nrAK4XmCtlVsVP0@g_VSfqxd&5s z&Xy9o#T?_<Aet1<ViLmr<w(Lb{#i;*KPqDO*gmOasPe61Qp#?&>&c#dZfecu{c4Bi zwdmQ*l6WkblNg!utYzb)15@wZE4Gy9*&SZ?<<@kCZHy9YV<N-#Ugh1A?%$xExS?fo zRjL+4@4w$XM@*BSm3~h)e5S<m=5!{fpy`v!-H#ru+gk8k>V9O-W_u>TRZ_A&mQ0U} zyVk7tYcaW4e}5{+#8SmQRvKK7t87>ux|b;5@O`;slmF$N+pe_aOtZ1uSugco|Fv7` zZBK@6`zA8&d^usZUsnE3hYPFXqy&%g$fR%jk-LA1+Qt|5HkZ?R_UEmAtLEUtrv4=L z#NqaZ4sZF20<z=SE;zZmY-x(w<;BQ4sd@K<*)I911&e>$Z2naL#BZhN48{1ox9cuP z%5u7%Vsl@YGsVtlouqcxojdQ&Og?l@K<%_;=(S7jo^oPN>rU+AT4Hl?b=O?u_&BTP zJ<p3yybR1|YTj6~%Eyt<XX~^xs$~x%c*^@LX79ee$M^8Y;vedZ&93CKOv`vLSL({S z=jxq=Nz?UzaO=4;F24EJ;nJs#@6QR$wR_<=al*mny<8s*KFBc4m20ds?z+I(y629! z^;AK=waw+$mEUWB9N0c3k9E6IoZkZ3&;Zss+-`Lz&PNr$XAwD|`M^BkY-`Jtp3M)g z9-X@PvvPB(U!chORx^{%|Di7(8Iu0~`l|YgGfaeO3YU|^i;J8SF3R$-Ik#@v=ydng z>Tid?axa<vCO~b=D!%*ogLd56mU~-kjj!k~_Z81|*7qA6WIO$hZFvK?5Tl~G*Ye#4 zf)noCeJyJ@MY3k@frkYl5wo>I*nD2_-F<!NQ|+ba|2>u;c&Zh|7V_g()OM9h(ad%1 zk*T{fQX1mc@82O<aPd5o7pqnDx$duDPv2{~yL`#1@(LeT|DDfwecqei=%_yZu=Md$ zp${jmI6GC2@%5iRTelf{39cF<**e<tmo8n>lVg#QQ})06&O*^%JTCmkq&*8-6LxI; zuyW$d?ikUub@SgJo3KMeaKh}_)gMnZ2%S3N#eO=(NN=Kj!P{F~_t_ofo4WP$_g&V4 z8XTF02?i2cd($Hr9&I|Ur+w8gu>El0%Da!xU7E1ZJ|!*fmr_DZ>dQUP=Nx!-b#?cf z2Xnhq3tA;zMPA?AyIWtVYTo;xZ)Fc`8y+5RH?IHp=YiCXlpQ{IPgPj4zdFuRHj!DP z*Dc<DVUeA(1H+d5`}4MDUl)tqaC5c5yUm$L%sG4w?V4=3a+NLZzc8E^5WQYGA)UpG ziCbK+q@GvV!DB{oZ$s>gliXqJ<76)}`z9sUTg^GipTQ#9w9vWz(w@rV@8@sMaksXq z+R=LD&CSi;Do;0mdaC&9)EfC6=0V)E&xWNfcMW?d>@;0z{mD8GtIAJH^qGv#nR3gN z)}K6aLc@4X+<u2P?wnZRxc{-zn{}+LW<5PUeRut>b769Gc$w<ld;e`Je0;2dHSFzl z_q3+DY}{;|W^cbg{r#t6ojbpjS<VY>eyh+e&QJIj=pLBtZ|Au>tTnl2`MMU?=z}ZT znbeo8Y3NaRTKy+r*|#O0E)AC*c9*^Vbd^7BdYPC0S!cCUy<=&cSygLKhhzvo|GW38 z#FLg4XTHsS8*9aHF4k)y|2M%mQ)8hCN5Rhd#pzufEGM-W<m#?nH2KcrH%mX1f4=|x z`t^4O|7F}boxP`tFxppr`KWH(oWDHWaeXse;D+BO7N?CxP6cnAP<`pIHm5~^oYMzA z|L4_9*<S9MrZh+IM&+hC*8CrSaNgf|Cq8a-gAHrOh8>STSE{Z&@vJ^~{?g*F`KcEU zHpyt5SlCv`FY@FR?=?l^8QyYJv`%pTnX_wc-1Pb9KD2FC)c3agJRxoW*=3vD8p?T& zXP=i-Etm9nEV9tAuVc0Ee|5gmU0QirgkbQRGxBCEM*lef1~dzFh}b5rnwoXf{xq{- zUC7sn<(U@h(S?4!kAAL}YrFjWiDdH%l@}JbV%Mk|EL<b7;jnXj|G(8g7w@v{_1wFB zl2QE*^-KR3ESEc~nzA+dp4<w#o&YDe2KTy@cT<l){Bz^^%=z-l+WvB762Jc?bjEz& zICJ&9_9J@l7EN~EDBk7lpufP7L3dsA2MgZ)`8(s~GCk)R3*?vv9+OFPey32<mGgDi zUSCC>OLGg<SthPo&|}+I^gOHYQq(EQ|6;F7Zk+uj^XN{zRkLN#JeQ9ZDs`V+f9%@q z=+N@&>eS=G>*g+(UD;%_s&#%qYlElRHKA@@y;ITWWOSXixTf3iMom!eKgyx_^V&px z{qM&D9x^3cgk-Z7`W}2@C#Yt#+;i=^#rJ+4R(d+qajuYqMpfF*`QF_PJpQtE?$7Py zs+5zuzTfDaVc(SY?f$`uhcEwK(oplVdtO3k>g&U@f|_hDt2hmhYE@pFs9kAm>N8LB z%z35qIj+-YCnZLGzi2dbQrDY&w=d31W>xI^96QHvnsm>!+zg&;5t>u}MxK%3efzHT z|0|xFxF8mt&sVJ8`7E^0pY>ny^7Mb=4d&BI9C!ZA-Zpm+OG%YmX+`)dPI+GDY@W06 zzl0T2LN7m$=dF}{(Q;mG#TVuWMG5nsNSX$vm9_uL5zs5My)a?5)PIK`y2TQ|Z!$}K z4Z7Ad*HT2s@ZRCje+CbD<0}nX6pp`UR(udQ_4~q)4F}p6d|`X{-io^+eE&P%iJb}l z7fjS<XBlyJ+-tG^e`81gy2cF}X)%9Q7`(4-ow8;z|7Dxm&o?!kJheABetF^>xqZ?1 zn{tv;7es7Nt6Z>C=H;R%r{B&J(XCvl^nll4-um4iPcOK1OH55O`E}ygH|x%M^s8hp zle3j&d?sNKWvF%UJ6EyJ3}wl?PfZ!*YM!%g2xH#c$;Wvq#ir(x-h9&;mB}BP8Di$z zNGS<#bp7Ge`Anm8&!ca`y_bD%cXv5AlpoU5GHdv7^QdUr<R<UN=j*C`&Ru=a&$?RW z{FS(q414~^s&n)&F3o+fcEVQu^{K#+5})_V%inI4Kap;&Uir7{kP!2=teV2lUm5m% zEfwEzq)CzG{)&rCXKfFjWMgJ-Qhd;Hd;M`)*WX{OuEug5xSx4-iAos1^ES^P+ztHU z-xk#U$rR9&d;QIZ;rrfN?uewHU)&_+HXK+ueQ}0CbHT;U2emTqtbgTp+3NU??SHKq z*4()f@bs&J|4dGKez)|Et#u{ucm3R_^DR|@<&V4qb8Osi%`2L>R{e=r_dKLo%zmPI zveo1^t)4`yyo}GPPv(95P`|Dtp*~AKX#XzZhUxoXoZDT#SI1ddyn=P@$u;Q--AhHD zc*iPjY%?h;>;L#m=A1}Naq?|dqZ3WqF3!%@lR58KZqic_&GhE!u?^g_Yt|Y!JGoDc zSKcbNE;y~Y+%)0rxwev7hU`j{1<qglp!BS7Y0s<Qw)*k^d!}q$d_QISX7QHm4nEVL zuL#S}cX|HY{#Zu0+W(zyak4M_<_o^}T)D3zHk)n#XR#w@Q$j?vROj5`)vvbkoZT4K zb$nlViNVSpva^C31vS}P81DAQJ0yi~a638igio{Z?k6)JzW9~UJNeh2k8dBGV2sY~ zSfO`1Rd(X6)DT<A1jW}JbACk2t?XT=UupAOV$Lny*W1)j+*JD8z#}Pl*WucF{e{8V z_Y7`4E0ioTu6X|Yjgouqvj@>T|4x2x(C#@&`rDPiM(=i>)LMPvrQ)J#T319)-nO!R zk(Ba*_2DGh3zAE|^sRbrtFl((Q>1s#n$rSm^S2&7UF~!tUDP%7c<revHy-c0AbUf4 z!F2IjS6PoT%N=XKy8qdE)9w2->yxKUKmR<oPhkDr-xsAF<O4m*^+gh6#KV5nRyjYs zc;zLx{c8R0+So34o)=EF4_>C08$Z1@bIIH-$<klfUb(vVs@8kOtk9KT7b)$OSngV9 z_GC^7uUNO$-<ewJ+ta_c?X_p(&}UuJcCb&s`vYtAQiV;|rzyurTK|8{QvTf0cIK_l z?&ml5yf3|T|Kr43!P0-_s}^vrTEM0C-!H~qJkNOnZ$alT$@RB(2&PAFk9IxfxXya5 zo7(!QI9I3VV(XmPcx<MB&df@6Td;7F@By_a^BmVk1dE(WGrqbyT;0xYo|tabg>|vk zZhbP6K{cQM{HfuSu{iMT?ChW4@7H_!`>X5f_S*mZ(LBFSYYK<Wt}g!bx;|f?dd&4x zKPAlM(cl>>^x%%uq-$T7e0{g(7Js?kwB?i5x}DIQ5WP-rFO!^}<DBdUP>1)F<+~M1 z4aMBEK3sHLT<%hRzG?08r)h_;)qR{A|6f*ZUBgu6ZvNDVZOO;`SgkI;U32Ed<yZ!m z1uvUVr?+Or&MMozR$t}DlXJoU-)?uE<<ls;e^D31IrZJw(kF;Cv2V7YqUry_eaeBQ zuetX8iCF3Tk~@*h<ICT~tyQ0MWaOBy*D%??nYerT9jgZKhO;3hyV@KCROUG6i89WK z?)dsQar<rC`-giE@+(YZ>yxz>d-3h$D$NIXn%p?G&tHgkbo%vT6~}`+O=(9?8-IzI zFu|=)i)n|4ii3dag#cHEP@x50oNLYqC0wn0VaomJkfPn8*>bA7+<hqrr+!^(RH^92 z;5?OO0^>UU)eG-FSgvs?Qbb<S|Lw9hEo_aQtG(DQjwgKoD<~`+oTtw<$;fPb7sEN- z45KyI)<$nXBC1l}Zr|_me!=Za!cPDGeeU?8-m{a*$e4MTXnB|~<8!eo0y$rm5}nE` z*WOwmE8SsmaPQka+HGA$in$AR6>uC7ZCWNLBqIJ~pHi}QxG&?v<}_D(Bcn}s;zSx4 zSSEzJGCZFsI$_F`kUafU=g;$(RQroE&Qa$|sO-+XKh;hC@8iT(59aXvQDRbA6}=@R zaOXSDH`mriZ%B3vo$aj65yklPU-N~n+2Ips&(=OAEyLID;p@vgjrHT_RSz}eC0_TJ zEWW65ZC$LkmK2|yjYibA9LWxjIyH}wX<8Q66ZfB&zbPmv_-KCpKf&ih$9g1%J2+$x z9PoPXV(IU@XXlB83HRKzxjsKT`}kJ&dfm{a^K&OJ3|^!g;M?0$V#D5-?)=>9!(Cm~ z+j{%T-^bnBmV0_-@bW+Zz1X7|+E;Nbcyd8Xk}Fi%Z+FSdLzk9%J6k;z=8*f%Xm^9b z)A0`L@5`!+DYlVDN(>R3QaGF0c)3zK_b~q1eu{@jwvDm=7vH{%87X&nmHzp1*?*~A zO+$Kk^-ep19sg%<-1VfCU&5dvc6S-;C)XY&hdJxCm^655Cp1cl{kXR!Lg&qmjm@X^ z_y1WFZ?ITD$6j%B*pI_6Wq!^-%QAV_^mYH(c%?Sv-?wYymw)&Fdcu=?t-Du;>^fj@ zJ$~k;*Iyr<*59vFd{kFEzC+u7%FpN;{o5vrVtKl|zpshh>^9@<GY79n&sIJB=2R=H zD5b(HW#SQ|@!{3#^=#Hr|Nb0Z$708_=Rtk(mlqdp{{Q*>Ty$#Nu3R07H~03=KG@8@ zIrX&I|NZ+M+)DPY;8-yCmBGb~Vp;35C)eZaZS{{%sVjPzo17=WWG2(vdAIwztXq%7 zLG}4HkLqu)6goJm+mW+|<Hy<Z52aSJ`Fp>HooKFK=8$&7V2RV)=L=72f4V$@>)Xpq z=j`)E=k6^2`LJDnLxjn)4mru=rqOeS^gTEeShp!0-duHdUDnkbJB!sXUR=0->5b*i zxw~y%Kj**6y5a4PE8pZ_hLrXC$7=RZzTU%O!+OK#lTMOn4Li5E9#4v{h=TIm|78mW z8boI-p5-Vt!?xPY{C><Qo`8QlEB_>(Hmum={nB^mqmsr&+j^&pTw5RSf4onY`K_r3 z<0Nfs#w|?$4&-0w>x_MPO}?uyAev_e?*$9Dv=yH=^aZD_KDjnWdTT7}hrs$9n@uL< z6{tRy=v`yOd0=wbmDPn35BugTF07sUQJUl5Ke1;#lUM>Br#V#$G>HC?Ua@p%c2~pi z?WY@dA9UdOTI6XQxg&bT2^LE!(U^?n;uljsElt1w_fglQ-0&Bo6}Mk|iY~qvaAn(W z^DTONB+Y7N7BE#YYM)DIis0bU{n9miUz1z7xFXZsI~QvB&c}VV;QVG{7iB)7t?>8D zkb33&xvvjxdG8)*t2Oz^jKx>_@A^;Pu|G4i*m~o&$sy9)8+p=8B_sB13B1xRa$fIP zx$o1B>x?aC${wxd4*Ho@9WVLpUdGgiAG>eq>9L&uQaR<-L-!S;g)^+aHDBqqY&fbh zS;EBk?=0EnQK#-GyRDWIh;6(R{J|;Kv~?O=9rLaE`78nPvVTsSl&{|2ay$H_!7s-N z)y1p%XWIU;XOOXy^!|JC{bc<$PwES{s{5Y%vD5s+r|-=czpi=csIA{*lK5_`&(Bx( z3G0;)e{a9JmqTaqLHXO2R{meFs`b1!&gDA&End~Ref7=4CZWdDtmkS@oPMyKz3Q^w z#n-I=5+cR(>YodCtP$R`ZfA4i@udGz#SMBVST}EO+GHVKApaq2;ci=X=kJ`ZMSp|$ z%BSaSmz)><H|W@e`Rf~Oxn3Why<^ckt8dG0TKvdYxjQTG63@R*9_`D|VmZy4&zxUi zzOwSlsjwBcdy7oMp0X_7z0dWRBsc%QdhXL^TPLw!a=O{D>N2C7-umsn#y^}6JeKE~ zD0CzvwAe?2OZZZU{(}eWKREIiRQ}2joch{6@bb=i+?*E}BU=A|TfRfA;Qq5D%hmPG zM{7!7o6d`t*L{CLcfFlL@CFyPlQkw?acU=uMK}Ce=lCV#MeO3epO?<Ad_UdM=y1p0 zzEietx&1Bm{!<w)X9cbhh~qnFuWUSvbNQLc$wA8*=3cZe|9$@ZyPfx*J~%$H*0!^r zAx-Da*~P_q?Juf~8au27BLXj<+*J7CvdRD5%O_a=>kD7PGJ`+ER-#KTFM`FFjU}{c zm-@N|>6iK+6czZhuWg(#dAa(}U#<da&nK@{zEQV}cSg^G?FKtemd`qPziffpd)@b} z6Ag>13}<v2ESsG0yS*x~Izwi6_p(Ck%*bNt&)4`LY&9)k{dqO#YR&fJR`%NLVHS=Y z^P>JS>{Pn6+L@!V(Pq)%zKH@K`M)NAyRhe28IPCUN&B9uk}*7Kr5{A~y?4vRTz+Eg zwzYn;U+4aX3K1JN+IyRoUgxRH+t=t>yndofUgy-6+nEaY+kctI^|k8Yn|-Sm@tnAO z;`ju~yz1%Zj1i%;Lsqw#Nb)Fm-F*L`Y3gq4jYZMkY^D(oXYKAac<+C|=Iq_|cQhsn z%Bcqz&DeZpi?y4-pOJY_W&MmZkx8Ab!7OFPY_URhk5*gfU72#bPGjD6u^6sx%voOZ zJ>uScS16CQyBz#%>3a4F)fwzJgcSC$Nt|_&xb*Y=)AgUe{P(?j<$Crhk(uHr#q@8l zxZLcmcyeERs`BrP3SsjEBfnIuuexhJ-Ddh!vC@BupQlWW;y-`<Z>pJ1w~t!8;+ffO zTOx8-o7+reoX<BsZL$C7kcnl+Mw2RM3ONMi%e{Tq$e7<|Ag*;uK85G`!h6Lg^?SdC z`gdM9q0)KBU^lzw_pSAF**3;qzrAU{)aS49)15=sJW&X?knHpLmU>0|%c<zJJ6g*H z<_dmMv%324(24s?7#P?MJY5_^LXCgitW=Y$|NsBMqkv9dek<n4a~YpvZk4#+|8sB7 z(|R?hCBa_SuI+vnKYmSP{F42o^g)TdeP8JATMiW_H&!?MN{2jhX`7lZ#>-IMBl6oV zJLArJ!<C00KFd$(yP2L{F*$eDX3YX-#XK+GR)$mOW-ot{5n8NmD_ymDR$AKZp9P`j z9UXx??cLH?LrZ3yc(!t%@ZTN(qb%=7Cml@r{$%Z}OX1e$`~J9=*V$hXTJ-3EQ187J z=?8speZ6)3p1jjKAzk)E&LvemUW}UIc1v}wi+AWO7K)u>Irnb=7KLN4?s8N;ZE26( z`Z=g0WHR^693SZ)6PC?WPvbo(DyF)5{w(FIDM?FXCL6n+U|D`o$0JXop(k3PIVOSY z-1MV+9@Ql*PWw>mwj+D3$$PI?r$qJS-h5dl|GoV1(*6l23|u`}y)QNvOuS?~vtxsf zyz9pzGnt%4O8Q(qX#piA{!!;lb@xcl?_1vf`GZfX*TyjB#Z!-NkMrO2w`2L4zUHfy zZ*SLqs`p;=L~AaiK+oGxJQLH_|NZ-L)3+SEJ05dqDP5E-$@vv;efEL>yvy^KM&I_} zOzUPZR@uI7=J5s3?pMgxW?rpG&y@Epc$T66eg4{~MYoN1JS_fSb!Y;6_<BuVMxJ2J z7gL=?zF)X^X=hREfjpa&^|#JlyHi(K7=JSIna9bWR<;}+#`1|d+n<}HT~0P$Kefa7 z_zA|~FAs`79lF||^-AXFqg)H$Rd#}D$v0!KU)X<=f0ohW`?7lXUp}jw%NelYmC?)# zpEb``A3rC>ml(L}Q0CK*dFKPIFG-tz30c-UrLtMIG2*ep8NbgvWY5T~yZi6^lQoJ) z_g7iE)xGLTonEo-r9g!d^P^e6qbuht`Uh?0o62y{A@9_eP22tW&Gj19jl0X9iXHy@ zy}aV?<RqB~&GJ@7CcBr-;=R7iOGNfTQq1?vc~=%Q<k#J8Jv`HNrP%9~_*YX+`tS0v zroRX;H(dMJyy{f#x6?~&wl1`tu{d+)jAI|Ci0#?zwR+c|O<U#e=VWwS-Z^u=|DNO5 z4~vcN?^f>bv{e&M`>;%^HrLa<FXgI=-nD~`ntL;)Hh1=Iy`J$Zdf!Gty}hnNOD{Sd zzm*+X=pKLeM&8Z%$v?BLE~vZ|(U#vEo%Qit&C117t~Q1Rv)tM4>cuiQt;~FtU2~=D zPev<dZ^qoHd(+GheAt=(+JoJlF|%Ja=ychY!;v4ipMB7=dF7U;xgWE<Qe=0?$Vg3I zA$aq&naM$!XDX)!UH@Ode;{>3v*w(S;rpCkh5A>YdTS+ee3JbwgH7M{b$%@7FF!x? z#E;eY)k-&n2ma0WXJYq1a>?YQ#oJ}IF1xhjUJ1Jyw;wlMy6kQI+3K}o?CP5yOZ<7J zy@TiBor<4Ac5*AX`b_(Gb<SFMsY37RPknxW^E-1aCWw9SyRY}(`LMViU$*7gosS<y zLMN@vT<~?-rPquH6~2q?xh&}ShUbZS2G^h0t6B7PQ=GM`EZ3W8HVgad9lVgnZQIOm zQ1>mN@5z<66<POuPIaAgo^&{^{zSF&fA7gs)gIQ8XJ^Iw&e-+Bs)%Q+!W|veHqEA$ z+Vc;{O*=RD?em1~DG!~_-%B=KQFc8i=2=#P;m2FEcE7xuV|!QX-?5d(57+$MZ7BS# z_d!J6q$}6fKAcqj)$P~b?F};zzk52V<*kgR=+RsIr6>RT`SpoZmSc<LnTcm^mRaBT zdvU(!-{YOnCM}Kd+1WDtbL75_g8b+9v7ZTSX?H&UOZw&Y9MjC@Nf8^Kan1XkW#Cs_ z+OeT3IRABTs{IcI&Nq#+M$*sjIPUxJ!tCDY-}qWILB`<d`3J3ekG=M1sl~inx^51q z`0Bj(uGgzB&D>lRoLuE2qrZIeid{y_H&p-oUbre?g0ioy`?^_m*I#VrNS@@<HDS>f zg=pQ``kf~dzU_(-wdH8PKKpr*mtf|WjMExjzwX6ooS5{U|6ANc7Wa8)>S8D8&JQlx zq}S{^O<3<{nS0-L8Plkz)n8X#Ub*NIU+oS4Z#D1h%bON%&|ER4?nA8Kwma9mo?U&q zY|m`_8Rw3_Za4gJX})dq{=D$os%1V?n)Cc8NbSA1CiZBsNN34j$D*#Zn^O*XT#i(E zboOG!wF%5qP1~yPZhmL<uk>Z_C$8=f(@OQPXPtVLVi~-^sx~cL(CN1}Q{LZm=J{Ke zZ%>s_@hbW!->&yj;J~b}WqCQD^yKgU(^<Y*dB?NXk85t+;!;vxntpE8F2`mwXV)|h z4sMefOErTpZ8|zt`=s@0*(FVHtuwfcUWawDy*#-tNPqsL6U}={W@cI0dv`g`b&SjF zGrSqPd-t4Y`?WZD^slsj`76c5@t{>;!&l=ByDcIt%a|ueF1xnv$cf7Hn;$Kk{Qor% zW7+o*$DM~a75;1HpRksJ^TgX*6J5Lc=2xz}Flkk_by(=k&+B~xZajLgD$~M~p|ENl z_pejzzu1acGHbjJ_*MuT{hU0T<3mm8%+K3>X1%(rD{|<`f5tZ-N<Y71;P7BzU|{fc L^>bP0l+XkKbw6-q literal 0 HcmV?d00001 diff --git a/Utilities/FLTK/fluid/icons/fluid-16.png b/Utilities/FLTK/fluid/icons/fluid-16.png new file mode 100644 index 0000000000000000000000000000000000000000..5a50222d456bcd18c59f444cea7ee4bbd8d990ba GIT binary patch literal 706 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`#*8oLzcVl}uqAoByD%6t%w+g~fJyW= z0|NtRfk$L90|U1(2s1Lwnj^u$z`$PO>FdgVm6?m%#L~|}a~cB!14oH#M2T~LZf<H` z3B$KD)AlnkFj;%LIEGl9?wxeeJ2+70xc&EcyY7mJh~D<l&b;wTu}agEX*1L6wN)!@ zJ6Q#j_s-y-8lkaNtWi>M?+<>Ji3-=87p)UHHLr(Dv|U3jt=KCqc+QJ;`{ma0wd(%a z_s8P?=f8F5e-`o0Si!QO)T6~>j$b;%h9jMyb)RixT5)_<oaD>Q)g`{ukFq{zFx~g* z_g_N=Q@@Um9-nhu4aeqgFsau{PN@=4v8=w)bNcDNjFM0mkNXd<oNW?rZ7+#sUQp2- zd@cQCqj<2by)vIk_shtd|0g<1uV-+zuRkaI@wf5s<=h7&7)_7Pxn^=B=&H|ZhHs3` zDox+FdX$!Koxr1{<i2<NHV(7x7Mu^XOI1x)FAVTtJEW9ctfV*n_2X%?UcF>X?mxc# z-1-}ySH(QHyK;m*na8-xWYe6x*YlsPs61sWa`w~{d3M&Bj;mIsS!Lc?sbwRu^GSu< z?I*ooeMAK=lw@f4t7tEoHm_9Qwo-b^#f^p^f7URis0n3xGF|)j?ws$=+JiZBCQfAB zFzdsTl<*BVbHo}tD?8R5VVHJP?TuXj^XZ8am#p<JeTj5&Ir94JIi|}0rBQ3I-EvS+ zh<8@<zuv2)G*wn<t+P^XZSA7hRnCjJ__*!__Z>g{wef`XzTRCcUvg}I{7`7xE{Vg! zx-r@D54_jRe0nN?cU`w}!`+&U?yd8*=Wcy6z2N_k*jxMOFS6J^yZKvSiSDTbHG;1` z<!`$DPbluh!^#a8|Hwa<f3S47pJMfY>rdWY0*u!jHg3rM^WyD)_U(#~Zz?9QoX)_& Oz~JfX=d#Wzp$Py5pgeZ~ literal 0 HcmV?d00001 diff --git a/Utilities/FLTK/fluid/icons/fluid-16i.png b/Utilities/FLTK/fluid/icons/fluid-16i.png new file mode 100644 index 0000000000000000000000000000000000000000..10e0dfa30699558bad8657df8ac109699da3a5e1 GIT binary patch literal 278 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd7G?$phPQVgfdmW!d_r6q7#J8OjaW_68M3d$ zCMGj9{Pvu&-FD80*rmNi>q-|cUNB)#_?)x<F1`H!`P&y^QBiNbmkuC3B|(0{3=Yq3 zq=7g|-tI089jvk*3=9mM1s;*b3=G`DAk4@xYmNj10|R@Br>`sfRc0<8CULo=i&ru* zFvNShIEHXsPfl=P%JW~qQ!a6s|C~mn;W`J&*Kv*+)3!gCInYy|e|{gk@wIu?#jltr zq-pW;@`f`QT}hwq=E81hU=Wq^{@e^%odX{%jf%gYnY-{C&nn4<3IazImawpOF}!A$ WXFM>Y{5b;y1B0ilpUXO@geCy~KwCus literal 0 HcmV?d00001 diff --git a/Utilities/FLTK/fluid/icons/fluid-256.png b/Utilities/FLTK/fluid/icons/fluid-256.png new file mode 100644 index 0000000000000000000000000000000000000000..33681a74e3b5466a0ea75f7db75f30ba6eed2c59 GIT binary patch literal 23785 zcmeAS@N?(olHy`uVBq!ia0y~yU}OMc4mJh`M(xrW9~c-I*pj^6T^NiRW-|Ogz$AK` zfq{Xuz$3Dlfq`2Xgc%uT&5>YWU|=ut^mS#w%FM-W%n-+79?8JKz)|8FQR1ARo12<f z!tm|PwEYYW3Jjhujv*Dd-pnnZA>#V$xc%M9WoGJSi6<RH96T3wv@;qkO0wEx{792a zolPXfg_AAhOp*it8OuLk_|80fSviC8D}$<L)9FcK5oYht`TYO4V&2SmGw02`cX#I9 zn|J@&`P*;49UB|_u=ak{{q6TwHGSh-DfnLF<C*LCPB>|I3B~b6PV1FFvXeoafhUf` zOfqargHiPNntErW$<nvW?cWIOU#*_~%Pl0%&*W~+iZVxukY7JcF6ut$N}t!O*`VK} z_59GRxsCPN!m$k-%G=7Cy6<Pk)SI<&vw2RMcQ$;=i+{C>7hNL6nmPW@%J6(KH8t{E z)!v6QJEu()@?&<BXTPzpc6Vgp-4|j3DUoVHj3#Rntlqb6X%Of5{Ugzz(~M_g8^i6# zu?&_ab1dIzeze|^>|xwl()w{pjjB+ao#e-fNo{gxzDyRnv_<e?{>1nC=KlN}cO}%n zIL=?q^<?L=*=PT!7bdGDvQ0<~`K&m%C;r2An=Jy9R76deaf>|D__%Pv-`fuw&$Zp3 zocyY`tH~&uE9TEfU5Sg$=e6fmzb<|6IorPZOP}CZPs^q?$K$J0`+B}yFQ2e3PJdq5 zdqz*Atn4M+_t=j<U+z%2dz(y(q;K}O-q40K2acz&p1G%pEu~c0|1+P%Ox?oI2Q(k7 z6wb6M)!1&Suw48`?7?eHCob3cKiRDp#aQxJ@9Zk!{g<~D=6v^eJ-wWpYtHvq8B=b@ zdMvl)oHWb#r`g3f={C(JhxMjTaends3G1$P6H4W$e|fs|{g2l_Q$phlo_~6O+RxGM zwdID@QjzU-kIa{+Z(!KDw|T9}e&$O%TpxH`7Jty8X;n3$H0w&v-Z}g0o-p<8|0}k^ zlJUjm+uWf`8Lrr0iGT9x4`+<&mpHTcCs@~K7zSB06kM7ZeK32$Le}WYl_I@Qr`!~} zbY%U)(}DqiY=78X$TZ0L#bNcOy>`E&Te_qC{yL_+eNDCdopU9ZJn85c=M{FzXtA8M zQDN2Yqm7?Gov-}&d2zGv-Jcs0nwb5AXYUFBaL;l1>aFLqr{u24XPhto?H|{>J8bDU z6wXXEVcl?{?GH2Wsm+FMo-R*aCP~H3cbk2w-B$EU!>lH?o1e73qdM4<N*b@^=nC*3 zS;}zfj+oAYM1Riz4$0gXpD?Yt&6{1`T6s!G$tQwwkJ_ai-xc)=(|T`Q$eS?xQ{i{n zhmR`$|NF~(N&k%40fWQ;SgTe`C@3o*ezPJ|>TB;u{uQi0v=*M@)D3$t(3<FXSVpAC z`B&^L=}Hc{4=#`Qqy;(KC<i{{ka}y{9nzq6K-T>K0U6E*;S09k)GNr=eUdlzJ&SJK zRTJY)i*Edm4oJGI)m{BmwJvzg^hhZVDNVb?*ZCj$oM-)6ykq&T&P3nJt5z#kbNtDl z9lA1WZr(@hq+OcVLJF2>p7|JT+_h*y!Q1zbzJGB&Sbe#y<NnHM(e>d%_4i{I8k`pP zDSqYD8adCQE{k!BhpxhtKWDgV&z`GP&3OF$i_@%?*Uscmx*l$nbus9b?W6kCb+Ru% z<saR==AFXro;8nn-B>5^cIxfkeeB=+=Av||OE3K&?u{00mYn<Z&8LkP|Nroun)~w3 z=VLP#IL<D2P`SLvKZEhm+2XDLPrf>4diY)P<83vGTbNSHT&IaXl>HdOd|~(YivP>R z&pqAC?H3w-GVRXA;A^Ze9GOJk<n37MHT~GLl@DI!P5<y<n)uQ7`o9vp{&KD=bG|7S zc>1lq)A`2<*P|ZFzP`Y3R?o)zH}U%UL-7yJbsn3Q#psmvzTCi5_#dxrzwe65yo_0% zm&+Y$RZCvq(m9st{fjMc(;eosUu5%zMLx7l+i1C_N%!CToV&ZG9xxDmd?`b4-!(tR z=ZyM4Ls$1yUQjpR7L~gB=7-LW3Gx#z&(d@-my(^Kuf>1Sx2jj}RrcGWXUzMBL<~ej zo@RXQJE7L5;#qg}<^E2cIeR6g6jWo%%~Csl{$G>v)@g&<J>DC)G!&LCnEH&Xk|7|9 z)%*PA)koLPWnycWIG%Xof<$HI%0#h$&)3FsOk?U&@$_<Duu)Dw<E_YrD~5koi#<JG zQE}~0SMTx1hVcfrr#;qAWODnh{r@n(y~&DC{}Mm^`F#Gm*`qzzj(qo8@ky9-+s=#3 z2b`WXPI@C^a5VnJqeqWcFsA=odCgJw>wot}ZJC#sy^PS3Ol?S7aCD~B|5~m!xAOd) zbM$Ur5IFOF^7CD#ucuTzoI78%w>hkTUF_~-y{b!|z5Ci0&?bNTRO0QgoeSHJtvcko z!f@u^s;^0xm-!0*jN#sVS?g5JMUJ_b7A|4BBs($H`TxJak-N**?l)fYY(Yap`0N?` zBts-h>Qs2PJ}n4OTl`AZblG*!w+!ZQu9UTQ-1>Z_>)XbiN9MFV5<Z{9_gBVM=f@r; z5C2V#XB#|f?LOXle$dS}?j~=U`kB)$yFRg9U8}hH$kE2Q>mmO(ce^b*GcoaR&^?=U znNzVhH`HmK%JrLaJ2>HQkm2&QFt;n$7o6GJU0(m6|4LZPCEF{Z3+}vg+G))DUjKd9 zO)l5Q+26BQUYatYN0s>>n-1H8*Bm=acCJ&nS!8(p%O8E~?@ODlrx)M*CH}{_b<)vT zh8-X7aVzd-Uy{<v^lML(R?6%hHFh8OtE?1JUg0_`QuA5Ot{n#-@`c5`{i<s&$8+HJ zX@1e4%b&eW?s~3KFxz=azoPUKw~xCPIpkWNij7p7ys_W$;X<WJW~%H@{R9oQd+V92 zWSA%MK9v(})SUZQsKmM}T;1pCoyPpn>+{(R-@SBI65Cp4e`;^i&&HC2zb~X(>@W&= z)>Sv@-!K0YFIqlbd3bP7RbSH=r^gGjIL<h_u39hS+n#=j|5%gXq^86p3QWtb`C57w zIXs>FSghm0%PBeg<{GgzT(^_gStcD^WKsU$Hbc+u?`|jFFqx$<`1I|veCwHW3B@eh z_3vh1_*r0f&opkrv*zdBFWt-Yo}Bt^eSV@;VD}btuS42h4+0&mzH+{}=Ua0`-k$%; z@-k83-FEticdcW3px=MCVV&)dqDL1Qc>etET_m(l$9^Z%1K-zNnXMY-%ewRDY!j&B zQP4i@{eI6`2Aj`MUtZX&eL~Ic)6A((d}q&pzkc!c`rY%Hrm<?(U+do3Ztk0S@{Nv` z*2x;vk1GzmeOP<V@v7e15Vy)&n>YH;PQ)ec`+xlS`^H^fEA*aT?sjLr#QSoi;Ht9C zn{C4PY)=t7)zqwUTZ*Se>x`y&;;p#J+CPFmyX<vozIovcKYO)Z)X`eIwvvc*rye!t z?EILpD=pvI>NTrj`kbr2M>@2*u7r0x-Hb`_7yNF!H6UKK&9ptbX4^imnrrL$65ZZ= zO{%yatjm?>FW7V?Sh-16=G}`Y^1Q2Z4AygA3*VH~rEoVpZdaGPogH`8H&Lb&@(TK% z4}4gIoF&dKoi53+?M%VWq%Z4~U1J)*%l!KPIEA}o-TV)hUo5P&-m_0%d7?M}@3doc zGqqS>ZL~h}@xrzB@*5HkIu$3R3jg@>+C_Zb&1bBWw)UJAv#`&<XLI?X;m4Bos=TZw zTY`9F=iiUGF*{n}hwQx9q4J(T&+2L~crtB;jl+GL6)W;9Iqxp&PQUZ5>>9&r^==LU z`&G8O_ZiOWv0Q({<JRCZTRB5d@y0uM#+hY&s~Oj@c`*I?EWS|LB-OTPwP;gz*{km! zpU*37msXV6^=4ymmGyK+RnfO=7^mE9db53M_kE9p0@IXIc$>qRBX}=JNiWd2DXlP( zNsaj|-w|JdCQjXSCFunx9jBbV$kCb9IBQwhy$5&uqq<`>gR0|S-q~6FW~pKEB71!u zoh#==L{+W1XFU7eQ<)^H>5wY>XQTb5Zkvf~1oFiUbiV|dYUR%|-qmfRqOTe$y<m-E zO?=c{mCAyOO{NEY6oeOePuE)(S8%&|+Wbi66K~6Y|No<QlVv`WMr33pZ=8gnH-}o) z-w7hiPnlPq;MSh;N-o;gaz|;nQcF^B<N}kxsq(ixW0vn*V}1R=i|F(%A<RCEMU2P# zWTnIFF6m7-jPRDx;=h-tDc0fn%T``U^aHom=G_xg@2RHs|Lypa=e<s{EAr=sR)5}^ zoM9q?ncHK17Pw{Ym~b}Crgx=(vebdw68rK`_!KxdshQ>7@tAK{>%ii`&r;{3!rjAW z$9N>FsgK$B<L6&N8tc6uDA-&V<9V2yFn5XD#C<C5xxM!u&A4n)sbJdn{_yv@VCNgm z+I#0HO}O=3v^TYQ2LGC{DGv^Hd%Ul-ZT#x&QDmUAU$9rfwBdc~;#1!9qH4A;SBU+W zo1okO?q}%hBZt&>Uyk{Eb?p<G$@>pZz8bEx<C4jtcP}fSEPcoM%>JkQ##cukw&lyU zeqaB|zDnG}RIcj4ABSDVaon#f=kF?Md$pHg&!3|lt6saL%GaceTrqnPqt_c?yZJl! zqn1tq$JzDY`S#r|(qPE0d%xnH%1W~fg26|mlo~gFT-4C9<p27Q%L{HDe6QRe-Et{Y zV~MCksphH2iyAJy^mpt}KDtP2Gq?Kc?}yG^ZQ5h~rF{!um05tuMnA#-RZABu{y#9` ztn%5-O?NW(eXp{3`{28)(oH=NQ&ah(-z=AR7#(fW2&sIqR($%R6?@(ZPTxOWly%O_ zfC7#ZnKki(&pxwFzxU&zPy3V{C;rnMny>dAGiy)}ddgn@!*7o9qx_}Y)eTaAIDH72 z{8Hy~hW*Yxbr(f7igS}pU*!62{Jm;9TWX)qCyiMCtxw<VRCM3_+-0Y=J4fi&Pqjv2 z>|v9`&YrvcwBPt{L_puJ!~es@0=Lbbw)n?a7GK{;@oxoJza6}>j4iy!`|<q;7xneT z;wDBq{e5lzGR)&_`k&SMLGQ1=h!(y5b@e%~>y69X?pSYU%`4sc#c{<=?yf_o&hJwX zm$nx?xZ*xht)}a?W?1Ll&%ZJ@3Z0RAn6PVcIu}>S<{S^^lm)iyH1@AQ7;P5jBhP-| ziu!q>)yImeUY(2hSy}CW(b-I#Z}y4}kGHfds&col`B={yHl0;-)ee*BHO?V>Y)W47 zGOW?pytMJUul_vkPyO5S3fv-n!e_~xT`!(1d3V90s|+?@-gzdy4w>!!zjsPbLE4MT zQxm!0*}QrukYe-m;zy^v8^JvHeED_GmGo5mm=pyZVt?8#;@tD{^#<!O=8zdH_qe?k zv0eJ<p|5-A+&r`Q0-{GBx`ml=O9y}6dO9NV$Hk9LJ*n2u`77iad{uwG+N<DN@g{P@ zy@|nmKOD~g?+YpB3cD`I_<EK`yZ&BA4yki5WNe-1hu;^@TKdkau+N}bf3NX|g?V3d zKHjc9^mf8E#SI-%UrMHVsdDM}?f2o>)4AQ*%k1#(46_MdCmG$P-uqdwH%!i-tMcxo zTCU~WRo^w*?K|&W=6dkUe$lgXC;f}U(p}aaO*dkyT8};x+2wH7Zcf?3_tD?V9<AFv z&tX?l>4vv=_%>>7Sr?Q%e^-E<{S>9^Y`%4T@2nET9^B^-<4yUme4In|MEWJQnaOXW zrYH4%54;lka!c!l+$8}nBCh5pUeop3-^givXJ4tA{>lF4^VdzEo&+$+RsI)Q7ilGL zw7a8Me9QY~<t~*LI}~@-ysZDI`!Cqw?EQTLt1kzCR+fJ&ayMfYYtWL6s(pq(e+NA4 z5)86>F1qmLQgJS>6&iw3a~5%Q&b{fXp=bS{-SqdB;#Iqxp8DO`9{Hj09b;3hR{5*@ zXEmB$1>N}D9nfH8&Ao7YzVVM&N2_PfRpxJ=_~D4c4Z#A*9?o}fYGMsj+~!qTTReBK zyLT;i&CC79bA451Ul>0&eNkg!arNQ(X!$EwWL6%U_4(%!v#WOf6TX>E-*w+(>jtT} zc^8}G`aPD{UVkn4Q!~zVuCInimr{>>w6gN5rjP|JOFgEXdi;6gw^xo=u31YIJhyM% zu<KW##;av~iH>ncr->S!JMrKY$Ij_O`xtJe@z-BZ<Bw0t?RJ-l+;HF5sQ=I^`(F=> zu53;`r|BVHuk=HIZ}8!=c2BVkr3+2Ig5CdLuVR`1%k$>k+grZ=*6n<-af;&Z-N)}( z9&%3z7TYO$Je)PPVf|kDdhviI$G03mm3**?l{;6+^?>Pt{Q}WTO-gr*&d)LoWr$~* zzPiqs+p|F^s!V_0_ceMMkuGl)JST~GPMY%OP0rFCJ8qPy+`6?jdusOjy<w7;MN2L% z^%g&xw%K(u-!!!uEG`0n)Ej@Vcd<}jbamU}y}Tv=7H$;M`N6jCpF{n5jW3sYQX;>} z|9#Sad=i6h_W{Ycg+d4R`?s6<o$tS-btC3lfzyOk%aB7;7;moK`tjDGs)HTx9(v5> zS1Q^XysPj>F7w4zr445L6H00`MLsVS)c(Tzg*!SsZ~nFg%wM{1L~cGh%jAD2+uTcu z@xBI8mUjiG>)y%Qcwx~GlPf0PDm-Tn@UK-|kb3cwwV;&_Q%2;DTb7L5s+m^gK4;08 z+4y!2!|lDI0^)*m4E=L%J+S9Ko9{I3`q3?7I<gD4b|+-&eK{%Wr#yR^>#t{>)uLYm z&9|@F%&{Q#qN3c)8;iEM^rYUKCUoP_1<UHCZY?X<&C{9Vy7b|5o{gJaEc(Ly`+oeI zJ&o_esm>ksjUS}4%qy=8x%Zr0RMpK8C02NQ^8tSj-cZFgiVIQ~MyFhw)BbUVM)uj> z>tc@>Z8FlH<d{jz`9DfB;VI$qW>OIr+}^-aabKxn+ChdRIdj(WF|+geyl`*ll@_ad zt#a%ArBz~w`FNB{q=mlT7CAG^R6D5UL)hwUq5chR@}^l+E(sOvzB`fQpc7NU`oLuU zhz$;zo;nd56odptwzj$D@=C4A^DeUI;^w}&ueSQJaj1GdSCHai*4f`1!!u)ML{wH< z-n@Bp;loF37xhk_%dm~Pb)k88cekcimQ8bO-pf_4o~;&FR|xVcZp*#x_WWGiY@WX@ zH!fb;#3W^L?X}haACLRp1E;8!*S()};{4zCnWoP&b}w3_B;tDTDc9@;HX_ZnyL6Zg zj=3qjW*zI1toagnxnD3a?eMa_kFIbj|4{CbR%ZOOV&%%jBOQVZw|~A;<-4J+;YG}P z=d?7n)YOmPxBV(@2sok{BGYi`QqZT*pOvp}zAOJ|>Cp;h-(71H?(Qm`sM9L1!>KSW z?ByxN(?)UY&0ntA!kL)NaN}*+;;N}kKi>wj|7boiFIwv63JuSjKYe+mnGZbvC?RY5 z=sNGOZ7zG?oILb3Gcz+JWJdg&<-GSeVn1EIvGo2%0qvYKXBZ{Dr|UhP9$&XGet+FU z;qcc{PFm*Q1q#?79nh7v`}suJtzRzJYVzTELW{zykNK=nv)>|IQ(yUq>z(=zxyXaY zg?}O<l_GX5Y}sD-w~Ei^gTrF?xsAEGoeXRY|GD?hoIn5ky4c;1UY%fkctUe!#w^Wr zw@*JVhI9%m_7!RtL`5q!$U0PfK5}E;b)H4Je=fZG(67AU$L+M~Y@KQi8#d0HxA?)M z)M*d1PiU=v*y-Fe?~R(@!}n)XS#7eHJS_gybYt#%jilhX`QgPs5Aj{(T=F&k?6Xx} zhrj=+{84kzJ8(fk!;K9UDKlnGS-<W1i)#vuhoaRtbH{8qbz5Ftk@O}-O?G3%_ZPR% zwig^}e&4b7VXhySahdVA1^p8BFRbTOJV@uM{$RULUsA0sa{KN_`|GzaQuz5Q(lArP zRZ^9w?t!wGR@aefH@}Glr#COXb?W8(@5;^A>mGERyKk`Sy!e+BqU^>#fA`O{*;2E~ zqU!KOEx)D@&&}P<vd(!a*h+FLRP322CSJ?5*UkNH#nWvMZYIrLU)P%Z`_qaa$6qel zd1T|0xcNPQ|NKAv{gY&3uI}9JE_3uJ1TK+#@Tlj$+_P7Sd8gj~IytxU{hY&R%9nQ= zb6>e!sFWxF&R$^Mx~A6U@h3&y_pZ|a|HItn=H^{p%nDAQckSn%BCfvX{iCPs9P+PI zt<Q8-xtMKQFZMpS@pHh=uTMAM+;*4krRI|O?M>S5`&yQ7o2G6r$IKTUv47dzuL>5n zkD|?%TkO?;Cw)U(=ijsSF;z#j8Q!e-N_^Ix?(EiEB{V~ST9^K*bbrp*e}dEF6)o<( zv$s1b7gzURQ19WT1N%Lfu2oe%VCFO}t@DtU+ObO8=gc1IHo7|$cQ3ct@3w8VyXv*# zg9pMZ9{$O0`gQ3ZkJZ22MvvK-jVoA!_i!F~F5F&oCDb8yr^P{+ZQK*zo(ix&C$@7Q zLs$RjU$)1+pU16Q|9*$-gsZYe)!n~-@e6deTwQ;7_VZ&~<)5l;bjx_Y+h}q5zVqyI z7iXNGSGMon#VN<n3EuvG`qhk8KTLS%u6$k7&?kOQyj^VRvz6`BJQo$e(ptEzr|;AG z7~2fF`!Pl=tG;#oj_bd*@arRvo>#R2p;~;pYt{;+e%4OCSG8ij;PTxSuN}4-?z*p4 zxF9jAQ6le;`p%Xs`7!ImBkNQ1U*(k=<v+Q)VZX(i&%gcVsP-N7JS+Y-t@xN-Ytn%q z9&cA)IKisbE6K#htSx=|>y>b)P)%|EYUl4iHmbTib}988U3t&@feHWa*~k5NdrklL z_dTCj%fwmi>vT5VnL4NB!0kO%|56{WDZD4-5z8+*_rP55zTG{x+sm#l-}xfh<Gsc? z`=Vu&v(`V!Z~lL<$@t4=YkhtDw$ym>j*?8)2OAodI==2we)sfWa2m^{vfbZYx4qM3 zx!LzA=lh0bH#V$hPkGMD>6z7_GJo-b!?g+T)#k2RD|9IKz}e0T4F4?tw3YA6(<w22 zxT3tY-z@L6xcalyQqe~SyW2BT+@(B(Cb!$K^{zjad%dfz_<5stvr#_d`n8hs-%h&! ztK3r6wpz%dM{mpL>X@Q-fwx^%kJhIwJ~jK~;&^|q)9?RO>j^kFE@I*M(y+!<qxfy( zx&KLT8$IglrmkHo+p^`vE3rJ$IX@SySa0n=M>f6fw{zjyV;*nqoJ;o|4P`oVe75@O z1ve_5-N`Q9&Of)PJ7a>$)Xj4wowjJ%g~b`VO#gN+++QF$f0dWXs!t^;&!0Zb-SWff z#3}AMQ9u4z3V;0;(mVP7_p-J(GN$_56@rc)pFY|D%F?}0cLpD2OneukxGB~8{apKL zlllKxOn7$RUiQQaOJhal_@1{bEB~xKZeG>z7b#^r$!pI$nZi#&!9Le5x$fK+)GDow zOL)<qxr8O)kk$U@8Xq6F?JBCZ+qLY!SlRAd(>48qzG#QO3bfm_e%e7-`<K>_p4xZ& z6+G|aoA~y@=TA>n_O6^+dG7C`#>-p>rXHPe&c5iOz+cS^FQ40}T*^3}$S}WMd3XJC z^*!5<t-LQfciWFM+9h-O4PIS)`KWqkEbI5%F*SxSQ(|ZFJ-;u0C3cRa<J{$%Gxpie z$}6Zy=6t~Kyu42`Kh7oS)5f}0b;a+4pZf^$PMoCcvhTjgr^=P{*4}Ua`NmpbSoWz{ zvb~wQ2A8q>y@lT2Z~E72eE&IhYYba?<l(N>eOH%8{_?dC?LTq7=dh86-8P@si@mF_ z$<BJes{PQvw;RMuGlP!VYFL@A4Y0j=t?_x;--Sx|*S=mhQ7Q6cdCXZst6+|Oil>r9 z7b`9h5bRsqZY`dtlRGQ;=yS!R3-5=#z8l)^7&a|KpnVmOCfCYsn+{xDT=(a`xw}J} z8n^zg=}|^IpWXe<&}r?rBX;_`9WyU0DzgU_MVP)7**3McKW_P5J65Aj7T-@iU32es z;@NvXQ<Y!6oVB)m&z`?)f4uV+e!gMzF5%VQhmy^+M6c?Uq&DO%&+?Nqi+rza@n@H` zqH;5D`F!{LKjRnw*yChqw&}lgcl4E9zh@q9mmXw4IFTWgusQMh`M_D%erkQ!xBSm@ zcdc>$d<~0JbG4=P9vls>cz>ucvFlMsbG>Wj$CP!|U$xd%eyv)ed0Bq-x<fBNeEfKJ z`y!h<4(E3jGdJ?z7oWB)yWMC?__4s4Sx0Bx=XQykmo?4bM(@pTcm5j<pB|lz`Sj(i zPi?N2f4!jC)x-7g_i>y5{_)|{=fHR86u-{;Fmvz4X7dGms?=)p>qM7si_w^JZ`X}; zOOAOppINuCyuICv*?#61x0dAB4^K5o{(kf%Xf5}gPT7(_Ho`UyF|Rp3R(b}P1r^SY zJO0AB(r)%CJ~1(;EcS)w9%goP3Z&F!e#rN(Qk+=zkNb)h7xS*B?+=?NK25lL{QUeg z(%Sw4_pjdgTDG+7SLLtH?Q!9EPUk;mUwQwmxbxKY^X3+_T~JiMVW(QXNn_Wiod*iS zHYTJTn9Doi<Mq}MkGZWUXNE0UR(w31NkXVO@m{LKwvQ(#PU20go^|bEm(^ia&jlJW zc0UT|*%-e#GtuvVd&Y$~^A0V4cSd0O(N{HWR}b~9UM-N$cAC$y&FV7i#vlHZLTle% zc^9tQq_m{dIJRWkS<N$hc6s%hpBJ<Fe`n$<FL}qB3X}U^udU`=IpMvQ-NVf*Rtrpb zm%a5yQ)z9z&bQ@(b3HAt)X3xo&VOdr^yQ#jz_;od|8jj8il?}h|KWANchpwB>*bkB z`M85;zUMKtOF!MGU~YXr(q*r$e?fhk_(4v$%~_2r!&N<eJRV&)Seth1#{96`2mWo2 zPkwrJ!WOstQ=cSQ{V!g7A$MhQI<JajO|z4zyz9$@nfLX>N*eCk2mjwAalT&fo!9<M z?gMYd=I#8_x9X?pL6NR2mJ?-sH}1*g&8*m*nOu9_XXh;LNxmM36!sKOXQ;?pxQ%C3 zS$Fc|TDj0GH=C2LPgS+LXFpLX^7sui?sq5KUj+#ZC48?sk?%5Nm&(dU=~dIuMawU- zxO!HL<KVqr{rB_MuHf7L<j<OL`BIAsIc)n_N{^j;UpOU2+t+AW;G(=Jqu8#O44W>9 zZDf5R_lo1zLNAv8TRj%bR|sBIzjb=GqOP`Y(ej&oJr}>^mUpx3L~KX^_1eUAwphwA z+OYnKzS=ZZEza(0_$JW`5yR>%MNb3Pjj4NtmY*}Lu54Tv_IZ2Fb8X$4tyxMLZ~1<D zPg=lpSeGfo(neUjQN`0^(vcQU;Q*1NSGLyvE)&y>IkBVg@r�<s~I0FZwCp&g6VF zt<_J(d(x6U|Ns5&I{r9w-Q&m6rne5c?8!^rRGJp>TZ)O}=^-%-;}xNcb>~R0c<eA+ z*XGZuy4e=o2l|iYDQ?fayv)p<Ay-f5_*=epJ&~J(b2O*F5}0eZW%7+@rLLVj_AhIE zb^HIn@Almclj4@#Y<4=kf8*jZXV2L(cjEL)f?Q@~!`1@q-ye~2!f%-vqY9@}`PVPW z0f{jp4&4lseAzEVG0a``W@&1+%h{)95+`mw%UZIP>D$#K=I>MP9KEB|ppj&C>)qYg z-nvW~lj|7P3UMT<zYmxa*6A#_MsY#z55^J?e}29{tJS%E>s>o<oVT}jeWSFl_MX6+ z*xlDAF`Qh-QubDA&fK^03fp?*Z+Y^t|2rpt%kxhD3$gdFudUsz;;`xP%aXRc-PaEa zPMtb+8jDAng-l<|)7bd<e8C3RZiY!xTeogKYqckW<wD;DvE{RLnLLDECJ8#sNhm1V z-ulgjVba#SKEKr(cJ12L^7O9Q((b#D8Wo)Sr}Te+xp*2&2Ajz-!6*E(lb5_$m^@8+ zMX%Dmg~?)!TbzQ=`n;I&lp|}gfwWbcWm6R6r_Z0I|McCwu<_WOk~~2N<K!b9g1mLd zb6(tdzyE)ppu?r^&wg{IzRsI@VWZ1B%PoHx3Y*Sf|8Uv-Oj}>;G3iTeVeH#qZYbE? zQT}3vDr3~7MY9EVN}qn6-rBnTqT&ME#b*T_ly+W;lDftf5HMi}<86oi8@6?LvhDT% z?O#}E=<4dqIhldYMIn-9f(y$8kMi7>1mW!d1>cyMnKt}kc+1Jwr*KlKVVY}Xab3=% zBb{#B|EF(sJDs4+R{dQ~O5(lvo-42Vo*ngB+$Uj}<Z_7f!3pL59v7Brq8EZ@**k!H zcAfHqr%s<fdH#IANUcsJ%Y=#+*`k?Kryku``+L?}hNn-Trlh928d*k%&faFGT42K_ z9C7yMPX<XzNt+J`m?z48KkDRUa6jWs?Do95mx3a87NxGf&K@;+$EVh5;nSXq&0n<j z_FK2q6)cz5Dk|*zRwuF1Z0l$7n#Fn?nMd{=taITI_Rh|eca2tS$aP4YA$fsi{{DK^ z3s?9Tmh*`$>6)<Nn9!j|N4tCT(wR=LRa}tyLt5b4E@ii#grA?D_P+bW=zqYma>6s7 z`mo2Mh7G*D%-UL7i<T@|a&>FrCSiv=Z)-F4L{eSics4n`bxtii{Q2CeQ%V2-{aw3i z?&L}i4(XW7mo7be^rmy0&<cgEoLyd#kxMimCv`JOwH<W0aZ#`t<S;q44F%yMTv z<X9Ld#yCULuW{-^^T#{Am+N=^+p)9LZt2g@&o3|cmtX82t;5vO%Q*2!>ivBmi#M#j zl~=QWlVAO|faHydhuIe2Hd}B?sX^nC_>YSL!ad0|rq@qB-zBtHMPp?{yw}&vSxvpt z=2Cadn4gL<x?~tH{v;xPJiPu@yuh0Wp|@ET*Jw26K0SD@|G3wJdwZ*mv#w|?c7NGn z+^?HqAjLfY7r*_V2?6o{UdeVHk||t!Z{m#nlK1!a`X1$1xpeP(>|(dxpj%ureD0To z9E~hAvKZ(3>q)9rDrsr;-tf%1xhb_r()iemi(UyC)z=v3@xHBTXqT_EcxiR-jbBpR z<J&JT`pmbx`{Lq+Y2Wy_EMd_wGWuy%{_c!?{hx^?EDC2utve-i)l#q3+EjhXu>1Sv z@`c-RQ3X@WyuBKdl+Rj9THo(qCg-#>=jJAle~q8MxiQ>hyK&C5u|n2Ka$(=g1AWt0 zgnM_)yXe;P{iOPQ6OGA-=Na9*q#Ag8_q)}Cn>#*!;O~*Mz2zY#!XVwid}|ZS4pENR zFR#Z{_g-A=ZocAk__U65@2)$RoVnna)Dst|H1D|dN1K*Ull|=$I=Az=_5a%PRWTuN z2FIq`lJ<2q%|?-dOwLx4{TC(AEeI0JKk`}N)LiTGNwcz6guKaH&5|H-{rU{v8FvHO z^xoF(|9Irp$wS4P7qMJ>C$#RdsOpBDIzRR->?q)gl`E)-R&MB(IP%rCV_s+Hn<>x2 zV}!O&j%exC-Jj|0^}uIA`HQp4eHKkUJ;yRbRYfO?8s#^A@95gzw6o@CQBZL3%604b zE?YOgY58qFtC8VQ?Y(tAGcInqur9)HW?1X0pc(l)j(@CE(4IJdo9d3NuZf3yv{#>; z%fDg0nAWQ%mj_>6`M!8mSp+$j9mr3Na}qBw+OWdZtKpzTOPS&ES)9Ec?Y|G)^L6t# z@|>{UAkgc<*0#C!sdKNMyjXD7&Co`QpLMMlQ_I@N&XW?ib!x`B3QqScop8itj@c6{ z6Q4DfechkyH*4Pi^gJ=7u6|!}it^Qy%t!vFym5KKu+(8km6>{5)w|D)=b7(WeO(n= z|Jw0mCtIM%$L;62yTX@zul(vVNuVff|I5!E@3p)R?^~|B{XFx&s=~_Gjvrrqo~&|E zXZHVGm9_P3*HkvM{9t}@=Rx89=Svq?YtLRT+i`kb`RcE8KIfZF|H@L$HA%&I(eLeZ zEE6>AWxtrYMp{o;Hnrg}Z<+ZGnUCsB^ZU8^E8CWz-_x{w|8MQ^J(c=5<|Ozt?&eO3 zK6CE<yp5gC++l`W9)JI{^7wR_>(!Q<bZ)uK+7+qM*k@8(w_mUMId8MaF^1EVF7g{3 z-SC-TLVEM(=Q6h4Hy1x=Eco}xy5i?+!z;FhB7D22-+v|}{_$$~eo5Y`)(7UYZ;CaU zC*r<vnZ}&L2hle5=TaGB?Ebj^yOL}9_k9f4yO;@^S{BLW@+TfWzG^?e@^RUH4;G}v z>rI*N5XJ5o(xqm$?0SYG=M;mJKRs<E&F6VNP=5H#S8C3F6Rq;Ox8FZ?cz*qwb;Zxk zhZn39YPVgX@9})!$qmtRT-CL=jO*K8?R~KFA`k0F+0XN>UkBY?Tj#pp(UtSc8)pBt zf$Xh{-}~$*tmE%5-tqEh@s*map3j|YjB|a=m{u4rIW<!>P&)k6)z7bXinHd)8h+Nh zxT2^d;nTIvudc64j1<W)@7#E0eaf*~m*5}Y_?su}z4iCOO0oN4H4nLBUubCGJoK8y z=Ksk=r{xn;z8Y!#FKtWwxcBNqGfj>MaaR);9(Of-_FYtd^>Us|cYhTIyI%}g$Fpf! z?Qv%L`R>o2zIX646PNqGbszt$oJ9w7{0dKYe$1S^;fL(q|A+HusGice*|T=?hJVu? zwiSLlIA7Xk^3_kfLzoOtsBh+Ai_4i(oc?ITz6C3-90UdSNf|AlE^&BK=21KSzg+d4 zcW&)7H+~^noVsbg$-4S{ISVbt!-sn=$6rn@e9gVQt8Me{)=w%og%VgjG|bd5eLWhm zQFhgLjy~VBOyO<6?n>CGcs3k~RlmDz_uu*dzlzO$@6j9k&v<_8)%6^!HI9_B*xU*d zQea+OT9esYaCX^@<k$DxZI_vg#M$}oaF$*9sAw6ttM*=jOI$CaSHwqG-oLHR;d|$y z7_X#fi`mNms)1_ZZ5r-j<|p1UO1e&%q|0F-#i-F`peU-(-2LU+?Oy->U|r7bT8v2o zAJ%T2_$xosTfl)WX`7bJ<?XXKtbAQrvBu8l*UInxLTPi(uFU#UcG2NnNy>EVJ-Mm& z-*+@WUVT6AdsR#C+m*u8uP-iZSv1)}Y3?g;4%;lX2NRrBn|wUZwqN0Ua88hGT@L?y zlllHnUal1W)w7)Kq_ElL<JYD61X9a?oDCO_O|)6l$HZo4&X{9R^L^K&8A<Z_x>rII zwpTh|(fuzUcd^pWl+Aln;bp^Lwm<7`T#4-PZMW8F6J38{+3VF4UVSs(by`SlZW*Vn ztn`9?S}QjE+~YLmS~zFwx-$DKp&iwAP9IjLez?Y!dOp~>uUI{q|Br+0=iG-v?tuqh zAAGht>0_qwian;Yw}#6)t=rOh(pk>1;9w@_jYPl3x295;c$oR?7EFB2Ev0O{oPnFi z+J3W!)^qLRvzl3#Liam(^+~X$NPjK9RKjBX?AhvwZG}rNm>TU4s16UGQ}+0T(#!Yu zobP;3vhAMz(*5r7Ka<ng=KYVkG`X(4UMEd+ZswhuH??OZD*0co`;al$@$<b$$LBgL zsCs)a?0@VTc;NZN)u;QCDz?8rbZ_+<U&XVcHuK9avLBxLqhE8;pPRNv0@90TNgv8O z{qWrzk7vuT$OtLy`CKh4zxVUsrL!YDOKJ^^r^hYa{eS)XUy5^oSzP*YeWKc*=%>f3 zuHJpkJ6Y`Xzw7a#|5(2BM1ElXf3w8p#`ikScRZrjA$;OL@0K1~yUQfpzFITnok(Vl z+`E5&s@m*+S&D9bc<+sT{mF(|dmVS*wLez<Ixw%8&FcU1wR<P%{SkQiDD}?Yca^)& zvCsJU#v=63a<iEF!qfvx<dtu)<y2#M-1(>5&PX#qWy0GS<5#J7-yWaVBf|UWl*n{t z-319>Pa59HaV+Eb_+H@g|5>qrExvs;KRhY+#{tz<d*AU^$mVXES8Vrl-EIj!k%`CJ zd%y1fU2xZWyF`Wc7C-6IL#LiQ?zGKd4ZpI)px{@nQm<`m^z<0fX=mS^nzP_{l$qtf z>_7{JTLrhx13@+H@%d>c4vWRQV#`+5W&K_(&o3(b{+w`LV0oXEO5*dzjpi>e+5Np( zQ2NJT)N9dM#!bzFd+RuUKl%Q8ch|?LuflUm4z#n`JmwWhJD{j+{o{4OUiQxq%liad zRBkp|H9SiGulq~m%9+pNoStj6dJpqoi`F+SE$jWcYTAB7<-#<<n2ncScs4(~bM_Y_ z&*NVw-Y_LUo2kxF@7%8G!dI}2Rkh)+?ir=|(=YS=bC~|6ZTWc~!TC<>cf5PiTBWD$ zeOV()Q{iSs;huj-`hVY-Qnk47jxS1n63?dI$G>V;dRL$3Ufz6o=}VIt#b<JiVjT0I zTgUT@8Qqx5xUzD>q_bZa&%gN8_;u^XRX=ClD*5la{NSV7quC}R9v`PLl(+P|&Mdfl zjcxkR8FK$G{(b*()x8Z3o=aYGFuN|_aw?)`Ug?S5yGn%Rb~r34Ubd1&VdC^{;r>_8 z&tJ!<x>9O(oKeZ!uq){-JHyHv9wmQ!vHQ!vS(WwTl}l5&mtK1KtcS6RY2W|3j~~C@ zKSQ?gs8``04uzP#c_lIP51A@|;ahN2o{!&e{V&U?t84TvzPQ$^hgg4&k-c!}Fz3^| zqRmZys<WHD+ic|51!%weED-%?3-k0Bm)`1zTc2Ji)S&YD=Ka3wOEqs!*5tT8Q}9L2 z;=He(dV7DWA3Z3YFO!*?mAxw>-u%w|`I5bNynR0wrq%zw@$1BXx0T6@yzeV?_5b$2 z_*&fD*4S^!)h_=Bdz`;`rN-{{y()akCF<m{%g<ljeU@FXf91(kp)W_Z?Laf)Kg$0m z-Bw$c)Bkem{Z-$NL@(oDDoo{CscgOD`;*zFnb-bbboBRd>sxY6VZVOKi}Wuk-oYFR zCLd;bW*J}n*`>IAo$fm&EA1_gBJ!*+e}xA1?=N4Y_T#YR1QGt;y^hoKJ}rLUW#X6U z`{mqU-8Z|#^=;gZ#g=D0;t=_j{Y-;l-me!Dy|=F&jQo3#^Yr`r=-r%6#mm^+=Dc=) zb@z+8t+igtpZ>==f2OuII+-n4WXMur!q#muF~u>rx5astsoBdvkL(Y$a%Fz|d+c5O zZtIrhy(J#k*PpAYx_RQk4ZYhp4Qf3i;!gj&em`LPgc`YI)vNzwPad;XKWlX1&D^F3 zR|MX#oB8m}_ixvoL!G=h>x}1p77v$h<6I(``f{fr;};e?<1mX^0woJIV$4GJfBb$v zn(OK@Urw#WNh}&?WJ{xWcs>`Oze=p{(NW#$?gg8<p1waN=>PcR&ECs5OxLBfw9GQ` z$@i`K>&^eSTvWdH(^sL?i|mJ;KTVFP{c6yBZCiGUtfhwJ<JLR(E?h3i-o>QkBP%U< zV0W9^ky76~>-|3#p6xhZy8YSSx<yw1e!s1ZUJ&SX`CMJ$8ZA{B4gPNd>eX2@i+04V zob&gPW@9DO_S1(Kr=LrBF!%p*@6X5T+1MU&?A!g%$G2f+yLJC{{e*o#cV2ehC#`pM z+WNPu7Ez%p)hT&OcUMl|bAR1yHZ%6jJpJpk-+dlbrzv$wwRBJCyuL}2e;p&^7gjz# zZ_}6T!Rzith#hE@{i5{h==r`Y-7Za!>sS2#zE_mlVcX{K6CYcCmhb0$KX-ZCXSTfy zz02?4PG(9=xw`l7kIT*L3r=@dDee3_b+W^zk5_dk|NL~_F(7_z+tjO*C$HL`_wVoJ zMunR<zMqirtI65;Bafp^{!8_OI~A{gzCG4x^YLi>*CYR4NleHIu_@)sUn`@#@A+C| z!N4mVcOq78OV0`4D08{n<b}`+iw&K%`D+-Gid$U1oDz(^C2Mp#^81CWIhwi;=7uV> zs%ypZz5KFS@2+a{zNCoty&BzaAMS)N-&pha;2gVv_thuPuX!?8`u+0{^X!YyW?x@D zH!xo!{Dxw&y|nzyL%ZI_{>=EA_+V{%^~`&}%g;*Azr6l({-2e<uWRs^Jnd1JfBGl! z|D~ljH>_=V>mPrzI9}%b``w?fp8I}m|L4Cu9{lz2pC)-$?rGu{!^WFOWi~$ee9^Yn zcJ^}i*3<jzZ5jfL(;fZ%OWkz*JMtL(bx+AYG-Q}+s&`30Uh2c9haQh#YpNHzd=E{` z4F7j+_QG--_HQCu@|Im8;X7VT)34w^YQO*eDW=)XPuG25-T8a<ofO|+(*@S9<N0*? z+osp+lzCR~dhvOqPtC`$Z#E@1mYGi#T>?DrOV1Y$-j!D`d*`DuyYt73ydR$Kb@SJA z%(*B&fg$?wx-YFB^Y+WH3ty*K`66krxS#Z8b<djZsR<`6ZqNS0Jzu<c>Bpu0F%o_+ z`TxCkX**XFP+GR!;GMkxi+S(wOm8eXcUogp?D{<?%ciZ975;X2P4|3Wt%5$2vg)dW zPr?tMv&=2NAEKtWi%Ue_{r-3UyPKa+ll8oxEywxFhS7h4ZXtJ+-wgiPHfh^RH*LnA z=iiUpGB>LqS*{SrFS<Qt;xnGU`ImOMDs9nPF21BZXs)`JV8!dBUvi%M33i9Cp4D=$ z<e=rs%0my6f)_Wf{@zs*y1Uh4`$|EZcQFT3H`&gJ{~D)Q^)~OLjcNRu_qRhkgX1}; z?l!p}dT77)%@)0YSglWM?&^zJRd=a<Q*d=*34Pyq%gB($>XM7x%Ac?1xO*LHiY%Rx z?2#aMAkqBG=lE~DC7Dn3RBvsq?OJ4&y=T|C`tQ4)nI6W~g|9vLVM5M9zDaKv1&8K| zy<hTDJt$`8qw6#Ej)mP6>(Sn_yZPewO|czSN7e6rfBv+9UDk2e`!M$(>ty!4(F_RJ z?C{#g9{%%&Op}I8-iq_QKKze;_$^jEdd1P@#n2@vc;m0o0p}M|2aoAJ3_HB<-=+7e zaeqJdB&07|aEAMw%I)(tT<cdiOZ+z8&B4bb%l`NEi#?@T6*D;2U-K1XT~xT|pn}l+ zw5sdRE*#;mYJUAO;K~l?_B7XtA{WA$UjFe@yt&Ny^MoZ2qTF)l{d@mwu1(jh>He|* zm+J;AHAO5={9aY@<$!^%zKz6Q&5)Hp0`i2P9oMdBe7UOhK|%4|jR!v#C3`ByS%%L2 zb+sj|-K;H#+iXSrB#EOBR~LTw&}`5yimH$MHYGvo@cUB=mdwU=jrlFhrlwAid03gX z|MmMX4WY?NvW|-c4mL~g-`ZH`cV$tH^bVt)|Gz9Ke%i2FjwO88g*|g$R;`basP%ew z?bpoAD{Uq<3Ty9dv58)_S-Qa@Ur5xb<jR}Wfa_ly>#cq3^i~8cWm#M|Y45~aMvr_L zglgaa?D}dhr+MPx)y+pf1kZClzWTn9b;Z(UStjqNJPU5okw}c&A*6A0k?YJOCf}K! z1%|HtaeM!+W9tuC8n?_`a&D%3Y*en|!)FU@a~5QudeV|395Z*4veoW=QR`*f*%Bh= z-oF&UGi{04L33TtRV$a=I_-DW#z|N}Dyu9qL(Zmt&qCu9H~1%nF<hR#p?2@h-g!DE z{M-I>aI;I=RvK;6j(9FU!K7PpNdkjw2UEsU&toQnfxIHWZeFY?R_D$YwL4;W<Y}Gm z8g9>;BRgAnEarc8ZgG_99_|l9*H%u;o%>n!f%(~lM2`Q0?_^DuHP(x(u`ZtLu-4?{ zoM*WYa=QQN!pG&ojMi`5*-`7>KJZSE_{E|BHfMs=TB!nopC<p!ReGCdxM(qdW3U#q zKK5@>T>R?qr`GCiWNBz^Q)b>c<-fy&fCnC5-zyz4^w|~`r9WTGz>e*nL&Y-Ph>Y() z+O49r-hQ~n^<}fi0jKJtLM{f&F7>U?IuceQ7R6Aunlnm<Gx%j{q+8J9^`fqhfg&oN zhn{~{JYDpleskuZ^MAij`H_=7ndwPXO2SWuTiQN_6IDD<Z0foEQbk|C|IeSAT_rD_ z!otLu*?1mIaOQispqX#cf&~pdJw0Np&-BS!-`Jea|NrOt`iOlsmil`>G|l`~u5?On znwSpbg=vQTGX%3$zE|yCyQ#=*Ht&4>S6adHYp-w2<YeG3Y*d#LzL8^QBiFCWpmXHD z&z4yWjs}XXmQOMWxU^``9WGXnvIxHe(~cjAm=%$gm31UNyX?@>_XoNrJ+R#_yD9j{ z{oh#&tXwK3ZgI}DX8t9vvMuR;?f1DeQ>Kb>Mlda~RaTR}m2*t$Q=&iTvFQzRkrUDt z)Voan9k`_RW3SI1;|H9I9Q*d$6pG&7Rk~X8?a`?EyqOGdrS3)eBy7K}Y*gPS+*V?g z_AlVc(ylF%k5*WRP3fo+a*KJkt#<RDfN2aF-<cGC31k}F-?zwR#jo1WQvVL_t9%q& zZ`ax6dB1fjV+7NISIx%^Cfz@m&ok@Oy2u+j+Z-kYid5(bZD4Vzc3T|!U=r7ny4Sp+ zmNk#=wg^w(`gt=b6s}D<+p}b$#4XQ1|28;Vd_S{ji`O3ES^nI!7{YiOR2goWS{?IB zc*64M-zSC7d11D{UwikOGOhQwi4Ih{lr__S;${X>(PdY7=DRZKvS&+ecv_gEW2|6r zfB(b3@6%sDW;pfw%i?MklW>^>-|yGwryaat*3F{Bcwyc}#k3~AiIczRd%V%OCz5k_ z*Hs^**A7glSvFh{3yhA=R-1V`OVgWSOSWC-NkzSGcby2P1#6X-P1K2W*NWP};xN0_ zIIL;cu3ce~hLdM`uXSab#sHd-Qf0WM`YKtqz(Qv2=A^G*(<WJhyx+je4N4q(f|mo# zEay%uDX^NGHtA}lN&+VXcdmficHZsFETRO$R2HzxKH7P7hA2l0Cj<A!i6)H>C-)tl z!Frk{WAdybAK9IfOpQ^8#gaj0iA@w~bm+X1bcTy%6H7y@8W)4-q%&2QXZNJsPdd}2 z%5Y0**D<ex7Yp0Xyd59yJ$j>!SNhBh`)H7B9ID-_j5r!xatybXzmGGHtVx{+3TWd+ z=Z<J}UD9E1R!izOoP6$dRyWI}DL-^fxRZ)Ji{Gx3ey@AXhl?RQH~<tZN9M5QoIC9J zc<0d>ox;7U-V70H4%O}<dJ|PNAKh&5)W3PAl_`2RQ#8{7BgRFqPOJ@Km|?=GBejL4 z;VOIXrF~nDZ!r+{nbVtbP-)+`o+}ZHGyebk8=ZPID=X^^M?<`>kVn$j%T9+L_NsNH zM&?b+Jm8YaV0h{s^QOk4ZXO-p1$&)3n`P(D5jB3!vSr47A%-w{7a676ecR%`Uj*lc zy^Hd7jL$sLm^H=XK?Cy{m1=&CEglDj7~XQW9`H+uUDL9*luO{j#^Z9v!FB2zWN#!) zY;E1v*WBPQa86(KTI%-OQ(3viG}cPaul+VNY4c4H<FBqPu90eut!AC~9Hx4@1#oe3 zP1)Au+AXGe^XAR8)&{0E+fE#Hiar#y`N;fv^VY42-tL!~ePeI+_DvNZAGKvLccqF& zWN=5MwcW@yoBiqA?R@QA+4(h}Ixp?5{@%vXnAF{(v&HR9c<!wkF7u{OUoIjpuKkwt zyxs3Lk4mi0ay8y{nCKcL7RBtQyltnE>mBDdp1@nizrMb{F2Mfqp;%?4N7@%xnbOp* z73_R6D<T4>2r9do98p;jaQmi{Ou|~$4tcM}7-P<Me))6Z@mtS?Rk*4DcX3)Ww@#?h zceYvK3B~q+*xai24Ra$HU8XT)BtBtW&%F4I%C?(1HeW6{`^+?2>MBwHLuo~T{~Nti z4Tnr7IBOhOexT3m#<I=}{^bX*Pgji-m@;jeQQe;kyT4z8H?OZ~%x-ko4cfxuP`udu zgZ+VAwL(WnM(eUS855g+`Tu3K(BQx1BWD~C$-aNeE7PWDR=>3M_4{qBzs>OdXIikt zbrNs8DAyee9d@%>iT}22F}b!j`g+ot{b|b+>SnVvThB_b6UbyQ7kS@wBK_>Sv`x#s zyd$^g$?~-yo)WtB7yGlwC7GNJEuTdU4)yH%f7bkdKwzNb{e8O6H%onJ`SEt5?7DZe zl>|KZNY9EdUXXu(A81my<n67iZ?ug!$h1sj@DQ<On(AP0{Oa{I-DrzHAD+zIs<l3M zX8G){i;LYir=AvD=0890+tktn?qWNmm=xkJth>`)nU)tAD7d@){jwDrmXE^1{KfWL zukPu8-_<&a>tkL<-PzuspPz3|ILKuDn}<oJ-=g41RD=lgG+_fHKBtQ5?lW_j+tvP> zVadP#=E72@Wj9*9<WGwSM6%ER?%12=zW!MWlbiGLK3VBU!7EvgDLQS^jbJ(;64l#& zf6HT~6e)q0V*T^HlIs?%ijU&GH^J6pR<_iIEuKMf=cM!Z96Zt~EWIiDQvU&k?k&2E z0^Ht>8`FfAEnmJl>1dZ&=_gY+0hMHhfMnK#3)|&RJv%%5?7mIRFES?XX!Y0-_HL^a zC@t>Xxs#Vu{oi4wQf@1G;cKV%hV^G&UZy!oWu_=oT!L4%`k!xkOg(IIj8-!|ZBkAM zgsq84>^$u@ODfMgWqHT`?^hkRs{d0v&TD?>fO5Z$Q|{W8JH6!#3^v>oVtC76E9hvu z?AcT{KA98z_J0xzw{iYRmsMF%E%xN-3>)3GP4`bXv8x<O-uCe8_4wy^iqD(Q{u6xb z<&?x~QHI%#@6v>}Jvp`a+L=F+elKQU-%x&ix>IHBpOyogQcqjFTr&BLOfX*nn@sZz z-3=@b(nt9ZI2d#0nn}yo{ZL%&9=%b8S82sgr>pO;FD!h&{;sGA@06P#HG>lq6|Ku> z#U0rYZ_2%GYx}=V+m&zqIi>SCJvDV>{{4Mv+b23td~>;A;)Cs<rGMv@y4IZDT=>{c zuJVas+SysDYIzF68~Go~J6zv(PUNj4^A6q}f`tsOAv<F9KuZf+IE96deYuq|he!R( zImT!Yhi%u{XMbb6n&`1FVNQk=!+`~dK2#lTy3TH&@o43vrHnr|R(;JnXYrWFEce!x z3D<9JHt=O&kn!?#aSVCKl(&t=;q~E%2e@a%$eLwc(U_*|9kb=dthuwMR;tM)*G&mK z_{@k`(BCglaRIM&o|mn#WZ9nF+h%-rKN7yZzn}kYDs$#yW7gbIhA*x%dWl(vKW}VI zj@(s}xm#9JSd&F+)k~FGKet9~%@TEP<1w85C;0)3H-m~fm!RRFWibJV+jt+}&flMF zc6CSat{Yve0~d!?7MR9w;%3-v*O&64(&pET#WB@yw^r<pGd@|)$U2R|!_Fk*={%j& zXJ(uCOXu&|7@7Mx<#S&&$09~;9@_)+8_RVVC&*-6IAwc@E1~N2+B?~={_JRFS-4H+ z+8#!4wWg%3)<jl=En9!HMeSxV*jvP(ZWXhS>C<mD*Tv>)PUoDA6Mp+|$grrmb^P0t zwUG=uhtHJVnZ$c+KPUVAiCaWFMV0dx&fNG~ydt0L&o@oAqwDz%Lo51K8HD<~8<!gx zuJ5<zSNqR0^V-HDF{#Eb*$+Py1Gb)iBYpqksXqN|U#0|;4HA<L|CC5Eg{veyohOv& zGGWc$&|5lX>)VgBH>|(+M*2O|@+c;SI*<pr*bhCCpLOm<*RGN~AIzuxT>2sYanIpa zPlpPRgZrabI|OcdySQa?)S}nV|8HB@@AO`BiQy~fT*?1G#P01A@bdlrC+aBI;cE`5 zvwi!2S?+x}tJhaO?kIa#|D7qZb4owlmbw1Am`!BeQiWP`A-l3E<q4r58Sedg8FKG; zs)^lEwn;pje1FKOMDG35q!80l;&J!rghlc{7q96s-TlkGZoer<(}XhTk4@)Si%*** zvS#+0e^Q1~lTSV1)@=V*bn@z#w;Lupb6q!D^0{B;Ua6|Jmeq&n;`2GT?adLNzMuce zgcnQw(+_^CK9HRiwM=XVi%m9XL)+mmr)*WEV}2-pk-BU0=wqd2`GIU5o4;C{?jGC` zvflsMG}Z9WPsE>3n7^xCK2Oqr)n>I1dzRfhIY)J}N8z>0mg(lPMP(OE)2(fb{wv%K z75%t*sc59gnIA&)-!RP<&e7Yjy8d+8)Wk^<92pY-Cr)1fY?bn1f8Lvs^G>gDpO=32 zT=NyHRbRhczo^e6745#2=TuDe;yC*!+pb6M{hM&{-8Yd9yPbb2INcPJ<*cvC{bro% zuuYZW%wz2%h5j4CYt?2Q`_a`O>3%---3;r)llFXg+8Ohue>QX0<Ilp+3m<YkE>?f0 zZ`;mnHO-*xg1N=pjj=!LtFyGu>)4CR<Qe+D^kH|O^}}9_QH{A~(ObLSPb~Ug{=C1! z)4%=&-?TN7%CDaLu&2*T*s<(du=1XdS0_73rhor!FV?$%o{0OGz+bKZWe&Ug`-%I! z_hAoTwl8PX;Rx;zk2@VV9RBi+G46rOq@3zcDbaj3@-wnl#h8iD*(Jc{pJDU)_nt53 z;?DO6w@rM;BfoNfOqtMRF<-XK{R%;|CvR@A%bRg`->Hzinr~|ycE!u@YnsP8k-6_$ zj^?A8{A~@%^A!?qDt4S(e{37uR(Vzt{lDDTj``Rv`dzN`vrJ(}maD9)XY#8PRsY?E zk8PG(KYM!EyrY44_a%KgF@5o}eJ^KTUJw>5kW$WhSykt>M(U^EGv(eertUw!B;tYa zq&EteQ!FJjOg6C2$m{x9-PaVIEp`5nong|So%geI_N?2l`1${rYI8N)Lc@w|)`hp{ zJn(qBz%qYxWx0Cnt@~wS1`mF*Gi&ATU#A*4Q$FF=BIA(to0K|yuHBfw(5z?@cavwn zy@ct>_twQTKc9NJXrG<`1$TiBH+yBu(<<Y*eu<`7pWwT6x70`GW7L)Fa#hbGwoOfA z^Y!=|yO;k!%5DF<Ji*sGzb758pO6{!Mt?ewltcW3TAy`y9ye?(s1pu*w=(PX$-UD* z{fgJ?nDJ&2yT0g=tm3YTH)pb)<JlG_df{`QKC57LR%^qDD_#FDi%dvaXZ!W#3fCVg zq49PRl^hnbtM1Mh3Te;f>s2<mDcjKW^IlZ7*fweZlt&j_V=Av~mI?VG{d;wA<^T4B zXX?Jn)ZM)rc;)iMRjaPAn!8rG%w*rbNi1Fg0%t5A+P&F!qPzN)t<m;<1yKR7xwigQ zy{dRafN{=!alIc5_x`NDxudc10GEqJ;qI@DQ<!!x3o4W3n{HZ|Zx{MjzaT&PcCYQm zlgAA2udlJ|`7Ad>C8sc4ZAnV^>6wb}PL`EE`NXC8@H5Mvd#;kIBKPY;t|alyDiXHO zvvqj#_8epRI=gy%!Bd`fCCLZ=eQVe*XJe|=vTa|~pQ_g`yFDhI%F#QR(HAoHWz5II zGPXGr<G6ylZWb1wUvV<Owoa#fPodQgBL&yX|1={P<(P$Eo-<kgE<?O+LQasx=K~A3 zTo6mqUC8)^aecB{&-L~5=6(^7F<jc&BBgRI{8+ri#Gj0L)un5!W?7glZmyqFwsP^7 zH5;328~41I60dE2$bGu)<Ky?X2VM%DdFLVell{|GfjE<?H(tz~7O_|`PbYM@ql^B^ zRqL~k-I#Oe;`7z~eymwnb7qH~-8OUnyO2d^pRWG<`g6f~&Wq;nHCOvQd}r==g+uu( zSFwkgBeQklz8&+V*R}~Cf6}gdz;eq0uEWp77|w1l@)tkx_`6WG#rFT%J+J=G?^wV0 z<I#k=n^7Emp7#3k%XC(r|9fP`4~d{J%Hp!$+^!_~*8f_wAo5{)o$N<XDfb186Qx;I zSewG1Oz`HCUmN)4r~4Uaqp-%qO$$Z#>gu0#yc#FYtgzbYKw96&tvu^zpa1^q`ES#= z7tPCUh54#gvwokicxGZVN$bQ`rW@~q_WqNaykzB$3dubsS~(ThdzwGwMkTZ+7IQT` zJ-`vHDVtev^whEScY;M^f^>hUr%is8apU2)dbyoksVP4sZ=A0$wi4g}X@ggd;^!j_ zUH$CG-Q@p1-*4C^`@8ty(!{#6Q|7lg&Dz`3_wx43IUm{YZrXOi___J7Cx1^d{@h;_ zaL{ej-CwzD!g6E}B!1WDJY&c5hvT21*o*6lyxHrz>h#ji-`<~69O?fxwtb`7q8}4P z^k4QF6$O_CPuSLcPV#8U>04gw_niH5_P)#izSl3NDQ~$cJ?+k!z4QOtzDU^2*u^s` z$!qTPj|CqOJfBf|$ENB@Uhj`n-~Rrb^R?f7hFMl&N&1sM8L_$o9gC1>+jl!Z`<wfb z|A1A!=9`-;*F=uQCC=!xXxn!)Ou}qBLj>~|<E8K7f2o#a9;)J++Mp--$)|ayy_DSl zFFY$&U+A|oQ(eH?WBp;i%-zqYJKl$1x0><wQs%*n_w%_|ulmnkZ#`T1cipWAMX^7A zn5@tUH0?5Zm=b(vQF^Fbbxlsm=a-HA$2V7Y^L&$C<g+XA;yKyHX~v&#wCR@I-f2Jk z_kUBd9P8#=eafM_(?zbV+VZSp)ylcWAEa$+zo{6-JiN{Pe&vaTbN2s_y}mE!?Ynof zx7)t+f1leOn|^)1_+}q-J7YfAvRAc&d{_T;eSfjuH80<A!OZx?hy`l5IAku&n%hv@ z80zq5t>WXYMgGQ357vtJY51F73IBNTsd!P+{}X*jqUYOoTF2SDI&aW&&UDY7tAAjn zP|u-duYX<E*8ddq;fnhCM+?jSh5GhQd9&d0$*GE;zO6p9ugWNQ_l@%B2MyU5?!IR= zb$0x2k13a@DmE?pb5N&D+{5U(>@O|-xz&+JY_zgtp2TjN5v3WdJKMgWXX`w^se!eJ z)_uQX@OZ}WndPtc2A(cEnLN4T+kW+xsi#BM^L(s#xI3*mt>ygbGmGCp>3f`Sd?r8E zQ~aOFbGfqV>93aknUE_J5OL<$?tfBSZM4lx(q3Gd`RMn*Z{^QB_RIb|Apd`j3)9U- z54Cx=GtP~k&30kI-k&ElnqGH5R=M<N?($oUR`pf|w0{kpDgWT(_rAd8e=arqJV?LL zaQ)W8z>Tbo@s@8st~m4m_`4jrI3ueSRlnSw+pUkR)OZuqeph-j+xB;-(w=Qz-n7|o z%GvjmF9>W1UiYxGFnIAZ<F_w2uUz}Fqef)Cm6G=_hq(uw<P!HkU*dM(xBTt2KAYbc z6CbP)b28d+*zbgsX6S6G+v%L%dN$TcbJg|sG`XI3Tj}S<WGH#4@>N2=`L`9dkB!q= z=I&xVK0i9yNHyaNfAA;nhi!9{S|3hsUbs)|nzU<2z@rwKFrj=#kOy0;uCTAWCy>6^ zEr_+@{?SDRZw)U#e-{7md%(Al=PMF-zRGwdzfgANs@@esUGpc1vMvufdRP5y=ed;b zb3Ea;TaCHu5*HbrVr@TK#ui_4zg1(Bul@A3y&Ku(taG(yYCaYG{G-xak^8<hr(fx@ z!_Tf9KX`gpt7q2>zv-8cPnme$RrfY;_wkiRH^k0_i$7K{;aVPZ_*3WcqKN6Cf}gEw ze&y`DeTDtaB&|823*Y$g_uLZit+36iw2Qkr-M>z1!Tid?C2ePZn}2?^`p-Ut%|ddo z`FAI|1*yH+FsXv8;obqSNvZk!911#IW^JC;*}h-E^ygyle!(NJ)CHEu{|!(6y!DLy zhq~$+*00Pi#ZDFc{5P-GJnr}VhfP1Wl%*f|ygrfZfZER)wrabo{(fn9|8R3w-GeJP zuGKAEwCbArx1TdkCtdlus`W8z@GF}~nrw1~`^_Fap7!|N;kPR~XFPvy|Ml5j(dGj$ zdHS~PvN`(YWn-oN=gXn(kGHtTCD-35-M-<`b-4!xD^^uc%X*f=;#R-=P2#ss{$mn< z&xf?mj=mpe=4%k-?HU`mlTA#XHG03v<Xzpbq&sdWs(!pwIc*hR_l+~}eZ&(dcix*3 zY}{M&^h4{3qLkyOPxZ$B$f}J$+qGxP2SF<n1D8MzkGto5kGrYw%j`ZcRQW<CvF`k4 zWfgz<&F*&{{jwrcgg4zfIo1D<>z?=GA$?mObg13-D4+8A8mqXQ?)Clq<PL0_|4Y)R zz4c7H@S6N(#q!2|d+mR{kWbhq(mUN&^+hUs-@AX7`+a0(rv5y?r&vha?5jX&(K7C5 z-`QVVTxNEvyw|yX^3%RGPxt)#DG-+XZt1r03|rZg8y~#7^t2#$qk;9=L^d`4J(+xr z8+eSRi@nS&zUS`Px#y?Zvyd8(uJ&wq8!^+H$=-c@ev5xjZ@m?BtVclN@7_E0mv{|l zzOm2d4{Gf?_+tH6D{VWg9pwe53qLP@R(bRA^T5Z!hcge)h-Z0HQ}fc|@K@fbn7>ad zd~KYfI^1nkT*BAB&t3e?jdwxS=l#t;%97_7=<i;Z(`>!&(dSNeSKZsT`7-CN<N3u> zKmJaRiOgEE#Hv{7rbN`1u9wGkI`k&YyT<Xrpz(>vJX7(Rt_F*J&WO!8Z1rIAG!X{j z2B|YHUv_>@cs1?W-5J5We3rZKN0*%HS(E!_eaXi+%au(QuF`y%{b?)9qI2#1dNBuC zn-|}ncU|8q`f-I9Z@<N7>o-?y<Si<zLab`O->%#9?Y=Tknr4VFYv=THd#60SyRScL z-S7KWefP`7Uu>P!5G5mYf5Ek#$ytWiWxl%bq*({cKUs1%c+<me;U8}vnY{Sf$J5uC z@~YmQS+My0Og)MFGuM4QdSk=suR1$loHu0o?Xm6M%LIjnSjWkFH?PH%Nb#uaa~vr+ za^PdfgN2Kpi7>P}sD9vi&=tE-vEcE$XLn~@mS6kqbJ5w3<BQc|H$0K3nH0Qun^ey~ ztM?lcuKo7kr<t|Sf1i0%uXUHxjQGV>URCvnF7(}Z7uB$ve?*l(PDCbl>*dL>N}hav zy#B!+$9y;4@YLSPGtbYLGb!!KNt%01+3kPj@$+4?-XALOe`NlDk^I{!EA9OsEZk`B zQtHLz6ZK*G0{vqvZ(2L-c5@1>c&z{2UG$CJ{3C1i=dBa;U`zG7COX~Sr}3tohp{O4 zlx0>Nr=^rRq?8!knC~;)HZ)$(pOnAPCFe}08-s>jTS?Tx`Bg6Ww?1v$e!QjUpQht) zo02S#v)`ZCy)TS;ufIs>e$VrBS8n{v`^&YX;j;b?yNCZKFLoF7t9_+Y7W#}WT<zD@ zvf09sZBHlrKRTqi{&>!;=y}$yQSn(9+66i_O%A<lm{S^4bi>>5Rdw6En{TSF+MnJ! z{d9kaUG<0iS8adRymgdnkL{QcT+8u&PJwaymwvgp>if})Z$wX(eAMr8(fyC=@4kxg z{D#Zov**tHa$ZEozlC9k)W*v%4T4v0-gQ`J=}YNiv(zu)H8I6c76(qY`}&XLTS)55 znfK*I({_0IW{7U?-+fu-<In9siYCsBI)C=KedFyo*%;RqY+ACH-`<zGtX;IfcK<%@ zejQoib*FC4k%{=A{dD{H6qo+@GroQE&AEBmFv)KBx1}FXObSfA)t9rKm1$Pf$8Yx> zQtrj7-;vt7uY6yX((hHqrk6YPiY~3*@xP}sW%(QCcw6-^eYxxQeLR|Q@fl-$k9N+- zt8*UbJ#I^u>zmboUAyr3YW0;&5l<fbePk8aU1>MnA!NC}r+H#w>VXOS5BmOA*gN^= zcDEJHC3jd3ggj6TezouZVf)hJ(`IuPO?a#GbdlnEH{Y_~+RHO+{^#xeE5D1wL-ud~ zyMLDMCEe?;-ue5iGwVWE$7=iJ6ZM+)4+@saZSE-fZMQLJ+rFq+yXezT4$tqJbw8B* z`0Ke-%+x34JU+_3{L^XQ;~TbXO>UBm4-DqMTcrH`@0{s=VP|Cn*X8|O`lj|l#;f=C z4UMh#9V<NZ*ZzuTzgNX3UU&W`^FPtp2Y>Hpob|G2f6nuJj_r5ZqdS|Yb?g;-wfbb? zvA&wy;Zw6VSg!go@r0M`|9xLn()xF{mtU6=H=WOZ-)`EcTU!pSI^3>bF=v%~|D$G4 z;R!Wg5B_2`)8M>0Lq(GH;Fet8nVK3RlX`u91sPmBww~fYa%F1FOoNA?pMCw{9`cuU zah$2muDAb>?5=;*U&}h{rQ-Iw$aR1IznxoM5OP)axczUB6T(hSh7-3OJhH6S%pvDe zNC0DNly%3|pw-J**#f1ETUYi@Q*+iini!(9GJ#=s-{FW$?blK!cue@DV`0X1tU=jP zVRBa20^dz4itEqbeJlUHwz#~Qd7{mp`!nY%o_yC|eD2=;_j5j1*VL=+-hco2qn@{p zPv2Fg8|l7%)Le7+M%b%)wH;l1;)APx$gPX~DmK4bDdg$&DQ~MY*_%(*?6>oj?7sZ) z`Aqq#541hi)jyYp?Tc~<dRS+d&#C-<+5;VnrMuIc4tJhrO|3ltasG3$M=v{+)c)VU zQa48_ZK<al=Rs~eeeFE1eSP_IzuDH#6?{-2pnvxJ)%oH9d(7LH9Qs>v%X#7UZsq06 zzy1E2Td`x#jTL3B_xTsHw{LI0y4|+<Ly660A^#6k7u5@j|J(nd=u~?1;ge4~pJ(Wu zO+31%NNoQXmHYR%u-4~qPkU?1mY`yiFj<+^_|w|B_#g&-#}_BhE^%Q#-sm}vO|(+? z$+a%cK4;#}4~HMVe)wlq%A>_+<fp_P^t|);b>`dN$sG16K^=v&WPV(*Gpu6KmtQyI z*prIaS7-U=UaUz!oA%1q{Dr@Sm&7T@+rgTSH=EBEtjMz}x7pvB7jIFtZr}g@Najf& zBW@OTegE%M|M#Mi@WTb~Hu~(7tG~AC%;$L$o9cE?J@zf7cYEv?-9PWxkFMEQ{5rLE zYxeyJw~Oc8k5=xRk@>UO{robc?7M7M9hX(CT3<)bU~8WHBP;p5aKPTcMQb*<%vbnS zz+%Jb!tBl1pZe5)CU^gQdAU>TEtl!f`4r{wl)d87Qu#}_Y|R{M>|EBKHuvPc8&^Dk z>B22r+zW~m1%>76X8t-a6tLs}6YF)}rYx+Xt<#qO2#b{}JiX1h`tIhE^53DyWWzPu z?KU0L+q&<O-<<DzoeHns70P6Pbof12VEm+@9E&;Wo@vF=D)(czwjH^XYhrfX^K<E| zNejCEMIMlyz5Su+8ubNY`!_ONU!>Lb?_==CCn^=1_GYW^pP!pC<HV76vq_;l=JBmh zQIT!Ck`npReb%RD4~tE^xW(RXt&;j-opj>EHwX2G;E1z&T%9fKWifXA|HW7Q;fUkY zn=5@`<+pPyQ#O6(R@t?_Fv#^rh3R1*zvWlMS~FKJZ<SM$@qKb$=UJn4`2?edg3Avd z-#IPf-a7B6=iAdZz23|7N00aXo;O>=e|*@o(BZ&y)g#xBeOeP#l(*)=?9TKKzV}NO zTTl7L{qc>pU90%_JLgXNPriD_HraBu_mYq~lZ$3FRjQ`=Tltklu+Q_Jc*U${>h*i) zQf@a!XTI*dmi}K-TW;!{+T}rWUkK?<oV|6bYUFwY)sH$0-^HD)PFnF#W9oGNGY`Hl zo>}```}o_Z84X6)<6gW~GJCS$#wuC*yU*?8ydQgAT1yKbKC;MqHF@QVb4%WwSX;ss z_^jqHpL+26)yZ%F^q%pv_9}^Be;$=&`Qe~Q+zr$ISH|(eQ=_Nr3#LZ=7u@xE_QGGR zH}+o2iY~seMQ?I?Zg2a2SvLMKzO|3oi>`RY-OWFGwIC_A>_9>2rAf<wZZVB})Z9IB z%Kd;Z$;SehKi>a(;+$yNOM7<)|B2k^e`<|IRQ~RwKju&7drxHDcx79(W^C9W7Q6Ld zj#^!LB$c~u(Zv}jQkL$GeKj}kMc~huC2`*jm=!ZuoVvC6Or*hwzn;mH-(RSGmi;K; z>V(M}f&!I2M(qpU)J(}dvc)L&nIL27*^v6KMJ%<~?C&gjd5YuJz7*E|{!M15L$_Kt zvVJ<V_e;3M6eE7Iw~~wI-aWAQ`ts$o*F0ppEv~1iet6Eb?1Q&#%H)1;i;7sJ@js&0 zDtCeG!S&Do2Rl`M+Ao?u$=SL0so90v*>5bmd>p^}a7%IJwnm-KT)=O>Wn+-gf-2t> z4>y;6Z5cm*%IMWTjh}DH&9!vai#eZP-LB_N*;nVg!tjE{-#XsA+oR7bt}vZ*>%F7% znN{niT7P)%KKW7h#VWpSOPte->)(qAWb3%@mq=P#$`HQL`;3ni)6w#Wsh|JY$ej#& zIqzRsv3d9ZU+h&i$yfAmJyg+sXR=(*{Qh5g%}Ae@_beafElB+(Yh3oAMWD84Qhf2B zPpjFrQ`<LQVAo&Z<J{~kTRxvNfBv-1=MT(Wo_%5E>89O18zrB<dh*3MUitp~z;%WD zj%{4k<a2E4T?v_M*Xy?=_O9Nq-N;|CQ@4egy=c2c3bR7Nv+0>WQvWx;^Z%ayCc*Dj zqR^-NA^mgD3H&QrZ~66V?CUz$ryF@VIHz`bAA8yDeTR8T<2754bq6yg^Fq_=i+nw8 z)?d1@=G2u^jxsj+<)J(OZdAE#u>b083+A(7<s9#R3UQ`3{QsTuxU}G9)1wQwrhK;9 zzGUC(>hr&OuNN0zjM6LZ6`Wn5aV1jdwtvPFHP&xj6+iZOu;*?_;d{Q3cbQN0&Gjc3 zel$xrE{wjjW>WK&bvrtbY@GkH?*HulHXch(AHK6vepBg9F`=ZWDf?wDEa%GS>nvHR z8}!F@hR+wlm6?Ym*XeW0zVo%nxgjybb<3Bwhp(AG{49~n*j_O4XXey9v*V6_Sz@K; z63?=KKKI(kmLEO2cH5s=wkXYP?mdIEJLXCqo6R9CXYu_6KjX~}g_U*;4gOEm<2hcj z7g#*>eE7=mz?8e&y=ysbYi*z0n*K&N{KpF?_i~OCZM?c##Sb&~M^3l<zF}^|nmKj{ zbSr<|O+FyLl7IKhHFKQv8Me&L=#eeYJ-Xd+R^a|}2l3Vi;S2)r&wBSe9NMyQX26Aj zDaSH2+73wQ9S*CKUMzq7^n#>`S5L&wT_gCOQF7W`ZbiX@T&pF|V<In~J7~bw=*MrC zQ=?h-tF~a1j9+-;@<v9NH&PAp8Ky_8-rGr=<@AJnVLII?>oECd*iDurw_c|lKDNSH zbpubp36Zll{|gW3JcxA>pTjF{=4Ljlk>!Ej+E3o%zZQ5fZW3I%Kc9JB`VC{vTN^$u qbypAIo}#$z)#k**ZN2+`*h{=tvpFZ^SHi%+z~JfX=d#Wzp$PyB#gTph literal 0 HcmV?d00001 diff --git a/Utilities/FLTK/fluid/icons/fluid-32.png b/Utilities/FLTK/fluid/icons/fluid-32.png new file mode 100644 index 0000000000000000000000000000000000000000..38efb2ea25054186cac20a089f7daac63feb7cac GIT binary patch literal 1587 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`MwVKyBnAcswj^(N7Y1X7nGF9AFp1t~ zU|`@Z@Q5sCVBi)8VMc~ob0ioT7}!fZeO=kFGIMd8sBiHX`O3h+z)|8FQR1ARo12<f z!tm|PwEYYWtZO`7977@w@134qFy*S`@%sE5IeNQyHmKauIWp5hQ7~Cb(<fM`WSOYD zj9?U7w?tHCkiJP@2}>hibmrE_7E_{@@p>7sxu?83@Zg4!(NWR%DK8>a6ip0IZCaor zz@(B=UL0BW|L=!)dWt98^4h=re`@>O@_ljrx#Dw;88<3Cm^!%6roUTd&R)o{{!RUY zf45q*ZroVBLTOjy$B8qY7&dHpk}LZDuGc^FSqzKw6<)iRx3l>4safl+GVn1t)VyZx zvq^%Bw$%UOn|HTgg6#t<U+U%O%&Z3{aojWWnCtT9g#Kh3IscOPsxPm<-^%yjxw`uI z1^YL5b{fkVNVYwceX-0ud-bH>#yjR4erkNoaCvh5ZPn%3>((q)FWFML>ec>pVtmHm z*!W)lwB(Ch_0LjeS>t}`rt1o+Of|b|Bi8SoI(2H1)m$xoeensh**A6__M2;8A9rBK z!n#d7$_Ka}yle0duVUP@F{A$O^Ut1>{(ae)>6)0h@Rw+1$&+W#ye8eV6ZGufCO7rj zyD5L__BWI-{+O3uJ3Y(q>FPg+<-0CjPScVJ>aE^(L*&Au?cX}Co=tkBb9csz9?3^5 z>n97<PrbKZ+Tug^aZVNgBk$YY%cdLK@0~N}<MJOD-$-%YE1I2C8&`2LE|H;kO^F}- z8JXkiUnj49_&4{~`3}X6D^_^;Ee{S24c)a<(>bB|X`*kn=_UUp@qp;))pfj@s~TpD z9W&p~yI(G};cgy#!r?prbvrJfpJyvwcra<>5wT`T<1~*+eOo=|+6Ea&h-`Sj|LJ?K z?6^ODTUMWwd4G3z_<=XG4fj9$SW)t;>&mme`(|=&Yv0Gp+FZ8eV!n-O=FNA{3X7** zyvgi%@WqmYQg_Zv#2v7+;Fh#Jdu%Shk^R%kzCS5KbN8kh7nUDbvd_Gr`~drDqlD)3 zY;Pnrb_lnJeEnI|doyDF@Ax{$=j)feTJ+t_wme~T#N|cD%WYQ6|1Vs-^XT+_+7H$h zc;7zC7O!=neEFZr?|sSxtBV*{$L&A1_wv7^kD9*Em>GGzaoPLeyC$bi?9w??o?W|G zcFCaPhwsGi65mtzo^N?qA8_#(7t5au#Yc4>{7BiL)_gx*E_d3I*Jai{`np?cxH5w+ zDzq3M$uT|ln8Lz)Q$DCyLi-AnjrgZ}H37SIEL#|lH<&KWKGd<W^#8%bzi!sO?EJ1; ze_+kVdGqFdST|p2wfn|HdEQ$L@<ddk5<*r8*vk1=+_k^N7V(C2amB}b(w%knF8KvV zcsE3?op`dVwqO(QvSaLrmc+S99DMdHjko3YTfXZJrAtKA8F*DyRlC|sUti<2VDH&^ z_0;s`%a^a-xbY)fE9>p0`BOb#^T#gVx^0`5va++oOI^!*jgOBWJ?dN~Gv&%V?pVg% zOLX0rI_nkhD|;KonEt!`UBt%~XVZe6ot<4Co~m7TJ)4iu?Ae6Vdk)y%&R@H9sq4#^ zFPXX|mf7>Q@UD3HZjp^xsDar_rD8R?hZU!NjxFC>{3gckU?6AnjAecQWWGPW{ZZPC zL2dc2nP$s653h6jb9MHDZ~XC0tOu?>%oEk#c+1x2=7jXfJ<ZGCRZf-tEcW4Gr%c$L zuWF~&|FSJ!-)tSUU*X^fql0CAM|S8vD(PLf+VPK_yvLJNx#X*NQ+4M4F#7i{E@A_# zSL{udB_&MSi^43vPjOkd#iD6d{@&pGWjVp8o_X)OHCN^KWWT?wUa9U4v-SV}cd1k9 zy4y!D`~JH7u(ayodhab8_5_*s-t_wMG=0|_-^;nH|Ld8t{ysTn#@ChxHU&GG#?Xkj zwo`T$MMj8i%(y3_F0RM&b4jw|>Ca`KXJ#8oCNt}ty?I#meuUW5f4#fbzdMj-tZ{1f z1E1q5MaEJb0_T6p=RAHg(`VA<N$m3*`2R@G%R8m2xRw9MO2#>9OO3nNR6hJJvtM85 z;p%N7r|dM<461H@b$_w;$jtr+z3*eqoYvphbx`{szlC}Ae`cTj(ya5cr&cpCFfe$! L`njxgN@xNAIf?|S literal 0 HcmV?d00001 diff --git a/Utilities/FLTK/fluid/icons/fluid-32.xpm b/Utilities/FLTK/fluid/icons/fluid-32.xpm new file mode 100644 index 0000000000..4b9ba19a9f --- /dev/null +++ b/Utilities/FLTK/fluid/icons/fluid-32.xpm @@ -0,0 +1,67 @@ +/* XPM */ +static char * fluid_32_xpm[] = { +"32 32 32 1", +" c None", +". c #000200", +"+ c #01162D", +"@ c #01356A", +"# c #2F312E", +"$ c #035FB1", +"% c #0061C0", +"& c #0071E1", +"* c #007FFF", +"= c #247ABD", +"- c #626E6F", +"; c #777976", +"> c #2A90E9", +", c #3291D2", +"' c #2690FC", +") c #449EAD", +"! c #5A9D87", +"~ c #70AD78", +"{ c #7EA3C4", +"] c #87B556", +"^ c #6EB8FF", +"/ c #A8ABA9", +"( c #A2C443", +"_ c #8BC3F9", +": c #BED831", +"< c #CDDF1B", +"[ c #CACDCB", +"} c #ACD7FF", +"| c #ECF408", +"1 c #E5E7E4", +"2 c #DDEDFD", +"3 c #FCFFFC", +" ", +" ....... ", +" .-//[//. ", +" ./^^333. ", +" .{''231. ", +" .[^^331. ", +" .[33331. ", +" .[33331. ", +" .[33^'_. ", +" .[33^',. ", +" .[332}2. ", +" .133331. ", +" .133331. ", +" .-333333;. ", +" .#1332_333#. ", +" .[333''^333. ", +" ./3333>'}333/. ", +" .-333333232_}3;. ", +" .#132}23333_'>33#. ", +" .[33^'^33332>^331. ", +" .$'''*'*''''''''''$. ", +" .@*')>{******,***>)&@. ", +" .+&':~(:&*****:)**)|&*+. ", +" .%*!:&~(&,'>'*>**,~(**&. ", +" .$*':]>:!!|&|=~<&]~<!&**$. ", +" .@***:-'|%~()<&]])<%|=****@. ", +" .+***'|%):=(!(]>:!(]!:%*****+. ", +" .&***):&!:=<]((&|!~:]<=*****&. ", +".$&**)~!**&**&&&*&&*&*&*******$.", +".%***]~%*****************'****%.", +".@%%%%%%%%%%%%%%%%%%%%%$%%%$%%@.", +" .............................. "}; diff --git a/Utilities/FLTK/fluid/icons/fluid-32i.png b/Utilities/FLTK/fluid/icons/fluid-32i.png new file mode 100644 index 0000000000000000000000000000000000000000..d7581d8c82a9b6a6ba6b6e110481f3f6d0af6eb7 GIT binary patch literal 450 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I7G?$phQ^Te;|vT81_3@Ht_%zeoNjdtX(t() z{wL+->regdF!N>jyb0wS3l}V2RJ!f?yh9!rA1j<Xd-~^}UrcN)HLhng7#J8BOM?7@ z862M7NCR<_yxm<GI#^{rK&BOVL>4nJa0`PlBg3pY5)2Fs>?NMQuIyKtxp<gZ-_~4u z$iTqJ?djqeqH#Vs;Q-%{|NsB@D}6|PclM_SQ~l+8d))<ph<2%cD3{!IV0ZcVi>wzy zb>jNfCd}$r`_R>}@c#v#r{Al;zdOmU()j=Vy|vZP`;(3YYp2-$`Fzi|yXw2p!sn;0 z6)Lv!t!w`;f1#z^`|-WQQ$E~h&Z_uca@Tssf#nY#JO~I@xX`X8z<1ur%*@Zs&%8zB zXMRmh|E7%}3m;3RdN|Z?x^X2pEp1KCwcH&3YYTJsmR9%r9b4G<_?Vl5t$c5841ekM zj4kq3896%qAs=quaQl1V+g+=xZ`*r%-`X>jN~|}uFH0)-Iog?gOu=@3&)M5kr%vtd yX=J%jRJ)+Tb+RGT3*(v)C&o_?D%_dm83Ki;KTx}#6T-m2z~JfX=d#Wzp$PzeEWkAY literal 0 HcmV?d00001 diff --git a/Utilities/FLTK/fluid/icons/fluid-48.png b/Utilities/FLTK/fluid/icons/fluid-48.png new file mode 100644 index 0000000000000000000000000000000000000000..0aab52c6369adfd41c2e93e07deb2c68d7cca80c GIT binary patch literal 2763 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`Mg`WBf(#4{Y)RhkE)2#DGa3FLU=qE} zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns}TW#-~GVNKKz1?l7{ag8W(&d<$F%`0K} zc4pds1_mw{PZ!6KjC)sSRz`%T${n|V9;a8}_|5eouZxp`sHX2xmgzy+MLCL>46>zO zPdwvM++%VyXVvnfyvvG8PHi+gSyn7L{Yc84O?&ii?oebok)~vQ@2z?LomSbxJ<~qd z&ig&5_+91w@7wq7e`<R{u%qL~yU<+TP5TXIpB36Hq~<$Ig`q2VYNKSeWliFWr<%T% zca4;NIo8}blCZuv#ombH(i8pgXD4)&f|vW{o}9`Q5+1%?&pFvrgyH%0SFZVGi3Jbx z{6xMkt12{iJ<8PlqL^Rs{U0&gIsHLvOB(I!r<jE*D{V?R$dnnZe0HNTdr?u5)so+q zW?X8MJ#Wccmc5BEoZ;d(B}&a@$!*m<Ez=23vvlrGm+-nj&vnL`taou6S+<_?3Gc7D zCccM3D!jsTvBrVKODexwUr6p*<ek6eSm}|E#ZSxbv6r~4y}REkbN~9c9Ial06X$um zHr$h)nUM3u!7f~8?t}>ny=orrWixWDR42_%pTA{I>~xO!M0Ewl(=I)3$--K^VYA}Z zHMi@k*47)T^-ll$es^{4$z|7#AO85|Cbriy@YufZJ6EKMpXewz^E$L^>!+{&$*DhH z>0Fe);uO_v!=<o<Gg|GwXJDwn-aY39u4n5r#LLSZ*!4y*C2Z}6x8J9WzRtOGYST(y ziF^CJ!dl92#F{abhHcBSXMXTrqy9|nYT=!!OHVvh>OPi!ZjPpdy}RIwNogKlUP20Q zyoBdkc^tS}HhGuuwmEGdepNMSxqDuSVes_v5n1qltDel8Cr?u1O}5_=y56;x%ew5% zjFOVm+uIJUS)-H5t^Y=#vTXI!d#6u(H$1o|mZ_^y=Jq&DW^NpF!#$RBSsJSw8NP4Z zscBo;@Y%av#8mx?&7--GAD%sWX7$4hCZeg&zkmMwII85he^3PLu19V0Gd`x4JU{!Q zEAf2tT#NYke3?Qm$6^~Ap0VsHC=$J-((>VB&-<^ukN;WmPfZsWtFf6l(Qtpk{%9`I zV%vo;4D8k2Kir&Hc;#I2(bH3$j~%n%*mA2n&eY~(t!BZsWs7Qk?5$ePO|yOc@{9J< zm5eKbPdhAbePvYey?s{DX{L8`7jEO(QWp@Lvh&sI1H03`_wHTe$~ez`X{G4-b$#dE zrx)#1e84t`?abMxyNvCD9GsjJKUqz*YK{qI%HDo2lV@wx*%@0ee1E$-eVy~cb4QQ1 zx+)*M|JF({U}eZ1*?;?2Zg*x8S*p0mCG7xnxS+Fj3bViedA7bQAD-6ByjfmYSg5;b zrSjer$B!R>zAMkfP^wo~WrkhtE(ZCy*N<GS%ie6zm-@TzL_@h$$B!RBVuDjQYM7aA z<GjA`v<uVyjH_bdu_u3PbzMr^WircE$WCx)j>yHAB}^glTkn0X+S}3L6LI~*fg2ml z?+3Ny+T~WxGfM4ZSZy_HviG0m_0l(T4|sS#TfgPWlW(648{TP(8@zOGyz}i&iQZl} z_P7@|lV%(UeUbgmaM|-HF72hBcI&SH?^*Z2XjjsTHTK>$+szZ=dR3Qi-^|YxV7>pC zvh@z-678GSJt5O$ABjCL)%_N-;Irk9DeMlBTlE8H^)6WP;QVh!ty@>DGt(4(pCt88 zS4mrPYSJ6YOE3NBpIU0gUpQ}Hyvu}!qv@_Jid(%t>9Ki#d-+f3#}j*9U&mP-6Tfq9 z*t3&`)yF!+yt6-=b!O#ekIui+SLF;Vc7{ECw^+6K{Mwic<>`+P{#$bYvrKbv{KIJz zCQr%A%T6%<SR9a<#`MmNN&k}hLhV@go2vr&=D+1z7dIt5v-3sJfpv=o_k3+PxmG9c zAGF_e&-QGQ{$n)_-Tm@2&a(WFn)NEFPS@;u=!J~d%4wg17GDy6Rmk=BXRb`)d{%M4 z$Ws%&cRmp0xvJVbZ?{wELf7x}?jAh3Gtzyd^tB`JOAqZWc0T)J)_IBlrh8&-&VOqE z?|Ut~#dK?B#JakNzU$YjeX?lq@Sglk_R$Z4$XK3Zzn-r<p4nh7aCL{>)<Y~)n0`8R zZspmPX5qyk|Defjap2Ko$ArYhj!jT>zK~(^jZs`bZpnrX6W-q5Ui{@nU_;^oyF7(C z+}zxgjrVuCq;-7p6z`1G49d=sY7Y(y%8@*x$h+ZGBhw1Tx|J<b%o$fE#50P1J^SZG zO3{jIb7Wrr&dbZ|;c476WgGj{>C@w{W?s+FWL$bt@pV3%dz3?FO#ST%n?yI&Z<M<h z({_+g?7&2^g0Ek{=6-yB$YO>7<4460o=jJ+UcJeDxi^h5^fB8}x%jOc6xLn!jj3H6 z;lTWcY05(9_PD|iQ#6Bf*52!Hc>Z4YcQRx1`t|FlOq;e%<DIsC^tolTpEFH9sq**N zSK;ikx(DAAVi@<aso2`?y?QR?q}{~E_ffOjJ4z;AwcjE$dFD*bu0<RLC$di7XW7o& z_TfW;rlw}*=B-BEC#2?{aGu|_#{S+j15JJX>Hq%z?%rzVwd<Z@xwb;Lm~PfZb~AgY zEM9glmqkW8VK4W_Jc&=2y0<oJ>#4Nf_c>ShDI0RF;N{|)v}eyAHJ_)`y1#5Ry81tN z;?v)^#SSD0dH!=#c~?7eW&9SAi1pXK-{0Gt8?W4Ey-2F`(5IcrO6B`l52tOFJttyd zts=-RbD}}_Ji{h_iOX>}FV167Zjh}gyKL~5p@L;`!n1C6^`bu^>PovsmE3F#1JyNl zy>R`1-OMpTWW|+Sqixl%IFxGY7X5D0;kj4)Ho1Doe6`mbFD9&6e7!q*!D)saF^vBu z*!IseWBwl1?AHFNf$fLb4d0qsZIM482>PtJ9(nEl^aC3n#O7F7%xO8lFX`&}l|QOO zKHXvW)R@b}aY0O2dJngLsG;7fs71_t50`7QY?j>m!t+;(=|$~t2_JTFhGhMT@%HTb z)3HO&n)B=F=Rf(?8`HxBvJae<pJ&JVc-qQ_^$ofWpQo}&@Lzc#XEAAtOh<f1ePH#? z*6PJ(n{pmU^o8^tTT_&JGPd|;nMGG_rSQeFO9g7GlU_bt86qO~@t$q}reZG{(dB)O z8|QubXlyY_#`)+@nWj738nYjt@0pNdw7)m$)q#GCl3nW3el{72dkoubm_NThu==>g z0=5|!W-;Vl%h@$k@U!U|O~&^Z)LyIb$8~xcPMY{tp`z^Z$LQ-qk_D42U(2~al|FSS zaQ&i=c~AJ$4C^0Nsk!GTe4Ev7`0JbMk@q(KJXP~sU%x;8pj5bh-mbZi)Bi+lsWm(K zc(a7;Jl|KxJv;Juxc=5HTcm9>n_c;tb>!NOXT#W5Hgr0u&b#|)X0@Q3Zr;n_Q>pW0 zzLekl@kmc=EAs)*(+BkI0|Hk+eRe_U%&(}XyPplZyH0LTFJ7h4P}OX_w@Evor<CW_ zr+gkYQ(LR>1hW@EL(J#h{`KV3v)cSeX(yKMIVS7xe;|dS*m~`!6-Nzz+f=mQNnE@1 z-G-X4-}yS#mLA<H;?Ey-uH{1ijhZBp=H^W^|NNWn5x}!z?K+J#Z<!5KFZRyQ-P`zg z?$*g6A-eNt_rK+s)_Q1Z%v`2F9oNzo{Qr4$Kjs%SxDsXZ_z9PvUby>{s)aV}Vf@Xr uCRH7M<#xHDeT}=)fBqFrc5Gq)#ILH`zRh^ZYRAC9z~JfX=d#Wzp$PzA`7EUX literal 0 HcmV?d00001 diff --git a/Utilities/FLTK/fluid/icons/fluid-64.png b/Utilities/FLTK/fluid/icons/fluid-64.png new file mode 100644 index 0000000000000000000000000000000000000000..9157ccaa9f2741b7ce4b98cd5559392e0c23c71f GIT binary patch literal 3942 zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4mJh`#=Cir9t;c&Y)RhkE)2#DGa3FLU=qE} zz`(#+;1OBOz`!jG!i)^F=14FwFtC?+`ns}TW#-~G*8h4HWFiAciEBiObAE1aYF-J$ zw=>iBGcfSo_jGX#skrrac6G#*tGf==-#=5(p2*fH=;&y8Ry$>xd$Ibm*cGwSu9pvA zba@*xE!A%3vui0gDo<T`v&lO1saSCN#GTu(mR;X=t1GDMnX0eg=ceg<nwXf1X3zZo z=i}J}48{f%GQQ6FUb(OR=e6zEs`OvSzOT~f&QN=jb559%ZRhKPohxEkI*PA5y0|p- z<?X-stIxuUae+mh${G>Pl`RVL*6X^{Z`vCNU1WG5uQk8-+tJ;>if@H3n^gNs>o@lw z1{X%VqdNRWPkDYw9gJdCO;_AweYX7<%dRI$x5Rx*R@gT$d)Dsu_|L*dnIhpZukhy+ zXKHo{Y6RUsqxATip7?)tBUhG_XL`lYXlb!-<_O~!dD3LZ)%D5YIeVh{;iJvHMY^%O z%S1Qd)amT(Wa7zRcSEmJnBn6(tCvzU9rzPOBkDOCiq9TgXIb-OgE6C!u(0wxKC$o% zpWjM_@$HK7IMA>8JLTE2=_hQ3TR*+fn_?1hDdF$JhcXuVs=uy2HZWXm{cmAVJX=#_ zZuIAm+xHZGmvrO*JF%EG{fF9i=~jEu0NeA@bFZ~cN^73^^PAx*JJuULkwOd_r`sD0 z>I@aqHb({p2Oo{xY1{Vm^K<KHj_tx3cWODfxRS0fmecT2KE>eBem%;<@%FY{#uq}j zoH*0c(ya2Aq;YR-)M7qvBfICg;S2j|-9OHS*FS&$oLk`Hl?Mx$+4)Qkyo)&Z;ll^E zH5#S&YMNCOBL&sF7Cg}UlKb4rOw(&_;Vi3VUw$h2{rkXJd0E73wZi9?Un;I@6Dyg_ z`~x=R?^^s-{a#z-lk<_9MfauGpL~A*tAJq2<B1E6l6>0?zHWFDfARD><+q{Pzf<}c z)Q&$em}jLk!_`ZhxusG}Q8jqqoy)#16Vm_fjHuGRsby0fB=KFplxZ_Z+`qETxo=c_ ztl5-A?8G|?12w12X`W=fAVX0_tYlxoQ}qv@+7*_!8fd@Rp&3}aG15>^gJmw$ud-K< zc@#J5P4~@QxQLJG7<25LTjv<08?Ua-P2Y6+(xsHgffL2In_MVke3x<U<3%PWpSZX< zn>})I=flpgtxCu|m$FMtKtM)7;K0x2ckA}wy2VnFx%F1m>Aj+MCtJHybtgM`AJ~+4 z*J^tE_E>hOXyKpA?`+rwCm!t<-~NW-%avpPvrJa<9a_>K;w`=J#8Q>G{b3#QIX$n} zs>g2M|M%PN>n>8;IEB@&`0T2hf2#1q=||TZyCdENNd@0kEJ){cXU>-WC#Cdiap0Ag zB1i8!#(ba6Tz}1b!%NobKVl@6q(5qE6$z?@HWpVe{9-d{Rb$iPbrZv<ueRHNBkLTS zVfK}6*3YcYIWkVVBlw}?u6L-!JiY@>3(s#%xVu-N%=r1`M=uTEigI+WRrCrH{qeC_ zB-+&IzWkm)0-MF^?i|?W$-G0mRIR0~*lI7!FZ-?MBF#-qm;aow<$IP(UVG&J>Zv#X z&*6=d_i6muBQxpv^v7+6-`6Wk6nd+*`^|oF^X{qEnSy6xjhn2k@|G_;)x9+Mnt{SE z>#Fkg87ta5^R2v<T}#&spW#$la_x(ywQbXPqxXpq)$13m`OCcE;?{G=%(OMWC9L?t zR{3FfUIouZp>`DsiR}8UZwwpG=Kbx8n%t1_pk@Dl`;#Y6y12SB7X12>xoPue%Zd*V z&VSrA>-qQnJ6xaKcpB9m9vFC0>GEx%{uRgAJt87+hlPY(QOb*QaVXNi%E<Y7eeUWN zD|XZ!T(5m&clrCT(M{Q$_OlxjS0C6SA>z8zkVPcaq1yJ(?-^f@34BNhH~8gPAN;d7 z^w63$YhEvE@qHE=HTU<gc^kR^=VxXs-d}$;YpLOe2pvA9TQS*BCdaO=y%Y3x<BhD_ zVQV4^&o&DyD_B}u=5cCht-mcNCZ^_a&NTY_&f@30#CEP#{8aU8!;|#gK2>|;Y#Pty zuW&rw!Si+Rh7A{#Ycq1B)fl&niC^E<9s7@G`#xs%*g1Rdee1A2;{P|>K%(ON-Eu~* zs7HdV3`;i_f4lr|S=?671=<2nc+Czxc%69d^GAUd8h;pH+?8R<`69R8peWRLO7q^N zCuTaq$=j-Y&9?53WHykFcyLlE=dkvHzL*t17MqKww|ok{r2EFVvvrlxbi;*9vKG7u z@x8ohx4hbWPT`O#2QIra#IZ5WR!WdDXs}$$ptJL}<h+XKiHH6_x5(|edd5SZH%eZ- zC?sH>9n-x=Q<l48d*?^K?`P7t=XlA}{G4%$iCY6(MDBX83%XAjF0=3RY`?&?A*|Rt zgzvwdUC-a(s^D*X_@{`k+L(CKvd_2o;pI;L=5mJY$!-&KW;xF<`yKK7@B8e<s}wUI zh%-%i-^ZZ+QS-t2Wfgp}uNJ!b$J_Tm%HOiOLfvcC7n^_IDvo`R^e)Tec~QgpK`;GT zm*AiD^*l~b8RTWQE@$r9SX!EPP4$iC68G2XC%-Me_^6|caf{c~U(WI;*En)Ve!S|y z!I7Tug)i@ZuG=#8OZ915KiHDEcAa>5sqTs0l!m%LTxtFF{p-Kqi!opSx<T`ILgpRo z1MChf*=8_&Ns7Ds=GK!RqJN&QzI{-?<t20c^Bb(fQ^c7z{PNs7&G6T^*nmpbhMWBB zSRc%bF5bEQvi*;TDNC|jO~1C?p10y6JFCDvTV_YUlc}?({tbTg!akYr>D=QEshlEm z?Hl9*YA(&w{SrQL`%5O)_5<cDdzc?w66AQ7pnu~V!`kVuV}E;bOc7rfK7E1QC)0A? z$5}I5KW$)q_3t}xTSxSj_qlmRvs8or3g5fDa^?D8<_3ETxv$nsrOfK(Wv=g?Rw#Y# z_TdW;t`+BMaWU4hZ#bTJEbqwU^Z%V+J8^t?d_H0!lfpM~SxGa->9SXwC5_V(wnhmG z_RCpsVO$h7+2QWjAlBxC4%aeyPrg=A;?P<<A)c*$xl@7d^;d^lxvy9%)*qD$P|rJK z#i>}f`SD`bZr*S4dp1^osmgF*aY#r|IDd!H|7-K!=Z>oz8{ay<KD2l3az@qtow^TB z$g%!*a`O2+<+=Gr)>*q_Z8~PvnMz%F!L@HA^R)MYxl9K-l_G?`YkN(oVsK<on|$)= zakILDlX1`2Z#i@|>q6A4oZo-$xA0!bh&f#qlmE4_Eq~ub^HQEH#zTi}_CHSFdhOxP z2iLV2ct41@3toQxRgVA7<>mZr%?Cg3`dXFsYHJgpgQ5Z_Cuh>eh$TA{Hs4G+GsEy) zq2r_VjfJcg*Bwi$s&+-Q=}+tY^U!(Xh1OTOM`i7IzS~~=yX@l25<bNm_8)(OX7X>Y z&NWIoA+RxOZST4bnG<LEl-Vrgz8il~P*Bn|Yl<^RSb63(Y0lM*fg(#UhL*R<+OHI! z=On(WJal^9^)EAerOmtk^6g`YuH)=EzTn=q$uC~KPz%2sT=Bnp;*0ApxAX;H{+o7U z-sY|MSFK+C^xyCI<s1i#l(!~!Ca>3z-*+eV<1_zgm$vkdJKw`6_VZWiHGK1amDj&; zwbZwp8xos0o4sMFSug(h<2RS~FK=!JcXfBi8X4AS$EsQB2;Q9Yd?v%UIicLX&f%Rt z|3XY>yh}JSL6J{U<hJRin_;^xH!#d-U3B1w{=&-})YSREwQ_a;+9LI50%N`Zw)<Be z3nv`eD(1kiz-@5JOinGW$$x`#Npi*X{l;q^i~q>duBgAR;k8!r$TmyY?;m2sa%Oo= z)f3q=@2AnlUp8*#rxj|CJI8EtX<YYi<@J*VJ^OMuzg%GNxqU;-y!!^-HQDK*oJMX3 zF4i+nVLaUMCi@}hKm7s*10x$*x%<(FYr>QHu72L**%x`_%F^VMy9K;5zJ6a)QaQDM z@^RsSJ+oJJs~-q^n<;bVgr4LQUeCvRhob{#uwUDi+#mnW<9^3n9j`gfZ;Rx9F4t>5 zyXf9l`R}YgH(0ua7;@On{>t#a=&cggWeAq>`L}G@zqAjUDt0;IFO}7WlWoo(F_%w# zK9&8XrhJ!YeP^-pV$JoRlv0wcrV2K58vPJRKCw7DLht^wyT@jJim=*h>DYe2#!u9( zV9yTijFJlN@J#WFu8hBh+hpXIJi7eKA%~~;U)R5hH*2bG=K1#bvanoUk}4u0q-e2e zTNBqRhiUu`n|E)x-DVy5nqMxn;c)wXc9svnQw^T}zV%2sAVjX`;%^(nW0!MoU2mOw zTV7%L0`ZRCqu<ZC1h!bNb`O%gB3i?HMmi_$fAC)k>Afw+JJUJC&J|>2`R|)op&!oo zwrREa!LYNlCjNK5*CY2O$Sx>5z>Hg7wb$uPR7v{wPnT}(u6(e}|DuMO*x$E#Tqd@P z3S0C(FSw>6|CjGywYtWwgaq>m?>ZTj8odvwBnc(VWBq0KOl$wqEspOQKU@?4zCtvj zR;2dUa|1oQ=F6;XasR7$SjrDb1RVR~czVUQjG24hcp8*Fn#}q5<F&Al%X`>0E|f6u zH~V7p)L_^5^f{-@KV4g<GQ~l-ec92E0q6G{mVJDjV>8ty<+;GJ`#<fTPK}#!y`SCL zhgmvs`s~{YaiUw~873s1*KOG)?7;RxSc9!?ean=y3oh=OW3E@j-)x;Wv3wuz>+ihH z4#FBzadO|>8Pe8EosIqLC-flt=pXCn3$8{~ru~dq#grU5^N-GU_w?Y9SI1A!?_FBY zZ+idZrwx`2Hv6+ozJEKN>~x<ekMH-y#p%vJGs=~I8Q9*Im+x}hXjuRD@10wVBi6c^ zO*ITLF{qU8iQv^(Sf;qdntOr$tFxC4UA{DmYbn$@EpE%o+P|HlqAb-&!n(0vP9Vo@ z;i6mJjd%Sw{Jfw$CH893ry`ZBVY2<IX%_?QMLyfhE#7iz{-aL}?|Q7y^eN9h5Y>8i zRo~vd$2s?%dU^V{wfm%f$s)3cx_?~zBa;|v{j=bBfYz!#hA(t;tgqe9Q?NZV^H^{5 z&QyWW#k@-$^1psFQ8B2P7j?Y+@RxSa<eRmNxL23;Ka9ze;l6(V_#0m1g}F9ASgw9q zt?0El*wn+t)GLYg=*6_)+akTU`~zo6WC#D>?6o*>eNV??f9}hYv!5TFCeCP7S{kx+ z;+|*R@n;e$-mu@1-OBf0eS6T$t75md2InVQ++-`c$NQ!=N~K(DiuSFx+p8~bJoj^H z_JqS9S7~y64}bGpk=3>F+;^vx|7z#6riAU6yIWO|C@=Ht$i`B;vVtU+y^D+Qf9282 k69~B_yJV@u$^VQ~FDia03H9e=U|?YIboFyt=akR{09^cMNB{r; literal 0 HcmV?d00001 diff --git a/Utilities/FLTK/fluid/icons/fluid-96.xpm b/Utilities/FLTK/fluid/icons/fluid-96.xpm new file mode 100644 index 0000000000..5c018aa12a --- /dev/null +++ b/Utilities/FLTK/fluid/icons/fluid-96.xpm @@ -0,0 +1,131 @@ +/* XPM */ +static char * fluid_96_xpm[] = { +"96 96 32 1", +" c None", +". c #000100", +"+ c #031F3F", +"@ c #00366C", +"# c #2E302D", +"$ c #0058AC", +"% c #0060BF", +"& c #4E504D", +"* c #14659F", +"= c #006DDC", +"- c #2C7087", +"; c #0080FF", +"> c #407B74", +", c #0F85F9", +"' c #268CCD", +") c #7C7E7B", +"! c #2D92EC", +"~ c #4498A9", +"{ c #2F94FE", +"] c #5BA18C", +"^ c #6BA674", +"/ c #7DAD62", +"( c #93BD53", +"_ c #A4A6A2", +": c #6CB6FF", +"< c #ABCC3F", +"[ c #C4DA2A", +"} c #CACCC9", +"| c #DCE913", +"1 c #BBDEFF", +"2 c #FDFE00", +"3 c #FDFFFC", +" ", +" ", +" ", +" ........... ", +" ...................... ", +" ........................ ", +" ........#&#&#&#&##...... ", +" ....)__}33333333333}_... ", +" ...&33333333333333333... ", +" ...#33311133333333333... ", +" ...&33!,{,;:333333333... ", +" ...&3:,{{{{,13333333}... ", +" ...&3!{{!{{,13333333}... ", +" ...&3:!{{!{;13333333}... ", +" ...&3{{{{{{;133333333... ", +" ...&31,{{{;,33333333}... ", +" ...&331{{{:133333333}... ", +" ...&3333333333333333_... ", +" ...&3333333333333333}... ", +" ...&3333333333333333_... ", +" ...&3333333333333333}... ", +" ...&3333333333333333_... ", +" ...&3333333333333333}... ", +" ...&3333333333333333_... ", +" ...&3333333331!,,;:3}... ", +" ...&333333333{{{{{;:_... ", +" ...&333333331,{!{!{{}... ", +" ...&333333331{{{{{{,_... ", +" ...)333333331{{!{{{{_... ", +" ...)333333333{{{!{;:_... ", +" ...)3333333331{;;;:3_... ", +" ...)3333333333331333_... ", +" ...)3333333333333333_... ", +" ...)3333333333333333_... ", +" ..._3333333333333333_... ", +" ..._3333333333333333_... ", +" ..._3333333333333333_... ", +" ..._3333333333333333}.... ", +" ...._33333333333333333#... ", +" ....&333333333333333333_.... ", +" ....&33333333333333333333).... ", +" ....333333333333333333333}&.... ", +" ...._33333333333333333333333.... ", +" ....&333333333331:11333333333_.... ", +" ....#33333333333:,,,;:333333333&.... ", +" ....}3333333333:,!{{{;1333333333&.... ", +" ....}33333333333{{{!{{,!3333333333.... ", +" ....)333333333333{{{{!{{{3333333333_.... ", +" ....#3333333333333!{{{{{,:33333333333&.... ", +" ...._33333333333331{{!{,;1333333333333#.... ", +" ...._333333333333333:;,;,13333333333333_.... ", +" ...._333333333333333333113333333333333333_.... ", +" ....&33333333333333333333333333331::1333333&.... ", +" ...._333333333333333333333333333{,{{;{133333#... ", +" ...._3333333333333333333333333331,{!{{,:33333}.... ", +" ....&3333333333133333333333333333:{{{{{{:333333).... ", +" ...#333333331{,,;:333333333333333:{!{!{{:3333333&.... ", +" ....}33333333,{{{{;:333333333333331,{!{{;:33333333#... ", +" ...._333333331,!{!{{,333333333333333{,{{;{1333333333.... ", +" ....&3333333331{{{{{{{3333333333333333::::33333333333).... ", +" ....+!:::::::::{{{{!{{;::::::::::::::::::::::::::!:::::+.... ", +" ...+=;;;;;;;;;;;;{{{{;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=.... ", +" ....%;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%.... ", +" ....@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$.... ", +" ...+%;;;;;;!!!;;;;;,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;!=;;;+.... ", +" ....%;;;;;!([<|^~]^([%;;;;;;;;;;;;;;;;;,(<'=;;;;;;;!^/<[|'=;;=+... ", +" ....$;;;;;'|2>]22<|22[%=;;;;;;;;;;;;;;;;^22[%=;;;;;;!][22|%=;;;$.... ", +" ....@;;;;;;[2[%^2|*[22(%=;;;;;;;;;;;;;;;,/22|$=;;;;;;;;<22<%=;;;;$.... ", +" ....+=;;;;;~22^$%]~$|22>%=;;;;;;;;;;;;;;;;'||^%=;;;;;;;,[22^$=;;;;;+.... ", +" ....%;;;;;,[22-%==='22|*==;;;;;;;;;;;;;;;;;;=%=;;;;;;;;'22|*%=;;;;;=+... ", +" ....$;;;;;;!22|$%;,;^22<$=;;;;;;;;;;;;;;;;;;===;;;;;;;;;^22|$==;;;;;;%.... ", +" ....@;;;;;'](22[^]=;;<22^$==!~]/~=;!]]~;;;;{'~]==;;;;~<<]<22($=;;;;;;;;@.... ", +" ....@;;;;;;]<|22|[<%;!|22-%'[2222*=;/22(%;~|222(=;;;!<2|^[222>$=;;;;;;;;;+.... ", +" ....=;;;;;;;,[22>$===~22|$==,[22[%=;[22]%=,!|22]%=;![2|*%]22|*==;;;;;;;;;%+... ", +" ....@;;;;;;;;!|22*$=;;/22($=;,[22/$='222*%=;!|22-%;;<22>%=]22[$%;;;;;;;;;;;=.... ", +" ....@;;;;;;;;;~22[*==;;[22>%=;'22|-%,^22[$=;,~22[$%;]22<$%=(22/$=;;;;;;;;;;;;@.... ", +" ....+;;;;;;;;;;^22<$=;;!222*$=;]22[$==[22/$=;;(22/$=![22]$=;|22-%=;;;;;;;;;;;;;+... ", +" ....;;;;;;;;;;;<22^%=;;]22[$=;;(22/$=~222-%=;;[22>%=]22|$%;~22|$==;;;;;;;;;;;;;;.... ", +" ....%;;;;;;;;;;;|22-%=;;(22/$=;{|22-%=<22|$%;;'22|*%;<22<$==(22<$=;=;;;;;;;;;;;;;$.... ", +" ....+;;;;;;;;;;;!222$==;,|22>%=;~22|$=]|22($=;;]22[$%,|22^%=!|22^$=;;;;;;;;;;;;;;;;@.... ", +" ....+=;;;;;;;;;;;~22[$%;;'22|*-/;]22($*[<22^$^=;(22/$(-222>$=(222->~;;;;;;;;;;;;;;;;=+.... ", +" ...+;;;;;;;;;;;;;(22/$=;;]22|*<'=(22/*[~[22>(]=;|22>//=|22/$^(|2|-[%=;;;;;;;;;;;;;;;;=.... ", +" ....$;;;;;;;;;;;;;<22>%=;;]222|>==(222|^=|22|<%=;|222<%=(222|<-222|-==;;;;;;;;;;;;;;;;;$.... ", +" ....@;;;;;;;;;;;;;!|2|$=;;;'[2[>%=;'|2[]%=/2|/$==;^2|(*%=!(2|($%<2[-%=;;;;;;;;;;;;;;;;;;;@.... ", +"....@;;;;;;;;;;;;;;'22($%;;;;=%%==;;;=%%%==;=%%==;;;=%===;;==%%====%%=,;;;;;;;;;;;;;;;;;;;;+... ", +"...+=;;;;;;;;;;!'=,]22-%=;;;;;;==;=;;;===;=;;===;;;;;===;;;;=;=,;;,=;=;;;;;;;;;;;;;;;;;;;;;=....", +"...+;;;;;;;;;;;[2^=<2<$==;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+...", +"...+;;;;;;;;;;;22('2|*%=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+...", +"...+;;;;;;;;;;;^|<[[-%=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+...", +"...+;;;;;;;;;;;;*~*%===;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@...", +"...+;;;;;;;;;;;;;====;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+...", +"....$=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=$....", +" .....++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++..... ", +" ............................................................................................. ", +" ............................................................................................ ", +" ...................................................................................... "}; diff --git a/Utilities/FLTK/fluid/icons/fluid.ico b/Utilities/FLTK/fluid/icons/fluid.ico new file mode 100644 index 0000000000000000000000000000000000000000..aee6b18e16144ef80b099cd14d374b10252f56eb GIT binary patch literal 1078 zcmZQzU}Ruo5D*YxU}Run&|qX>P-9?VP*8yIUobH+_%SjtXfQA^2!O;HK<Zf-@Bt%9 zMuv0~R)#Ct3=GMMu?)W(7#OzC@MQQf$CjaYX)HtOx*~=Jix)D4@0q~x@9Z3g|1U2w zeEIg7K~z+jK}ZP<6jd`qK_KXJWajRfJ45XmEwXoK%nlY{P@ioY5go+9z*HI<8m_>= zz_9k*n^PYc7#RM&J^LQyDwenB96&U~x>sO|!S4!`E`icdAhbJ_c7xIoQ6#c~k%8d= zGXui|b_RwIAk5Fe@I#(~;g3Cb{Qo~BoItJuIRO-&NXB6>>)bdQPNp$1{BL4l$j?h+ z_↱pI#Rh6(e+845R+Gb~!XfZ_SJQU;Gh^B5E!Ut~Ca_7uafKR+2**q9jj|D%8p zAHl%}C*(gFTQnIXfc__A^LAxrWg}x{Wo2VyV|{*Q<2B~TPVA1UIC0F_*yscQXJZ@n zL)&-jRJR{8Hn#u3@X^@D^-y<>M*E?I#>Vmt4E)O0TesKfWE|=^Zfpb!?@tz+y3Ndt zmCd@1?Ll7qZ+v`@va#`T;~M4vAU?lvc$TrTak6o`AxJp`!>8cj;80UjQ&WAAGy?<w zy=PJH-aTFS4kFFK|L@(pckh<Qy@&D{zPx+)?%k_({t)F14E*!nJ&Stx5+=>S@b}$Q zt9Rf?hbZ~~?%ld~aODgP{C@A=JwYgEVEFeASvkmnclRM$A>`k8uaJxb$*1N+WFX|< zcZ=6USP=3rA@i1@+V?9ImH#&lmH%b#&G`_MAtWf4AuM#V0hA4q1VMZdKES}h{D6Uh z{R0C7KM4O|V37aAz+nH6fuSCR|1&WB|KGs)|NjAI2!6o+|NjSm;_(lVoBsa?01KWr A`Tzg` literal 0 HcmV?d00001 diff --git a/Utilities/FLTK/fluid/icons/fluid.xcf.gz b/Utilities/FLTK/fluid/icons/fluid.xcf.gz new file mode 100644 index 0000000000000000000000000000000000000000..13a7c93006f806461dd5f056695230ed2e5ebb63 GIT binary patch literal 22490 zcmb2|=3oE=<|k3y6(X+N*1fBI<|%ZKBc+0?MMZ^KrJ-q0U_iiw!`v%c3^*sIFjb!L zKC!@!h4JvKBsNzjE{(2r3)ZaJEhOMtdE$}Qq7@6Sb1Ug|Je+vE<hpHr>GvhVheGY& z?V5l8-1oUJFF*fN`l{rr<?>ZkYR1~>%d-8d+O(CmZy%PJTp~0-<IV%UwhWbvoHO^u z{LpIO!4oeNulqr?b-nn)z0&ciKV~)QtBVA)NNiU>VA@s_z?rP@%S3UL&{y>=uPa>| zN|X0=`=391@?!<}jGMdDtfb7(N^aJ<WV=nUweNe?<szHQR$oMvBEu~^b*d(B+rd{B z`24BVGQN0`C#u5w*PpZduRQu<Po!MQ;aXqwD5?JB8K$3iNaf9_*c|hK*W3prqr9_E z+Sez~<>4-A<qyqmhM!+#Em(hzckcAppa1i(JJo#h-UAcf<VR1f_MA4cUYC7l!Rl-2 z!uiwK+f`Sd+t4zzO;zN2?2}syu1cj{mw4pun|D94YL4}~NvE6t`Ta1ejmWCp93%H& z_0bs>oA0dLUFGY(_J26Lb?w%^SrwaOx}#)4Cf9UFx%=*k^vl#%tX)5MTcFeAsgtL@ z>^y(w^sHsts_E1JH0``87d~zKfyvX~d+MJ!_4Qdf@7qZeXU>~FclPsFN_rnFX9i!6 zu@$Q7@Mrd!bgpFSvS8_qSt0Tjrp?QWKcz2QnqFxf>)DnnbS~Fp#py@fdm~w&)ch*p z-!pIW?1>ZKYZlCmj@P}UQaXFnt^T*MQhHjsxk{4W5~ps&o;TRm<5phGmdvg#Vf`&g z*UVy{QqFQQzqzyCp1dw}uS0ydocf$h)e{=?6s`LGS9J0le|)HBcj$=urCdq*cF%OZ z=WX1ZUsZZn{Vp<cwsUR0diAEgx|Q#<;tnwZ!E-y??kqLcdc(TNyyM#h>-weN)(gH> zv2rPy^TI|))b*<JZ`ZWq<woth#kq@jcTS3I+0CB)#4o3zYJy(m@vn=_R$ke5!pvv$ zBX#Y%O^?*q&R_H6WS9L$MkVbf*9%fwZ{7Uks6A&*!KOo=r%!UJYug~n>_}Yd<rTBT zATUYOM>6VQ>bek~RNI+J`j5-jO}QCq6nuKe<khJ<ohzLyHNx9Bxh(S#J)$Kl<eiYE z#Q!`?X-De=v1?D8Zrw8LboBOge0_46UG=OQPtK}{6zQt3bN<M<zDZd%`|c5ya{DyF zE7K$I)@B&Jn%wY<@vE?pfaBjKySiAWFrVU7>sT-+Bz$6nn{bHcx}@4j-|4k;E{EPd zu9~%2>~iq8M6Z&mJ66Tz9ZZd$%iVH#z4<4nPcJt9?s6~P5zJzFcW)$z;;YLaUibQc zaZPUDSo9;9#q#eJafn#b7gy%agJmB?9R2)i1sB=z{<l3^bwVfX?cHr>rO*BfDA5c( z%G1C4&Fe!|#@6BAFCIO3HL0yJVAZ0NJdxkBrstOG3H*zhrSNZ}xLe;HpP!fHJA+et z_uf0Pd3{^uL~pmaiIw&BDzgphYY#4)DgHD4iPFsHe<v<D^yll*=?3ecE}ysV@0KTT zmp|V$?WVc%$%}X2YaDq~H}RbYvzw<w<%V6|PnKP`etAw<Y45~uZk!I58-BIEeLcJI z#xhQ)S<;&QU$z$|{{FRWc8>JVCCjJJ%W-=rxpRej`oud=zMDKf_jrFD>tD%5{r>7T zc^6;Ksy?-({(0P|XHlhB?ytM&?RIhA#;>Wj3{RJqUYy%eWq57IIrZL`DOY~5T<lLN zV^2Pt>3^$6@S@kTsEPb*&4qH+tLDGpxOkH7`=liMol{$XO^RHiKhgE4P{*T4lZls? z8_l09vHSd~oRY0S-<-+X6;<n(mg$i9pqXt^YiNMd*GWEmMI-ND{k8N${}PjqM@ycz zs4P-Q60u8ZpDerUmc>oe*tK(h<-#-weD$_%Em|C}s(wIoD&LX7J6eV86&(*WH$B#> zkZ{eG=}v#eD0lEG^BU{m#}&$YEMalJJ1h)dg!e99tevTQNc+$&hDlp@TiiMNvV7L@ zuS=ham9D+|-h0OcfiIf(o@6$?<lM6S;=DB{c16#QZ|`4er^CDd)9Mq;vU)Aw)jtj2 zP$=_`|IeW^Ch_H_|6FgsVl3FA->Rs)$1bX&cBM!iTVS9XQ@*g(ge9hjo^3DN?(;w) zbLt(vR~t4~Uz2{C@Z9I|>5XESe|X32KE-nEs#CaOVaDpPfSF>OJ3U|Vwz3B2tPy&p zx^e2HBh5F~ojM>9U#{CIb3|eBn-bTyn?B(w3$`-uY~+{fQ0)F{bYZ5p+mV-xV^^&g z_pI7vFh5#=ccqK-bgdI|GFAabF>9x9G2F9zS}|YJgqE^hN}9RLw1W=ZYPfTNo%hIu zqg9^V;hAT8cuO_juUtPp&u58>m~Z<Go6i&3*J&-*uFIWwS>)(dZ~LHQGe2F{k~@AP zw!3Wk^Q}j}tbl}<>4muuy}!p#|Lmt9%q%iv$H9gNTHl^s;kaE8bJwJ6huY<TA$wh> zPU=xteyeh^*;L}JQdH~jmJ6R6KZw<q)O$8%-F&`c@>CAx6z$xJwSQgbZrt+o?cw|P z=43{`TQT|XGuu7e%G-<gmmc7Lp2h99p=(J-sp`=cMz>5PU01A+oAT?WtC#lDC-u2C zf7(+T_s)z9-D;|Eb4A9xgihz3&NrQZZvNS|WJbL+<34u2uCHo0S0uknNOYcP+$Ub5 z(9pcU^5)*-Gt8yF-`i@ccrr%&PH9(1U__5ovWVPbfr~m>TUUB?{o~g;H@W_BGXH1c zvlsmN&h@-Gv?lZaFK2)8MXA><zLccj;@3WqVLxA_;+e>i^yO#2K6$xZMsp8$%DQid z?tc4mSLM3*_GH`2NXd1MJ8xc&*)FyuHGQe{svm#WRLX^W6}{~jbX@tZ`pB6zmh*D{ zOfj@Q9o-;r`>ade?9z+2H%p$r{(dv_-kC#NeEL`KJzjnP$3_EtQ{DT*_PW~szj=>O zjh*0rDE^bTPqY1_JMlB(CrmZGKK1QMjfRhREI(TAylk^Bvv_Z&W#r3UEBa1vO?SEW z?RHhM*W;UEsXB`DR`|!p=2RcM<)60Zv35_X+}Vh5D~@B)Uk=M(?@an=SEiYEtL^ae zefBYCUdufBOl0Mb-`ecZy<EGn;{OF#$pX);d-<<6ZU5IEY?yU?3g>gp>ebA}i>zan zmVG+)X3^E#{}qdVtT~f3Q|YHh?JD(2`BzW$`<`jN&K_cX?eddVuQjWgyyMm`Dq6fu zFlKH;=-N%9CE^zi4n+8iPJP05ZJMU6La_JDHE%7id_GX?J9p)L2i>X4lEMq?SbNP4 z(suH^<+`-$@j@FP{{>qt`R4E6*SImyz_#gPkw!h&*JhKhs}qf<rMn&YBx2*1s<HBF zbfVhCq}W*AcexUGymY4o3$@I5j^MC9%d}y$;Gr;sc^%ijJJ033nKI)~T+@eqfwIN| z*&SaqWJ8%}FISbScC};unBt(`aGNK?D95aQ4bLXY31^whJGLftz2)kE^vcRBy;Qu# zdqrKS_d{9sJIpac{m-(@$_`94y}-AuJ=E;+*F=_J;{`sBd!>2B^{qWt?sHu%;moai zVg2DFS_QW`L$7M&9n!ny@4}pN_`t+(+6Bg%FPSH9DRaH3Jf}TH!nXI8U|)Hw->Nph zw@i*aA;uRT)_Y$tedg5O7~X&INmxPl3O?3fnX7_0%o1webQqN~mF%4LZo)PDnR{5( zt{%IPs~D@itVJ{6TVs*oj@l)wH_j3EDrI<Jsu)nm@>F?A$nSs&6E3nVSa5_ISKN_b z)$S2$UTn76>*c)utbO0NAMty`-|^^jQlT{S<@r&WdxKA3{8v^Wen7O@nmNyK$M%E0 z?B-&=eik1V`BaHb(_3;OC|WbUE~fU|&u?3N)-5>~#q-VXcOv(x0}fvvOw^flRVQZu zcN<^TwbmxTmDa_E6lpK%xDl7UNA>pphkGWR+N|Yl%s<1)=7!*`)3Yj{Yl-Yx?p&iS z`#sAzwf%5QMBj`GmiOQM7OQAHu50>dd`bIaMdBhp#|bAF&fToN;J}p?l^eck`1l;z z98;2T;hB?d>ombqJKdHn{}u69l)6*obWd_l?@s*`%~_bWpW$!Gi|I|jr+hi(A$m4^ z(N7MOuGU|&E4(#Yruf-EeEL{7z<#l9qDHXHBA%WljDc@{f7D4|vmxJ_`=gPBfMS5G zABXOpc<0(kX6?flPbMVDwJnly%Ui?rnk`Mm;PuzzDi?lVIMY7&t-!v+M^^i(@8aH{ zVY5z1vu&OEt#9pr4YxS%ZGG(`{Uu~sl*Z0gG9QJfzpa}&?{!c{&idQNHQE2FVh-vk zpU#+kQP#8gn@pO&rRKzk4aJv4Z$$U+)MG8z-x2yCs`2*n(9;~B+(a7H750d}n)qPa z%fk+D?k~K@>c{f0`GH!KH|ut>1M+J-Bwj`<#J6rS{t_9ItRLmJ{^z5huM^#qZ~UE5 zx@ggwC9>)X4?^baDjiT2y66)x*8GWQ>&6eO>Yth9n*<-sGH7HmDQLgFV3z)|SBuRQ z1>cJFKU!7RbhSBT3DcfM##vKEn~n!u`eD+NlYEE&;NQF>ld6QR_C8|SBHmUjw(Bo< zDxdFGje904*W?eXJ@jPx)58<ia!)NQSS0FPsngC%(N94~cCUCPYUZL}SHG}Gd2UOQ z)|B(vll>;%4iWX*${X{#&0vCmcBl=Dv$nH2-!i=u9ZOUWSUG*)vn+a<u5C&&U%>G| zBhjDizCYK6?Kt!$M#I&bC1Xj1n9G;o_C%$E_f19n0<yHdczzw0TCQ>N!qn_tI=YRA zzO4KHSkY;f$=rx7e=gK6&^0yUZaL3=u!MJkYmb2Y*00@FyrK)sq!pIds4BFwEL_;@ z^nC5bohO<yqDr%meK7WAtPE`CalWj7!GGO0ErBJEEA7}E3p|>28j?g6vO8ASO#U{- z{b$yhFP6L;cpD5E7Ay&s%f9u!xXwa^Va+v;hnFMDvy~Vvn|>8<vrSs&lyNn}q@Mls z#W<B)M?;RBXP=d4Q?hwW>I^@#=f4y`7n|G_dXY3yDbd3^)t}vGMlL&Vf<?^2-b3vo z4bz>)>%u}mpY2wjcp!A!o4xiQy(LUfyDFq5ioWFgK4n^hu|f^AK7Twzx%JzH%(3r} zb?bhO))9-3iZIW5eSBfoWLf5$k{0}Z8vF|qM4hLxzc7?;Ij;Ce?$F%_ZVy?4dDjV5 zFX(%4?ctSDraOKo=DB!Ui?Ahfev4F=cpcdMuW!o%$K@|QFI`{K)@#Rl)4Dg3f7L1Z zi+|Y8Rp^!o>`9T`{O|E(b^f*UB@T5x`D2yo8oQ_CqOY?>$Dw*_w|8@nM)WhOuU)Ys zME=bTzQzBhC#;BX<B1fm;Q4>&iB~8~o2$!@<uh*iH=JU~;tlx7<l5}n#LLh*bph*+ zvK7}AlYai}k&ATGo4ll1D27MP@w@7*drL#*IFEW}cFA2|9G7|eU~z*j?+p13j7)Ba zJ&sK}a;!{xS(Ns|a;7q$E1K<XpBL4ge7{iPT+3EJCD+9l+?7r0rZ4MF$mI+(ZVvC> zs?O*zac6a+zUU71z`CDxZ}Rf@9QnN8(c-T{^10L-Rje=CUu?6gsuYp#7mK@?q?j66 zdP4DET6iwI7pG04{kel(HGGpAGd4HcAG~z&S>8ppsryzh5&u!{yK!Uid-p@zY}czO zCAxZct9V|u_!ld3`hu9o7B1J-NB1m~zuh3RbY<b2r9p|VMiZw#zOro7;r<$l<fI+m z9C41v%hdEA-Z?Fiw(Zg}9qAt*IZO_H3i&CPe75hCC`V*Y$CS;6N5Vcxev8X5?%V%8 zi9OPE!`b;eiiFz|*N4gcsy}JJ<#B3TNmta>H!sDCgpaM3DHdvL*|K<B;6#h7Qs=)2 z%*~$C9C&MC%c;X&oDJm%;yjN1F||Catno9MLC<|+gw{fjl!m|QTxLOsS7rJO1%xGB zUdt1BL^8pqYi;T571D15%-#Mt)O<a;@xR7Pue0lUYJRKN?XyvDdh~0P>hA+j50po{ zEpCYEtNieQ_34w@mo;|gJY93*)ibMw>My-}(xj%DnjhQPyYa>9`Q5AmI??`)71CGA zo2q@|#aHxg<;<vl&LLuMy~>VLI`)EJ;KLhM7Y*2tJk)HN!?Q!LJNJ8gN8^U%N})#~ z_fFn#_)y3Z{%Lzlf#LmsB5w2fmMj18-)IsNdWorSo$0bAt5jcC_1*X0uu67Lf0{)| zNU8K6+hrHL9?DmAe44Q=xn6@$?T_TF8^sd0^=Ccq3_tN9ja%mT4$(Vr`!=nb(i;49 ztxv_@reAkIYlgJt9nP!}3Dp1l;?B&>`pd`I|GVw+u2&VZQ_(L^`*Y)E=H;UF+3|Bl z{&L67Em62t(HpM*?p8P>=l?a&)n5v){J&dHt!mLay@^Jv-^WWxze~>fqIc|_jl(0y zU#lCUlGJDF+)VNGTGly1H*EG@Me9{>%~rP_nWV$6v&qN(r}m_rt=5N?q+Cx1hE9CA z(9h|_HSLx%i@AK(b0?h_I3y?~d3jCh>uno1=0<PNk@B_B+@hwVv?*|l$XXZI3z^@t zPbP79X52Y-)lyIK<XgXY7xxzLzNS0NH22z~(AhW2-p1rcZMybG`(zS-civ6Ab?N&X zo!xt6OkZ77{9CPF_PQwf`VN=!_gAjO+3wmPePenHSN@%4+3On@ANza#$?s)VMmCwk z@As5`Xkct^>y<Gs`?JIF@UKfp<e1lVYCn8-TfH)^BK?`I!TyZEi*sVm@13l6_xZ_l z)d^*e-}Ww!@c!1Sa{KVC9aTJ1^CLebTs*`st`qgC{n91%>A#+dor??D^JnFy<>6w_ zeVGEbwH`a7#y4}u>*|`LkB{zK^k|al?6`YdzV)A;zAhqkTjlH7x8pwPf4ZRgxA^3v zo~*mI7mn;Xx_aK%={837_ZF$2+Lm*BS7q+YRq5t?1OFZT_q}}229<8pboZ6-KRh$P zXHxfUQo4Cw%;uVdYwq0ax7}R%`nCRAUESF4x6U=Y_sQM+dg;<jrYzph!moQC|8u{- z=hLreSC1NBzP#z#+KRl#$DaR-`1ItK{o9{UR<F0eyZ7bAl50J+Zehw%$9U&$y72#1 zpM8E^R@|>0hUNbA_m@09b-Y_X?p6KUy~^r+^_z-gFQznZZ8OQ6Z)CPU<@4>Q)@C;E zWX+#UOMHAO{oK6Z3E?lQvrbpfpZnw22fqKz$&FKUQ_4Jk9e#c9*5>EuvuiUCSATzT z^Z&Mwlhyq9=@-BAIwWVm?f=(Fb0)s2zxn%JgVwq?|GnSuwW%nn`10>Xf}^8=P68_{ z>%n_R`yNT}UU4zwjn|bG7jJC*-nMbEz)OWB&rNBQeT~;K8Gp8Zey=^j>}T$$v+s8O ztoxg6ad^(m%Hs33#pj<FpWj=q<H364z!AeG<>%PjyYgzQQvPoF_jXTAN}OZhMZ=Gt z&CAzWRqTD`_;mSvopXH$Cx@DT(Xq8kJ#)A2TUg=6M$zQm?3R(yH!XHmvbK~;8l;|` zc>8MUcm15x(h{y`JS2b2?(5vU=lG7P?CYo9*}W(I;|7cPXk+DMV{hs7{e3Hq&F1Zi z4le$F<k!i)O^pdFS4?SqE*V)};xRk6VAqa4PagGE&YZh<>9JqCs@l@b;$$y>-Zt<5 znr*L+9sKTA`jz!ce3#t%>>O3@w}w?W?=9N2>Jqp7Sy`di+3CyHFJ7CS@>X>6)`IfD z%G{q*`=6(meLA51fc1j;)<W*S^E3ATOeyren=W3iBXLjn$kkgB{?W%z9Mezy(&cQv zD$DDf*pp>0rye}jcXT)3{FS5EfA*%L_`suw+f%2P>(9QhKe%D@5fA_KR}^<#pYm1x zeOUN?%U=hNEJ;wW>fF`0@rv!5>|0Cz^q;%8y8hRSMH&BJ&5X3Y{qx3bX{o3ai`bs! z?*0&&dvt59xBHRb)(=z@!i)>vOxgI^Tz+TZ-zTS!i-z;Bdwy(58Rw+PnX|n1CbjGR zd~&(#*6-<M1<i~0zPYLTOHA(|r{v|ZnwouI9!`%pyR&~wzOH#*!u0_2l{;H&6TW|3 z-FIizs-5LokGJf5xNh62c*An8E_s{UtNXN{_W%D>`Sz{w?P-3}x0Y{?Nz2tM<a}?Q z{P|_IY3O#o{r2m2-|_U)Z<N~d`R$Zho0IYbk51N?n;Ls-bJ4L4`(h8-ywyFs*4Bz| z-tNyuk-0yw+IDYB-jl04^XL{Hm34`>?)pD}6#ZPRzIA)wy7_bG%E&%R%+Jh9do68W zbhGjG)UEU9-nXiDn6moFl(25LKV9+D*Hl{TO*1u_5`S-NMM%(;^_#EUxpCr*qK0Mq z+mF^)uO3yu_Ed%4a)#8URpFOSHhk)lTXUms<C=erB1Oj<`0jlZbNjW6?U~-hm7DEs z!lR-qA3rGiAhL3zT*dYDfC}#Iea$;%r=OA!xo@?nD5rd9^UQtQrfq9Hvbgx#A=?KU zso`a3&%bz)ws3v3_=**;qjr=_ZAvH)bd5cF^)B~jt7@+=Td!Q*%CoetGdWytUu0-> zQQ7G;{~r3OSw+2Jvh56?{_r&4ofV7p4>owD2g{a*n(8LEPp}I%pSLSKxc2u8cHt_P zTT)rs8{Lg2{3@5;|LeuvSy38?uG~BL%`GY`p~yJ$cgazA@%PRBZ_dh#y=L8iTJM6< zCjNJ}rH@}ux;5*zdsy%5XX>UG0$L|MeE;nI?y$(}|Bu|ezLXgm$NJ``spSSgKfzde zTmRnr)w}l9zuXYv?`>P5;_H0-fSj<MMb&aC*_5pL0_@4TzOhxT)2yma9I_49esya7 zn_1>NnpaDTIo&>@x##~G-E{A))p>GpmTH1^k>1|(;}$MVe=2MLYHzdo>Q{Ew-xKq^ zb}a5Ro8ol+kgiqnzvJPjvbEQ}V|-m1@hUU(@~PmfCR;e)SQfth_-NLx-2tmTi=v%< zO-*@gv+u7fm@gfA#`-|bt|+TBjtANn{!PoVjE-tAHCH=$Ju2SWm-md|mF!QygfH}n z$j5WvOUz%hcxn2<JrklP-Y(p^rq3*XuB}dqqC(c}T^jfIpOR)@Q7!T6g@o75>ebmV z1&vEi-pig^nmXMsXo>628Ck1WCw5=Atp2EeM&WaN$+u0*^7nmG-SW*>=6Bu0x36wZ zGM>HcJF9cn%EtUf-FxCIR`1&O<xcx%wz3ZsW=TnT$GlXX<yPi+a`N^0Eaf|jOTPYi z$7seDP@$XrdxG6%vw8c%xm_d8x5iuRS9k7QI+x#JarF%+Yu6>`4n12hlvP+EuHQMY zP3lLd_imF9lQ->pHM{-({2R;n?qA)!cCOBh*u}~3ZW%V;+W+R$xt#(1&#Yc$MYw42 zh<tQ>y0!Lw?|X6KSMOiGdL`?+ej%R?)BW>OuWltqOx_YFbZm{zp4jO4!mpE`3bU)Y zwV$r7eKPlh)T_gH54PurhZ?@$c5s&qyZ5Xu?~d$c=hyDCi!?0tnBU?j_^IK7MHTNA zX_2zaFRQPLUf*DGFF+=A&Djb2E}PH)`{v=|Q~vxl2Gt=^MKQY<9N4gq;l#Tj|2`>; z^xv(Qv@*8tblhU|qsX#t`IEYeeQO>De(hDBE#@P2NnOwAg8h`(BXNlpJKu-jvt_+1 z{EFl1;W?J9w>r+hl3tZR_r@%H)7|CI1?2TB#j7T^?VHN~>+{!7pQJB{lzndJ3JN_K z&-L28_Hn0m=+>v#`}0rFpL5anQuwn+!oA{}u~la`MyD>FUT&Np9v<2_>DI~WzW9yb zAHCget}k=LpxkG_AEVy3ZR;L>QF?ZDw!ipv(fOJ)rgHJEU%Tv(fn!eEy<dCP&&|29 zz0%XKs%C@swwM1JT&{+`OZt6*?^gTga_{xx>*ifBzHp6WUcW=)+1Nvq+|EVre0kV+ z^)p|YDGU=2964|zh%F+<)ioeAIC%H!mFX`fC-1E||8#e`{@XYc6ERs&(SS`-Te9Z8 zowQl)+#K8DOB?E9o$jpZE!|q$yOiO-G(#y<4~xjkRzsu0GhNK#-TCwG%$Y6qk|~$@ zkI_#if$5!V!z*HnP92yM_c8FFUf8i+v!rJ2Qaf-|PU+nhV-qt&Ln9NDa-Nr_m2W5d z=f_%ZD3UR0b&Fc{g-s&ecd60+2OTFm65_+7i=A_MS7>HT3HiV#W!3g9sM?)9TD!Bi zdN<?dZF7Enx%KkxXN5JFnO00(|B!8$+p{3{^mO&=m8}!!iOq<2Z4JMCK-yt;R?5>i zy8N7<ipvXm-%K+7zc|=coWIUsr~eG$9Tt<O=QDiIdMPC_d&VpY=@(g<4z3E(fq}Km zJ<M}6+I|bkA9&KRKh(rS*k&2mM;31L)l6pL7ju@Jkhy7bhqdg^$#Ra6k}tfyJv?6) zgjC!QPh-3Fq2Y+A*SfBX+oz75^UF%?>G$o}+uA5LM@@NtvyedF<n#uc3)ionn<Mva zqxscVqh_(L)SSn1moyDmy2nhJKe=_^vRPg`X1l}(i~cwzye35Zd&j$GH(v?!E%81L zizQ>k9w#SvsFkzXT1*P|_`cA1`kI>jdo7G}_bhFT%Hm{P<2C1GaK@cAd#w0p?W{V! z&wrba+;o{|EDv=I8E$3m`5PQsb9{IIx%-u$9{qHdPUnC1f=}=M)$3A9LZQvY?B7pC z)_(Z3Ryy4-YJ%+R)TQeMA9G$^`f2s6Z$_{DzdUm*_-yE1K5tLSzYojyI9~i=*P8UW z>(%+2i+Rt*?k)a*uSxZBb*ts!)-Se8-JF;3u%13!Uw`zEC$shM8x9di4;=U5O56CY z<Beg(mm?n!|2ocQwJ<Wqr}V+OEEn&ivuZjQ96zRPvaEXjl67yH=jdL1^=-?;2CwkI z@QWEC;mM&qa%}6Ta#=K~38=eFPusSx?qK4=MmfG|Z2^Z}xaxYQ_(r>j`^UTfXSbEr zEs^-;mHB$b3lk>u;PBvs*Y`Q`a?aV<+B<pm?A4R6%&F`+5+JT;YG7ozc|t^_r;ZO# z$${1@`>tQOW^7_;Y;JCBcH!cYWo^n|*sMM*n;CtRDRlGnS<<f-unT!7D<>Cs_U_%h zx_$cg?aR-cyX3)s-%pua+I{Bi)tmQD?c673qxNh6OqZ<ZFCIO6`0`zkzM>t|#2MZ> zb8Y`LDc>sZ>h133`(C=q<jTcs#uHEdIdrT1jey{bJnw~5_H`aPcl5Bify$!T-zx&_ zXI^oc{%_ybD<`#gIA4D<#qj{+X0~rH9%SdIEy!2;%F+FLu9?N!{F;{KYc(CrjiqPi zXB^)lxA*t*W#8V)$-YSHlv}&#&`XQkR+a80Z|zGC`Q%-k<a+1Hns<ptof|u+MpyKo z@!b6EiQkDAVp@|WBxgmOX0k5vKPzWl>GtkR=gqy=70Gv3uUd6;CtJCsfm!~~wzs># zzqzv`C5Y=tim|tQrPH@HqO-ZK>7JAnc&ln^YPS7*->Zp+fg5wq9`ntfe(sFd6zdrb zYysCdmGZxyXPbTX+~Vi!W9&BP=jK&yS>C(!%HqQZUal^ex7}ASJe~K>u`4$Y9b6y$ zf8*zC@2qMb{W!Sx=i{o@L*9!S>l90Q-x?;>9lYr8eadckUCrk=U;5<C!uS|F7k?_B z`}51?%hqDN{ol758X9eO->|pl`N`GW^I~pn*ILfMuVhx#uV+7292T!Bc^CKg@T^CZ zXQwT5*?H3=R{59z{enMfFYk8C>r34_di&Oi12=9huKj=V{rmkvQI-F1J>*wYWxqY! z!FQ(Rj2l0W@GboD>tyqz<m{qJ&U2QQ-J9Ef=6>nR&8LDEL`i=5=Oh}jqvh+Y9j`8Y zJ;mPexq;oGc)@CRkplsb1Z^wc^?8f-&%buhVna?!cs={d<b>@TwfXO^NU70edN^xc zr*pvhkE^-zuU-jPEIZnM$$Z<lHw*F~UP~01(0b~4zqa1{8P*oJE}vtQt7mIqIN*5v znvd6{+me~tS<ZXj7%~bJ=GIzHn#-3r%}wCoq3V~6T4!T6{LZ?%_?M7ZW{TOjdvlGS zzjvx(S4eW1vwiBmWo=?jtLK!ezq@uV&_?W8N?y)8ff)uq@sC8Ub?WbbebqK=c6(Tl zCr`<i!by)G-(SPF;rNG^b!}Dw4-Gm_q<dwp7ECDT-(YM$xyp6<Qz@n(`R%VbY{FR^ z4xI6e`?f7_;$OwG=~u2!opaA*t-guhtyfYUR_u(&HCC_vQSyG$!j1RLo(Vm_@Z_WR z1ZIXk$?5*@<sYU!f580b%VTZPucjy5g#IpNoAs*W$wx!Mlkqp~)Ys0PZJKc4hGOyd zjT7oOu4&zEaeF7r_c<F@eJJy-P37KmEr4A_h#`R|qvGt{$<oWd@Re@cG_CdPxyafb zPxmz>+Q&^0ef;>v15O)h#elzmKg$QbS-5!Jy4*JsTmo-=JbgvC1~oKqo$Jr@<1Fhj zag8%~na(|b_(EugLD9>7*`d7r@8sgWv;Dcd^51oBt$A6OTY2$aE5p>cOU@~J3Wv+@ zyLm`%Rlevtsr$w^uAVgJs`>t8FMEGh-kW&0Y=7suf-{%?ULSfzA<wV3X!F+3ZzkBK z-~Ji&L}>RqhO0WanAg42FXru$-}d6M_5;7E4S7?yE@u^7`TPifA7k{M<{E_~N3UJn z|N2Dg@AaXEX^rc;D()OVYrX3Il�R<ZW_)^!(yfh}Ed$KDlz`4!$P}iU&^KGhK6D zL_wnT;0fcd)q;=xUWq<@D=9MH^!?)Qr~UTp_3bug)$}`9C+B7aG$y7!NWL~DmTj59 z<JV7~+%=T7$f|VS-B=lYetOvS_`9?1l?<;O-(P#*^S%78$lpJoZ@vEgDS!L6!x7>u zR&4eEbK)uc4QbQt1b6wF(E*1#{_MTJO8#h?K2ujzY*pQErN!PJ4iVQCi?_|utNd~F zvRB1yqvV>mXL-MV@p;ocsX<3P`Qvrpm-i3eKfOM7e&_1`JCz@nSQ}kCwd&Di>1F&K zoZPRkl*jyA*PYtGucG9C&cQd1hKzba#>vUvH?v>Wy!hK$ySVx3!@`%w=JT{Fe=K<~ zqEq+u?4hfcnj7C*m7SllFDpLq=;QP9_pEm&K3lLOAU|E&n_F7{!D)H%sn<hmcIE&4 zQ5Sn_>+3l-J-4gg{ad{JMfOtDsn_}U%{Nxq=$-U`V(~S(9Z?@&yll2Ue(n63Hx~_W z+`bw1N@7BT&8A<Dl^4}dtMR>&6ThyT`ladZ^V4#+vPR<ZT082lUO8iT@~@Hlnb`6L zEA~7reEW8>^e4A3{x1ZcynOP2Yu~nK6@{_3G5eEFO{nv<ty<a}yW#DfzirE%#hLos z&DIwDontujrQ~7t!t8HxyZ(PDygOHzm0K<4%R8ZWj~_h|yjXr~neo!Eyi@9X<gTm_ zf6u5aI@|y5>UyIRL4!xXW?3)araRX#@5qLU!fAWAf7YqUzkAo%dYZrdyi2Bsj!V{9 znQnh@=Wn~0)}*<!?kp~Uw&iMjUWomvMY^HBCtLTv7V|kS{Y2+R(Vwu=+P8Z@?+$<3 z>($BqwV>d`f!F8vrKvjqRxNvZtNh9#+2`J`FMYPNiH(V@eE;cTQ|jhpsZ05#?2@nU zJH0eiwEW!LNZV?c_kI7)1xa83P<Po(W`AsCaM|A<VG0_y)~+sPk`|?34=%cNZ*th% z{Uy799Q(;Ud%BPGv`JTtQ?KmNbzgsPXYJD$+m;5imGTx&j*75i`zrJOp1OG6)`F=s z65{V)Xjx+^%^%-)de-K|`zJT6^XEldR)=_9?~{ELto|(Dw&c^3g>SWs+rRaE+G1*K zwDDu#$r*dUO@7?7ZOPI09oAM=E#GAhuKlkf({b|m?CrHX@-p9@_!oQV&tIp<mx{#J z-rQ4pcG64d$+v&sn4S2ckngQw&9|;z))VoUcDL=i9T9P(%0-R$bnG+9sU|5&@8;}z znQT015%XOc*}KiVm-Nk<G}}5gBx<`x{*D;#CiVxr=FJpNQ)qw5FXNV#m5`A2Sn#55 zZO_{Di0MzReA)8PHu=yV*|lfRF4bd{-SySi_wD2xh9~Y`6KU8!i|v5j`3*OgOktdI z*n+wJVpE4&>D2N!X-cIZIs0<1>&3i#t7B?><+Ayvk`Ejl-8~$<9||Tg+;p74sB+@g zQFV<uK@!$pi5t9y&%6A4^gyS$aMNZZW0s@^oe3weUA%eopj*<S^=DtSNnMi3u2%O- z?2&8@3~e{o&Alo(d*-Z}vm{<J-)WX-Ua>qsgD2%^fWP!d`2`oxXR_NnxLT}kJtW{V zi$PR$*TpAa-L47bGVH1-XW6n!O6%2Gj*PP>`e!6&G>6B(+%#L7`ARJti)Xu1V6nG$ zc6P&}Um|i+6ZIQwUP{b}h`4Qe>W*z~O|4CAj^Msk47dNwbk5wkbnoi&goxcQZv6P6 zC+ocT&DpOLHc16=C94#E;(R^jMtZ`t4T8#>f`pZAm%4R){(4gR*5mgNgr`oh%DJ@W zr}s3yFdr!q{c;1>X$(4E?B@>LbBip9c{O9tce8glKA-IS%6;q`SNfhUXC>Dy?3{Ty zJV)QA{OPBc{$ai^<$oTNTs7;L*tvt8k(;l}?y31+_j0T9YelDEqdxBF7n6=}k-nmz z_F+x$@w`yG75i#)?oPR<*wcGKc;5l}jh`~?8GdhhEq9fv>_DGviq{FnPPqwOybGQS z{$1vr9rb_5vtM?p`hKrDXP6Znvb$kC-!{jg=g2OLkSPCv%LmWxxf!iL#deLp?dHgv za~s|M1+{+Le(^!@#|_{3oW$MQzi7Ds6cSjY$TD3JGz?S6aU$nrz>=g_7CB2DXNFw5 zW@=E*<u}ho`ogB}4!Z*$Su>p0F5jv8D)O07_4^klZ#wG(!i%^R*xqh-VfxEp%e&`* z(2wTLXYQJBdcNY1|GF@{H4A0S>ZXXVnrxM@<<_rdVSVrReVVYLqik+<%CmL$Wy`-Q zE}Ee@_l|DK)rsv_5A9x%ty0KxOW?Zh%JB7e%x!+L`+i@lb<vJa*RJ+@ut$F5?E}Yb zR|NN8IrC6C)UD36%IV#uwd#4-ZK?{sAGsydqWU5uYYCr$iAB)&ErFAZ)6buqJM*;e z?V=903A5R!_xF5f{NX6?fB%r?g5vvvm!Ip$&f7m>_F>(~?a$xb-L>3*RaeIS4VHFt zbJ8B_yf-R1bZ6>ovziS#dGEeNcALxWV7mC_<KJT4yJ=Tc{676~44#&A<KM+;p`Vxa zNLnVIoAozbdw$Kw5AQbet9?oEiE6gt=#aMgyLWB%_xe4Ff#)Vn`6p?4+Fo;24U<Ln z|7`Wf%}JM*uf0?F<Hy3cr<e1+6TH3j`ia)vdf^IxZXR5!-Dx~$s!`?9b&sF>y^S`v zULBnhP+@cI>?gK@>AshLY5d&Gwo-n3$?=n?r~B7zsqhI}((mr@yl1Di-t_C6=Lj$b zhOYVYGrC_qc7I91+b@i=wR7gyCL3%C*C=+Bo8o)eQ<|&$-5ne5FRF?cZXP?RpZ6n( zW&Qk%G6Kq13ohOBKKgx~Y^1ra>Z!ZOP6gge{<BJX`|4HQhM$E~{C7*6oIGq?{_g(n zE!8JGS{T?nL%ofd8ctL%-kp@cUhAR~|N5z+cPzJBmNPs^D$eeI(Nk%ye}BCuv&(GB zvo`GKG*{~FuPb=E<6RLucd_;VmWv|arp|M2JM^n+iwE<8*WT98Q_DWF@V$_^R(`8( za=9e;OU>m|nets@broJ@)*hatd-jHYEYqUGzYRjGE(O0@oi7(-Xm#=axjT2{R$S<E z?ugNQf5fi%m3qM`=Tl;fY}cGs-E?Bg%!W0u<)&;}!}vA9=IOtkO*1tG^@O;i@9P~F zd*2woj8Ed$ktGV%$+=b2+rNJIV>rTB#In2P>pY$fTloTv8Lk{*uogb`VXMdAX6yFw z9={Le8@7FaImc3bLFVDbs}|kuZac<qG2?Zz%E7J`yDJl3ez34_*t*d3apUhRc9kJ@ zg}?8t`Jpg#Yv(+*)oX7_H+Vc|zI%r$iS6vYqFq}aes-Tf_iw<&tGb772PU!XXIHmf z!7OC4%e|#OVfPb5@3Q!H6`x$4PrlUcdbrn$wfe@)i`QiLY<ySt@YTtcg|drw^UmA% z>%rGo%j0eKl&?zoH{(i+hP}Esv+t{3{#V|9;%8)MPP&u*AS2KDVXu_U>oeO_EhS#Y z#?Ak_;mxUgS2rI|OYfbrC*kqK>`;ci-sj%d<X4rw_hY>A)wO=(zI~sro$L?OTIMsu zBKO~|z0>WOTgu+wIj)_aqQ3R}#>Icr0uG(}WG&8@6KR+J>d2f(@9lEC<HBO=USH`; z<!Fvs%d>TcWZvDKb^k70o7y!eQ2E%iecK;DS-w4AK}+iD?!DV(UtecfZd>;2$-~&! zV!pETuGK&IAgR4g-m0$T{W4c!_9HAC?pc&<`^qYx7h|cfzS_U$x!%c{!D8#~ZKz{4 zuS=M&Al|u9Z0!U0%W3CNo|QCI*jPKEJ|X4$6+z3(%X`nix@#$L?tq_4M_?`clBM64 zX<WZ|(RPEg)B3vF>SJy{ETT5)Ny&b)&{-9mvSR=4=BYC~XC66t*Iq>@<lWn(<YQX# z(``yi${4pKW+p9Iy*N8TX=7nQ$(GG#<}NRqnB97OLw%$rX9WcQj|-Nr>#_Qu^{K zo6Ev;d+%-Vp5}ISf#2OpyN<h^dir+KalPBMzYcZ2<!(RrQ$u>fdxH%d>XNUicCEEP zSeIq2UU{eCVX_;aSJ&Gq6YO%o-kYrcecilE`iGA8>^0LW+0!gn+3~k#o@}tXhS<5e zRys?=Pk9_|+w1-<f8K1_=jqO`PtG$*uupL~WN`GA@9R&?`(=!BPE9(y+y19Pea-s< z@n2$A2Q+7Bys}LDI4#!tn*JQKx}bZXe51|v=g&H}%jV-0_bto!{eIyZUG`ot;^5gc zbGQF#=Kr)jy^J>{;jrMj3nmkO9ZP*$yP@>=vZ>skK0VWmvMDc0+b$r^{pxLBKpd|v z_w^Na$<NpQc<@*C&YGE8#`FCpC(jdD_C-_u&7`Yl+djXZW0X~OZ_XV};p4q>c02rY zHmu$%c+KeT^()5ZTpfOX=jF^wPAp*jJLwTao7akIUt^>qESSPx-C7&%RO8eBfuY>G zds<z}0sg38X=ZwH|2`>HHmqOXJ@-h9lE)*zeTVu=l#R7zz9*(9r{?)Es()0{&s=W) zz(e%0xSK^rOIh0QEs`0Zx_C_#8@B|7go>oxmtJ?_#H$F`-}+G&4_E@%bgi=T7SFh( zZTRy7OZnl+ahm-rC(qB|*O<4aYw!Fm?4lF97_xr2hreXrWm4=YlBE>5!me&FXT@f> zGUFZAXZ=@PNI$A>ptAn`V!rE-4O?IF$wXWhH}ik0A*274L+;aNQ;nWYZM>4kI>!qS zUC~T-@0Gt+mT<AYN|7sa^)CNA=jBAd)NbO4e8)EXk8kY!<_)n5DF@P=jE)^J<KC9q z!sD-=A~VNcZ_0#|-kdY7CQo=N%yCj%Ife1hwWifAIx?$d8ooSR!xb9;@%6Lk{@(t% z(Kdw%H8Z9+vrdo>6%AC|R})yC6Q^I!o8%;O^w|7$=ku34uIX5N<H-HlEt`{<DE%+t z`LS>6iTc?*c6x%XS_R<(dHEbRH;VjDn{G=ozQY<<#D4Li|K`1$uUbd{t<IV1{3F|9 z$8XmAcg}F{Il+CT`A@8rS>ol1-KtG1^mk3zFTF$MoW`183nNWLWlx^oSU$TlP{hT1 z$GrQ07H4SR60UnQeUa>`#b-mfjxMt8TD-{hw)Jhn#5EZjt2ocz&ztJRb5U?U_gVdU zcdU06yP1nKXSlW=U$pFo#+f%+tKFD7HgLGl`(&XLcR+FJ*&WyaRQ31SJ}s1+I%O5> zov({`_gY-+@~f`wV`snAeE;!59-AMvuMg%InEw?oXTNZF|K7?_Dcc{iaxyLK^%;9# z?7m<0UuM^Dp7PHx-zo3Ol9xU#*K_%8!uwaRf2K??c+d1Mw&L@R%sbY9v#Y=8E&um3 z_MdOL8T)aiN7p@0^Xkg%IrNC#FJ{l%ke8RApIx*)!*SL#+11sI>lf=jT>oFis$sE- zr`p}euF@B0en_6zb!}14hm-fagf8;7Cq*wRsCIsEa9VNHx<VD3z3s{y|6k5|f9A_M zpZ{LQu9MT(M@Qet{PocD<;~j9mlx!IRZv^h^`R-h>fe)FvmO>4=!|f_^ZWJjy$z`e zZ+0cJZ#*6MWPXLC@mqyY>Tf!9PwhY6P;zAF>TOSUo0&gn?O;4sac8d0^oqWS${$`o zC(F-bog<-G(sFG#C*P%+MolcU*;0k?-pbqDsu%TNI7+&(`P#C(t?$ep=B4lQmcEm+ z>-XE)ym`O$P0wcTzhbg|+nfEDzHHxi_y3!J%F)d%e#s*H4(-+55#IKyIi&XM^{C7D z?^|u(w*UYCvS0C4>AUM$-rN8FpUW&+9a!P|SA5Rdc{d)`=&=`MFO=AGo2}GOLq%c9 ziek3s>~pynSX?+6;NjpA@Z3u$@VT2#!1F#Qrb9BNaz}Vd=N%C#jnhz3@CkVC+Y|WQ zxhLRxw-eJLfzmpQ+1qFQ5U#z#x?n=X1?O0Wi>|WkmM~extmG_l+~MOb7R|j$BCfCe zTW$J%`>nPA=W2Y@I+u{FKJD?rzdOEn$i;N+j=y+U=FZ=?cgr5XyZ_={!*y=6ln3|9 zza&V#yVNScwpGrj{<BZn@<#jJFY|ZX+j@itcpcd5X2pDdy{gxzCXw=J=49=sKiNMC zf8uU5m1yjp*0HDKUxD$u^IAW-_zvbNJgj|H@V9MuK>b;{=PVXy%zIl`<(kcKo!<FF zME%RIJqPZl@Az=p*y?IvSIrxVcmH0rsUI<U*n0oxW69@*+bt!_e?Lxr{xN)-+2f1r zKU&qj^uF`_W^4b)DM>b|l79>9bmYpij~rIr!R^nx+y7(P{Rj6-Z8AQvzWc{oe)ins zWRuP5=YAbc|L6VMxZdk|$>sTS-tsSZik#P2eqN?)cVop($r^?2^QWAD<9AQ2Ejw4J zCEQ`@&BR2L4LRy_9`q~_`{UYmNUViha9Kc$_LZ(Mj-=383`cf73Q6iJw`|z<?uSuC zhujOhXBvAP8Lrp)n+Wf{5VlOAqBPD#aBtzg6`boDwt606J>IhZrqmLf4P^p>O6%Oz zYIGjmI`-i7FNF%(xGTa3dp0VqtJ0AXEG?XP?D---E@puT{k8{>D4q#q__UW{eNFoP z@^62QZ(sjp&;0oPCR3KCn^qBfHq2y|v{-RqZ~n`JYs`~<W*_)`dg4mo7r!b~y#6me zG5uTgJAe7s_ve(P-??q7U<=>*KrXg+rn$nw{Z79#{w!Lpf1!h;TD@>Rm*f*|7Lh|y zJqh0v`}+^J#jH5mynVw*yEegf%DH!ECvQ-k9&`Ax|A&Ha+jm5>xzFZ(wlAqY@xIP# z$?w@OKh9-}zR0nzC-cDF^B+%jn#|krFz=XlYQlv5eBzF44PEZ3Z8;IG+_%S+k9AwG z-&#lQ4Za54IlYCB>zU{8QI(qZNUwWhcfs^Fzi%^i7F;@>QaH`_S<tr`xAspc7gYS$ z_4dFTmj7NI5~^nDf=X^lF=2`mJ06DwdN{Z!^aU$F%(0wja3yoWga!`RxoVt_bHzB_ z=9+PFb|_qVDPZ}k#8ctbmjDk3mIZ$Ee=I)N@MGaQfmW6l{Z~C5{I7aC&0qNhcsNun zJU69c(Yc<A1?Oa1Sz4@L>2yfH(&^NGrJ|vtkg{U4lHQ8VYUfr=UNoVhz-cb;w*ryN zeEb&@|Fg%oo|P*V=@U1$_}5i7t)XwxCmpuq-I6l(tOa+ZN=2ro8(PHi6#SWc@V?}q z`ke=_im*t%`{r_^Enc-STPbi!<geb2MUAzkFEoF@3gG<x>O#c4+R_(Ru?}<l1s&Q1 z>+Wd>$~H02|IU1*Mc`0-nDcA?BF46f3AY#?HSJvEo3g}B`non}z$B@E>)AZGrmSh3 zf3NN8ogd6=*rtEF7<6gY^@$1%Y#m`ymp{z9mXqzBJu51cH}~@XL(!LuUl+X3^mbr6 zopJevsKZ+4<|u{eiC#bY*wm`7KmXFQ^owD9n$}LyIhXcNjhdUkG|bm<?Uh#%+FPqW z=r0Qs`V(?e`&*>~=iekw3wMci8=`#<6`oxl{w3IHL3e_;uIr;!Zbu);?)kwb>o(;; zyu~_$8K2{;wBL%|zIZCF?)%P5?@J8SwD0ygb%m|3{*?dV()uZW;vKTmx7NIN%_y|I z#T|TTSNyz9@20<g6KquaCfMjf;uVqOGc@-tUgof!>-g6n2bQid{AHXx=eT$Ti@wur z8Ru*p1+HAiaP`aLg|gX-p-22R8)iQW7i|fDvpG>naQ|inp7i-TTB)xmuQuu0V!I(R zUT>C*xc2%*@sU5?@0%-LG&yX6`|DTl4c9l`>ppYc;eDl#_J!XYc`s;ZvQ{xMSMkR) z?`;cP@SXSdw+Y+J+D_d5GLdCl+1xD(wg=8TdOhcGEMNHKiH(TulwVWWW<8KFK4`qH z!p270Y{wPbjf~6ex_OO%8Je=}Ff(PTu+BYI@8rzlwDxhrO7BG%RJMt;s{c4V*`{Ny zRz#DAz@98)m+;V-AErSe&Oam-R|!AlHjKIA@Ik&!iJ?VJFI-Y9>*1pnii^w^{Ywy; zs8CXnyHz1j{AP;`OVMVBK>j3dj#?!dG3J83`{iBhMSdyp6k0mj$0&SU^P>Cp&VMSu z7BKK>%zAKY*S#Hw-iBWEHc>w0eNnhom7};~qbvVKCdp~mlXiwLlID^Y5c>0B?&^%z zY}QjQ*-WWrjt^O!y0{swy3KY-trO;mTN_y-lH2)!?+{<H!;FTOG})OO8k!YlHr()N zX*KO(v1b-~<5HnJZ{q`lV@=zQ#r~Kl99)+n?A2u5T#^2@JnX-Ha_QC#Cc$mC2P4`A zf7txV6;qUPd-$qbKvCJy%kj#R`D!f=QhknZB>x6+vPA#c!+s?GSK}eqFUlGMOAOER zm@l30)Oh<6%TfJH<p<In*9409J-QdK(c<N{_jLDl!C7XnqP{3@2;G14)Q7*f4E~5+ zkh~$*%eJj?W#ifxq4&B@KUtgM>zAm{T-YeW6>Org{KX6<J4@CxJRGNPGr0WBzM+wS zbke7=7R~TO=XS;S+xxD6e16-ukIz?M`*FF+=}GQ|&OfGUoLQ_!pUi%^-Q%i$vNmCb z@AD4PXY1kw%|(Q!9Xge?b9K_R-BqqOfgTZD+TBmrbw$2=CHm1(F;R1k&a~ZHX**Yk zGo0cHa1V}%)F}@=Qxv|QqwY6TiHJ?A;fIhj2QC+L&HIsN%eLqVkIhrV4<-GL%f+jB z{7*@iol3s(QjXQP_eyWGpp~d_>oFN6o}&%F!oL(2+WqZY{owqb-|oV%?jE}S#X9tm z_o01RE%GZHkN;wlTfO+lIji?;KHG2YyZYX<fpt&lzR5o~eKky)w|!F1N&hvBO?UZj zv?T6+!oU2Ekml>g=LNUaH-z!{N&3$$WZt`h>HNR8dj*pg<m{U$bvf<L%>9$*AO81U zHct2pzow<zigW*2wc|M-{@h~r=0{F;<HV)hSH0v8MC=h;%0A`Tel_0v7fnN)H+JS6 zihF0grZ^@zCG!6LDG&c{T^OubuaN!6%I8x1!}>4B)tCJHw1(O4d#py}<PU$WwpwgZ zsNJ~ZZNTRH8=OxpXP6&i_$%PX7v2MErYmMIZ<u|>v$#FlCP9_=lE~)I*^CU6)G|xt zHvDXKxOh?b<+J^Np2=tZJ<8{jSi)KJzjr^I%+4RX^FDK1FLHXi=tukePp{8^XU{*g z`T6g~<&Dpaoo9Fz7u?@0BXho};BF+}JCV}||GE?xG`RR0vQ9q~RN$(^`h8NZ=jEo< zM{OHKVm4+lG=<l?78fwMel=t@?_2udR3z8BiAx{MiQvjJ@je*4BxU;bAJZ<zq|du} zXJOB?xD=oGpPeS<^J=Xtl@|ZH-uRGd&Yw=f82e*i(u0@T|E~YA)BDF~)q<pjPpjX& z?RfS2{l<3X6Jg8ce{miAzGwB1bA9jM{J5XuzS_*tdV{YHe-7`*#<h*{_qf=f=xRLt zeJ$sOvD@;fpmoVpSBBnlU3S=L+Lrb=;qShPeO_h1Jm&PRfOXT}l~iV{@808k|9Aef z7~i#1UUMvtVc?5TxIXubw3(fD#LvvB_EL|dH^1n<!C`cxx~DpRv)-YvId;AqK0OY# zxE8e{^?1{Ua7XU+a}J!BUYJK|UF7(;rR@hVL+k9MYu6S}zf*bR@Ao!gM)3pnhDRBg z>Vt!)Nj9Fif5P8fVaH+lsRE)*pC$?isy<}6tm4w!a;Sfr0Iv|wb;f5GRJPaEbNv3~ zz~gyfWxLGJ=kqzQFOgqRJ=@qgHtOnW>3@Z3&x#lVs;du~eek_o9h>N_n(|cBDeU&4 zXUx&oPS+0AUf-{h!u;pmv;9JwQbiS6?{eIn=W}9R--e|J%p5I^Kg*kk#(ye(zT?Qe zy}y^Iru55LCw|&8bMvQX8XY}*-dx)2|7$~M<s8oE9#W4dU3Pn37&b>Y^VJpOWUch$ zo}BY%oU|--u-L`-JjQ}ku&Q94hT2}m4+*C&b+6x;l(vIA{k)|>yZu?W+^q#aXX)<# zCcnSnZCvW#=kfLbzq`dbMC;!E@bP3cZ?8b(fw0rt=4xb%taaIN^^flJ{X%bDG``RB zUL-te^VIFG;&1wItL$1-@ulsCi}lMJmb%v));`c%^ml*4kB{|v*<baY_Jy4}Ioq`O z))UTT_q6mSU*F#~He6?Xp)mMe>b)b0FKc&|GcrdN_f{^xJn3-<^Ty}1mZg1p<C4>1 zd^}xEC|l|AkB70G6KeflIO+uYRKdDk4`$u;y|?fFpKrZU-Vdbz|NDD={`K&CyUQN_ z_!k>}O((wNnozu%*&VB&AKOwhbT@9?_~ytq5aZ?Q&(Y5oZ*}>1Novcq6ZhjfuL-sK zX2{Q}z7YoP&<V^2nf(0Ex3}BtJiq2%Uu`Rxv~cBS<(e-cTCF<g7-u;sb{0R$33%DU ztE>^&bZO>hx24=BvlmQpRPOScvY_OtPT<R9kqa)(HD2yDWx<yRX98ZHoVn;yxA8&{ z_gPQi%fpfjFHJXI0^&aA33z$_<zl0T%Zt6HEZ})k5~%sSBtY^=X0WPP09$d?3Z94e zwz=PU{5<E4>xRvbw6z+!EE1F!JCq#x;$~;EENGPrr&qd9qliOrcB_}9$$=FvoL=E) z=8AOW%?LOte%G}aq=4UNmq^FF8J#D^_qqs!1oF>Z6X~#<ap<IY?Z?}>3tTw8?0r6q zbo_gBI*D<ST<9W}RE1}qTrQSry`PRM1kTn9Y%-D%_F+vr@p{|W-0fj}a|F7bdo1d* zO#I}YwD<`4-H=PZ&FiIUc072|!p6dfEeE%#itiHE&RHXBXtApEvAXMKGnxItkIr%a zh!iaEn=jn_c%em|lZm17yg3E}E#m4b0>J_`aq2RjM?XGZ)M@zfVM~a>zBv~}A57Oj ze*Rrg@&=1Ko^|Wqo#*`Pz*693)3A-9Z~j$D_x!>?Co&kyi~L?ND|HAzV)({d_~%T9 z%y-s>DpCugIn=)}37+DNWzgC8_S!kd{g+*q=hQ7t2sYJUxb@@W?i=5@y<d13{PSjw ziWWI{(L*7}C7anT&gb}qkNqM#Y;&BlA7B4=;FiODu}c@zYxXj&?aeeamRYz>YAx@c zG&$Mr$HKKQ+*(w?v9@>qJC^M3KdXP19FdM+=aBvQ`ca;OkUL&mww>4?;c)!aM^&yZ zW_5w#;>R!Rx@UL);pehC)wh4GLw5HezAf7{bdL6${EMnyr{$E~%wsjp*^2k9K$lM6 z;fv{>bGXDieWz%NJI>aaa=~R~;lmXn&kqHxJlGnf>J^Yxq`2bBqo%->XITSPy#ii6 zP=7YrB9_m+ued6PA#@STQoHB<Ud-qCr?$<}2XO_TH+v<Ylb)(JM;ye}eBSA0e2#hQ zvpLovF6;9)FYj}rQ-%E8rfN859^JX%(yU^)rBjL*c}-ccg>ea=S9FD?V<!7V_Nf|< zp3440-8LIdJ}sE!wm?U$a#F;T&ZQICr<yROZaguWWnz2OeulO4{jH4`6gmYSIrdL< z!^ZlbIdA4a(l-0HzJt$|QT3bmg?`O8kT)J3un)Mz*Ikn^*D<71Xo}Sh-C%|#Mgmi- zEPCXpXgIFym$hPD#8~$JNq5^Kh(Eruh;|&ip+ALx#hq@gz@|$gyC-nD7{3WPC4Sbm z9F)4b-&AV}=o&`O)%Pmc#01KsT%T{TE;3Eq`Po%dZLede&=iYqnJL>oY-*acZt}t( zU27)?9(feV*zNw)L~h}vV@s99`ne)(PA&h)G1Wv*bYn#b!$*&Wwo^Yuou9FmYi94J znY}4j+*T~vrj=rLD$Q(Cp!C8?w^mKKsWJPehg)uoSJrB$w8c4T%92|JwN?_ZVT0hl zN3&iuE}X;m)nUqm#>6>RRS6c$+fH%#O$BAZNx_b(BF863tdnh@RVE`7E^+3e$;AaT z@*J8Mu{5_m)aYX}l$k92GpS{T*HjHh$<D|2Tt_q}s{gcDAz|{?#e&bgnX5yMYpwSe zO=n9xb18O#;y)KM9=v@xX9ABB)8Tni96g<@R3-_xHFP{`ndk6m@eVat9mNkz&I*Wp z3^eArF84_FUtj@O?L=<TpYoz5F-G;VjoU?A*H%R5+`qcvJBw7k)uNwV_rgTBJ;*(( z#%MoPQq|1)bw7XYyayAe`TlShc(^U!W~b9vA?c&1pSwI>eP(I0y;9pf4S_#%&do@E z@}u*j#V;o3e3roHEiN+6j0?@%S_FBes+>F3+U^A`YHhS+VX@yW+_!(hLi3In1y1z> zyCh~jRWSI%CS)sB#oS@1{)IKMq4B0XOVs6liK0Uq0&a6I%>E&i+;iGa;fLf!hen?j zEB7{7G_Bm*A$cs-U*OM{j7N@VEUi9XZEF7TfUhaM<e-Y-QTcT)hd3p7%;IknmgI1e z&^ustk?owzDb8kx8wys1OpR^@D%-Ab@Ez$BzNDegs(ho_K{?=tu^(r3kmMWB28TB; zy$*%vBUInLJYV1+-d25pL*#pp(;es4NrGWVgIUiq%};xIuT<ymY5f%DL^-V+0@sow zM1Lf@%kUjG*FCgK;Aa%8^q;C3yd9CQ>_<N6Ki|C2Kw$dIfEj-yL?xyhPV6m|T-9_e z)#`M)c^GS*s!Z^M7mal@B=+}*DsowG)cWAvKg0U@{?LTbfbUC$ySFEXCR{kS#`=Fa zYZz<Yr7O(FpIJ+ijQCHme*Vhg_u`P3_=`hc2V4rhjL+*YVm^0~?VJVAU!E}5x;#;J z=g()kUj&ryb8HM%<T|eTl2!Ras*aSnkx$6#BQC8x!fTJMTHv-|!HOWxu5ZQxU+kD& z6Ii&qyaYuaN-yf2|A)^l`{c@tKjgng+>>X2|Dw~0PlC7Ssdw(N`qhWmlt#5iW}9rD zW<59fZ2i)+ZBiml1_$#?gBEk1yOQxod{)kcL+T0#qL^1)thm=V^YuhF>3bVwTUhMx zce*{Ey>{l#S66QS_`_Qgs`bIjMCyLV!84)jj=6nX&%$`^l~3=n{U(Xev;tGRZ5$dG z%DVD(u2p?HDYC~|&5%#h+fqeKbNZPi8Kcg^6A`Br13h=9h&`U*+2edHh_BP@l<H=Q zcAq2}qiIDRAwhaGk6NS%J)Tf_K+%-*zNNUzwttT!Ue7-l^?%-$ug`ZsX$n~yb?eXa z&Cm9$o2^nYo9@=Q@y0*(LatuR3xASs&tj;rn8emT+w)6>g?sCVLgNQsI|9Rdlq((! z79{_;xv%oW=2=U27XR1$5MlKsH0jiZIgwl%G45NU>{44K#59a`l6p2Y7#^xQ#S!Q^ zGf^<Pg|$cUS+HA&m;AS-`KLIzC6v!B?-7_fMN-VrE#iPgqFrjsiX~?@bQm6DI>s@b zS(#<EZVjK%;TTiy;^mPuZaW>8+5g7UBXrf$!gnU!#nA?76ONwG+_CzQL%2fIRfSy% zFCtvqUFJ0$KI;;Ayv=3bcU@Vblk0zVrGA}$Z|P#ipSHdqHYaRl{r%sG-F9D8@rP%V z#hFCbDeJMTEk3}mY{%-*%JU<|_<{1`1ME{p7(|U8Og`Jt-y>8Q666$j;>^6WXY>}Q zxvQGiD;igu8Sn0yB|G)XpVl*PZk~B#lvNfI^jX|!bGq?n_Mpw5Cp}j<_%15-%)98B zca2xxtz7@S<O9?Ca5rs+Emz*nyz*|(<>Ive=U*&nKViRvbN0*Jin&}?FQ)MSnie%X z|36Qi^t_{QxlFC*e^<3xDOV}F|49zB#C`XW6$L$JlCezRTlWXZayh@7FIRqegDYpH zjq(#?Yhx$77|#>c#!hm_IV@Y!y-u`iaaQVU888LA@qLt(v^<jTtn$Qj%Jk30Ns`L# zKYDs(9&MHr`Xo1H`r>IupJa}mX!Q~Ba*|^b+@XEIr6Iv`t^|wpqLzfcD;}gDH{>zf zXnZ(9lBZeKn8!@JFLA?1o@U;zV`@nP{}lKC_E-AndDLF{<N1(3lfVBuf8}~tNSV=} zJ1oBz?|mWMlg58Z)J3IwkB7-xt!awe*{3jeO_StKZBpX*Y*G4My#CX&UdbsU&byR) z@1M{3!{zq4KH$=iB-P&gM>GByxjk0Q3zn*n^?bZNxN+gkPe0a+<~)lMye7!k<z#mL z^Ut2+&JUIq-_uKwO?=>HcHUe+(dM7#<Bx|_*C+@6=-5=buTb^c#1r;2&wqF$sygp) z2iL!+)jSu>bP^iAF)?qsEwP|>V-MpkE4B=O?G27rz4a&F|NG4N&$6ff-NX6mKbF7z zIzN5AX#35RABy>3^w+t}U(jQFLd$Gzf%fdM9g~+D%+Eh$CG^w#XM}se5&jK*N5XyM zr_cXcV0dLB^RkS$0yA6!YYy!<NICJOjcfLf?E)+elM}l9f5?B4G}^i5(6T?iiFbeO z+j6<>f7tY^#teK`kp(=f^A0wLng0*Zjk<V9P~e`0$HXx6_lI6d3b0?>yg{5Lq*&_p z*350`UwJy1UrWk($*-<tdc8HXC*kXzgj276Zs1z|oO8|XXQ=|KUsyRuT|6WwkhsX8 zDfBzHec0WpQ}$*2ImWACTh)4Cj`NORZ2@v`4y6^|OZ%RGUahz<WwS-`1IY&$=Pf_D z_@MCn@<#WsN4a+HuAMPOBV^j&Yc?CBu61mmslt~T`u_5d<0>ER)SbGr6Muj5y}Pe) z!&AYc4~&ZLyAE9A-<H@iXNTK~NckJL1dAABehO{*IDNa&C(S?K&br)Kpt@`47xBqQ zvV<9q?GlbL;y?cDHskK?3up5rJfELi9X{*-Jznq6=Bp31^k{aQzp<>`y5!l(`2GK@ zl>-(`kE>0~v5dd2A?0W({nssL-(`)cr0dbo@~kehbnCoXHre-Hon~GAN=D<(x`6g~ z0qy4k+Wk&hmHgDN*mZyZUhVVs-`k%4jDCE7|NqyMXH8nI{yitcMpaqyLf5wsdvexT z?@x7;*T41p!i|db&m8vGmT$10tS9WSTe|G>ySDA|efMME)f;&{cx$hCJ1XkKG%?xj z(^#j!VRU?y=3WpY;CHil;p{07=Ge(tK5;YWJovNTLiEDqyk{)WxgKqCl;1T|U`}{P zFwftYX&e{c=T83}`}6+P`BUdV>x(G}67-cl88OTEwWPPA=q8aMGj9-=cZx}C$cali zH`h$}Ja#E(!IHhct!uVx&i-n2GGZ3*lr7s=PWWn;x;aiw^7RvD)wj7?DSLgvYOQ`c zcvjEmip&o-d!0IIqn};CrF+YquHBxZ`>Qkm{+66<&N$tJJmxWbc#lh1XvLo4T=RlQ ztt4=l#1+OJ)3;vQyXL@Nl?QRtyuNQ@_-@4h-6(k1bj=;pId@Focxi9XfxSHUt9IU> z`akyPO|=~xY%Uv5OD{@Pcs^6jd(NBm&dDXy(l(`6PCjpXBg$)cM7m%6wVBEuk?DSW ztzMteOqgqVH!|ICv+C<JE5nlKT4qP2`{}$slWCMZ*YbO4WcoQHfq9EAG=6=$$0%)X z+0j)wXEkJ+9xHPtuF-$q%J_Qo?q!F5y-C|-x7*>*m22l0_PQOP)~WQi-Yk;Ee2%@8 zpUKM}!8=Zz=gJOt>hCJyR<bZ=Q$HzjLAT+7iPW6HWFPbRrr^ASZ@rRt_i*@~Kgel4 zt;9L+m0Q8T{ib&>{L#I*R`t-<SU;h=@9!%AKQ0&9=9#`W{m1qReNRrNDOaZCY?SCo zDsk~wls-B6tlOs(FFfQzE(zMU=BW6aNuN|+yg2yZ^!^}2g&igBbMmTK#J?YS<IQn* z3#T4SQ+89!WnODj!_LKSi(V}ADrlW}?O$f=y*c&={~nMqvFALtpmUScG>y|~KRqQ+ z`!`K`c9JV{p3dy2>Zv;RE5G(EJ;@b0OK0}d<0(3}oL*K^%O|9&Z;mVra@#z4!QnS4 zifQVb9~N32$d}UKUe4cox%tpbE$-#at(V&lWnSdv?$~=uH_}8W!For1b(DkXrN*i2 zAJ2c#_D|`5vz+(Qn2^MkGdgudAD`XzqW(%^?3d+JV!tRyY8{*U^@9E7B-=0T5&X4m zuNR8TM5;aG_Pw@#pR~&ojU^Xqc=T^<@;ReiI*s9`S4NOZ=f9__FJ!kaa{8{cMP<p^ zCoVaRp$l0<7V9R6<T6HI(>TBz?J(!#GUw<60=Jl6T@*9mh;p#ZW#nBLX|PClfqgEc zZwB`ZZrug^xr}EsxnHpAE>O>9RNcZ_(k^zPcUwd5!gK2n&MEi*D_@soTJx&3B(S?; z*B$@KmeNl{)}0dD8gWo;Ye!o5zda_2i|4#sbt%yAkkhtT{w%VuTQW_oPQBd4CHwSC zebNm-?$`N=|8&>vZ~eJ_!#}ZS_YeJwo>31LJn_pgXp2kteJRa<Q>E_-zwh1Oyub5& zL$biVsbA}}Bk%LFR?T*9jB5MwhySVkOX-Z4@)=<Az`jO@rHB88?fFu@E#5e#Tkd`5 z_ha`D-gkD7{kLw(e{Szzc?Rd^mm2hm{a*KNJ?{y{|BZ~6S!-YIe*Le|;oM#2mMiO; z);{pP8{0Ucx~*l(5y2p?qdK+n+j3j(wEv#Aw&AU_la@`wZ0_5^POH)cgKFirRd2BU zb(GQ4K7Q{*`8J;oqMT7|z86F}Z!F;4rPS#8>|J_}Ytxb19M`4}?i|-9k!@@To6TLg zq9-=YyIj<(o7uMePh_}CMnbDRH1O3gXDIegi{n>N+6*p`2OGym;5lf=(&zN>Dk z{3fmxF?+(Hv{1VW=Or5|zkQiAEnDVDTG{07`Th6z{k>NC?bOb1`Cl{N3ZB1c`Jmx> zhS7!z56|SZ8K>s(S!ih9(@C)~p8e2AayB!cSC=`r<he6x7Qx4!H8f9pbk?cOc(dfW zDH|;xELc*p8K1Vu{wTBNnMP*pGE+qI#5T!oePdR9;J>upsh16wB39hbXR6I^-8}#7 zA<uN<$!~9}%sFp*LuF2Ej*wsc(=#cWvs;4KpSw4U$!y8a-9>4eRJm7Q&C2okEM>OD zGR)HWW>4$Y->Y&wJ{y@C?`$qg+hoYS`sk{hv`;o>#+E*o#y1;UuV!oIq<!)+Gqwz{ zG>+_dz1j`p|6lzq$7xa5A_kkjOG|{C0%itWJb!kPftK<F5tj*Bp^gF%7j4`faA}qV zS5wCI^QUgPUP#Kh%HMc5Oi#IGfr84GrZlm&voi1QdU@xwY<AoNm%xjUdJLW$ex9*& z-tTke_spLgOfJ_+Rnxz5((X~oa*Nn~JASA;T(vd1`|!Az-^!|nRn-~04);%867-cJ z^t<WOmwfhS!L6&<SL|wEX8k9^Q!A7|pp@UY{Kv*gA*<vTypo&s?nAQb$`D(a8A0e~ z{Ld(e|L?2Q&A#fpCVQ5-*o#9pOKv`_^$O}NZm_6!J*y|=ck;`%CzW6AUdL6;-xRiY z#jLysi_%3Li@CpV4mZAY-tOq%H|o9@?l8Dc)!zT()%Pju<kt(E2(NyT`Rep7k5hIg zD@7xYaM|R9C0K_&`0cjlKy*YS`x&m7PEm{b$GG-1ir&Z%OOOtGu-YW-LFk$Ta+{f= zH!{sPPhgEZ#C0b*EI};c8&g8q0j@Vj+8ZQ;)TSTKVx4!4>rR*Gk4($3gaceMX4(b9 zVGC;1vRLg7aM>h=J+NBiuv6+<=G)k1Tiwrcy*a?8W17f%FD<6}#F_)4R~G+tdv($G z)y0O$#$1slH%(YyO0j0{k8E5kqLRrKrv7i|{|mK>`%PnRo-J5<_sRM*GTD1iM4dN` zy_xqZysYnNT*}7hC3`jr{(QZ)H+<2brE)I&PsNvq{L89q{&O|=Q+T}S&()tLKV46q zyx(eFy~{tN7XnY$A31c)IO@~Pb2~Ijxo>2Lo#xucka@U-+v2>~h14)_?&yX!)_0kX zoyod+Oim$phTn<#28#BnVW-o+F+^5ac~zd!NIkJ;+SfOXn?7tgSan20H9yRoKdgI8 zVib#9wBU)^S1<XBPB8OXeV}&LfsROB>y=FT(ObBD(jKeZ{>%<LolrBQgWve$!bw}A zwC)QD%jo2P_q+e4XWl_?za{*uQ$<!UO$a+J5Z3)AJ8P>CuU>@it?jaZX0G#%Uf-B# zZx(bS-eUKQ_iz99p40tn8*BCHaHdyyxRn3WQ{t-YREn2oc1m_ec206}eY9Cdedne* q{*}EglW(YA)K;AD{d0zkU(y|`?YI8Rbl0AZXOyy@vUI{-1_l6FF6UVQ literal 0 HcmV?d00001 diff --git a/Utilities/FLTK/fluid/makedepend b/Utilities/FLTK/fluid/makedepend new file mode 100644 index 0000000000..86b86c162b --- /dev/null +++ b/Utilities/FLTK/fluid/makedepend @@ -0,0 +1,327 @@ +# DO NOT DELETE + +CodeEditor.o: CodeEditor.h ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H +CodeEditor.o: ../FL/Fl_Text_Buffer.H ../FL/Fl_Text_Editor.H +CodeEditor.o: ../FL/Fl_Text_Display.H ../FL/fl_draw.H ../FL/Fl_Group.H +CodeEditor.o: ../FL/Fl_Widget.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H +CodeEditor.o: ../FL/Fl_Valuator.H ../FL/Fl_Text_Buffer.H +Fl_Function_Type.o: ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H +Fl_Function_Type.o: ../FL/Fl_Preferences.H ../FL/Fl_File_Chooser.H +Fl_Function_Type.o: ../FL/Fl_Double_Window.H ../FL/Fl_Window.H +Fl_Function_Type.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Group.H +Fl_Function_Type.o: ../FL/Fl_Choice.H ../FL/Fl_Menu_.H ../FL/Fl_Menu_Item.H +Fl_Function_Type.o: ../FL/Fl_Image.H ../FL/Fl_Menu_Button.H ../FL/Fl_Button.H +Fl_Function_Type.o: ../FL/Fl_Tile.H ../FL/Fl_File_Browser.H +Fl_Function_Type.o: ../FL/Fl_Browser.H ../FL/Fl_Browser_.H +Fl_Function_Type.o: ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H +Fl_Function_Type.o: ../FL/Fl_Valuator.H ../FL/Fl_File_Icon.H ../FL/Fl.H +Fl_Function_Type.o: ../FL/filename.H ../FL/Fl_Box.H ../FL/Fl_Check_Button.H +Fl_Function_Type.o: ../FL/Fl_Light_Button.H ../FL/Fl_Button.H +Fl_Function_Type.o: ../FL/Fl_File_Input.H ../FL/Fl_Input.H ../FL/Fl_Input_.H +Fl_Function_Type.o: ../FL/Fl_Return_Button.H ../FL/fl_ask.H Fl_Type.h +Fl_Function_Type.o: ../FL/Fl_Widget.H ../FL/Fl_Menu.H Fluid_Image.h +Fl_Function_Type.o: ../FL/Fl_Shared_Image.H ../FL/fl_draw.H ../FL/Fl_Tabs.H +Fl_Function_Type.o: ../FL/Fl_Pack.H ../FL/Fl_Wizard.H ../FL/Fl_Menu_.H +Fl_Function_Type.o: ../FL/Fl_Input_Choice.H ../FL/Fl_Window.H +Fl_Function_Type.o: ../FL/Fl_Menu_Bar.H ../FL/fl_show_input.H ../FL/fl_ask.H +Fl_Function_Type.o: ../src/flstring.h ../FL/Fl_Export.H ../config.h +Fl_Function_Type.o: function_panel.h ../FL/Fl_Light_Button.H CodeEditor.h +Fl_Function_Type.o: ../FL/Fl_Text_Buffer.H ../FL/Fl_Text_Editor.H +Fl_Function_Type.o: ../FL/Fl_Text_Display.H ../FL/fl_draw.H +Fl_Function_Type.o: ../FL/Fl_Text_Buffer.H comments.h +Fl_Group_Type.o: ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H +Fl_Group_Type.o: ../FL/Fl_Group.H ../FL/fl_message.H ../FL/fl_ask.H +Fl_Group_Type.o: Fl_Widget_Type.h Fl_Type.h ../FL/Fl_Widget.H ../FL/Fl_Menu.H +Fl_Group_Type.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Widget.H ../FL/Fl_Image.H +Fl_Group_Type.o: Fluid_Image.h ../FL/Fl_Shared_Image.H ../FL/fl_draw.H +Fl_Group_Type.o: ../FL/Fl_Tabs.H ../FL/Fl_Group.H ../FL/Fl_Pack.H +Fl_Group_Type.o: ../FL/Fl_Wizard.H ../FL/Fl_Menu_.H ../FL/Fl_Menu_Button.H +Fl_Group_Type.o: ../FL/Fl_Menu_.H ../FL/Fl_Choice.H ../FL/Fl_Input_Choice.H +Fl_Group_Type.o: ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/Fl_Window.H +Fl_Group_Type.o: ../FL/Fl_Menu_Bar.H ../src/flstring.h ../FL/Fl_Export.H +Fl_Group_Type.o: ../config.h ../FL/Fl_Scroll.H ../FL/Fl_Scrollbar.H +Fl_Group_Type.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H +Fl_Menu_Type.o: ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H +Fl_Menu_Type.o: Fl_Widget_Type.h Fl_Type.h ../FL/Fl_Widget.H ../FL/Fl_Menu.H +Fl_Menu_Type.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Widget.H ../FL/Fl_Image.H +Fl_Menu_Type.o: Fluid_Image.h ../FL/Fl_Shared_Image.H ../FL/fl_draw.H +Fl_Menu_Type.o: ../FL/Fl_Tabs.H ../FL/Fl_Group.H ../FL/Fl_Pack.H +Fl_Menu_Type.o: ../FL/Fl_Group.H ../FL/Fl_Wizard.H ../FL/Fl_Menu_.H +Fl_Menu_Type.o: ../FL/Fl_Menu_Button.H ../FL/Fl_Menu_.H ../FL/Fl_Choice.H +Fl_Menu_Type.o: ../FL/Fl_Input_Choice.H ../FL/Fl_Input.H ../FL/Fl_Input_.H +Fl_Menu_Type.o: ../FL/Fl_Window.H ../FL/Fl_Menu_Bar.H alignment_panel.h +Fl_Menu_Type.o: ../FL/Fl_Text_Buffer.H ../FL/Fl_Text_Display.H +Fl_Menu_Type.o: ../FL/fl_draw.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H +Fl_Menu_Type.o: ../FL/Fl_Valuator.H ../FL/Fl_Text_Buffer.H +Fl_Menu_Type.o: ../FL/Fl_Double_Window.H ../FL/Fl_Window.H +Fl_Menu_Type.o: ../FL/Fl_Preferences.H ../FL/Fl_Tooltip.H ../FL/Fl_Button.H +Fl_Menu_Type.o: ../FL/Fl_Box.H ../FL/Fl_Light_Button.H +Fl_Menu_Type.o: ../FL/Fl_Check_Button.H ../FL/Fl_Light_Button.H +Fl_Menu_Type.o: ../FL/Fl_Button.H ../FL/Fl_Spinner.H ../FL/Fl_Repeat_Button.H +Fl_Menu_Type.o: ../FL/Fl.H ../FL/Fl_Return_Button.H ../FL/Fl_Round_Button.H +Fl_Menu_Type.o: ../FL/fl_message.H ../FL/fl_ask.H ../src/flstring.h +Fl_Menu_Type.o: ../FL/Fl_Export.H ../config.h ../FL/Fl_Output.H +Fl_Menu_Type.o: ../FL/Fl_Input.H Shortcut_Button.h +Fl_Type.o: ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H +Fl_Type.o: ../FL/Fl_Browser_.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_Type.o: ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H +Fl_Type.o: ../FL/fl_draw.H ../src/flstring.h ../FL/Fl_Export.H ../config.h +Fl_Type.o: Fl_Type.h ../FL/Fl_Widget.H ../FL/Fl_Menu.H ../FL/Fl_Menu_Item.H +Fl_Type.o: ../FL/Fl_Image.H Fluid_Image.h ../FL/Fl_Shared_Image.H +Fl_Type.o: ../FL/Fl_Tabs.H ../FL/Fl_Pack.H ../FL/Fl_Group.H ../FL/Fl_Wizard.H +Fl_Type.o: ../FL/Fl_Menu_.H ../FL/Fl_Menu_Button.H ../FL/Fl_Menu_.H +Fl_Type.o: ../FL/Fl_Choice.H ../FL/Fl_Input_Choice.H ../FL/Fl_Input.H +Fl_Type.o: ../FL/Fl_Input_.H ../FL/Fl_Window.H ../FL/Fl_Menu_Bar.H undo.h +Fl_Type.o: ../FL/Fl_Pixmap.H pixmaps/lock.xpm pixmaps/flWindow.xpm +Fl_Type.o: pixmaps/flButton.xpm pixmaps/flCheckButton.xpm +Fl_Type.o: pixmaps/flRoundButton.xpm pixmaps/flBox.xpm pixmaps/flGroup.xpm +Fl_Type.o: pixmaps/flFunction.xpm pixmaps/flCode.xpm pixmaps/flCodeBlock.xpm +Fl_Type.o: pixmaps/flComment.xpm pixmaps/flDeclaration.xpm +Fl_Type.o: pixmaps/flDeclarationBlock.xpm pixmaps/flClass.xpm +Fl_Type.o: pixmaps/flTabs.xpm pixmaps/flInput.xpm pixmaps/flChoice.xpm +Fl_Type.o: pixmaps/flMenuitem.xpm pixmaps/flMenubar.xpm pixmaps/flSubmenu.xpm +Fl_Type.o: pixmaps/flScroll.xpm pixmaps/flTile.xpm pixmaps/flWizard.xpm +Fl_Type.o: pixmaps/flPack.xpm pixmaps/flReturnButton.xpm +Fl_Type.o: pixmaps/flLightButton.xpm pixmaps/flRepeatButton.xpm +Fl_Type.o: pixmaps/flMenuButton.xpm pixmaps/flOutput.xpm +Fl_Type.o: pixmaps/flTextDisplay.xpm pixmaps/flTextEdit.xpm +Fl_Type.o: pixmaps/flFileInput.xpm pixmaps/flBrowser.xpm +Fl_Type.o: pixmaps/flCheckBrowser.xpm pixmaps/flFileBrowser.xpm +Fl_Type.o: pixmaps/flClock.xpm pixmaps/flHelp.xpm pixmaps/flProgress.xpm +Fl_Type.o: pixmaps/flSlider.xpm pixmaps/flScrollBar.xpm +Fl_Type.o: pixmaps/flValueSlider.xpm pixmaps/flAdjuster.xpm +Fl_Type.o: pixmaps/flCounter.xpm pixmaps/flDial.xpm pixmaps/flRoller.xpm +Fl_Type.o: pixmaps/flValueInput.xpm pixmaps/flValueOutput.xpm +Fl_Type.o: pixmaps/flSpinner.xpm pixmaps/flWidgetClass.xpm +Fl_Widget_Type.o: ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H +Fl_Widget_Type.o: ../FL/Fl_Group.H ../FL/Fl_Input.H ../FL/Fl_Input_.H +Fl_Widget_Type.o: Fl_Widget_Type.h Fl_Type.h ../FL/Fl_Widget.H +Fl_Widget_Type.o: ../FL/Fl_Menu.H ../FL/Fl_Menu_Item.H ../FL/Fl_Widget.H +Fl_Widget_Type.o: ../FL/Fl_Image.H Fluid_Image.h ../FL/Fl_Shared_Image.H +Fl_Widget_Type.o: ../FL/fl_draw.H ../FL/Fl_Tabs.H ../FL/Fl_Group.H +Fl_Widget_Type.o: ../FL/Fl_Pack.H ../FL/Fl_Wizard.H ../FL/Fl_Menu_.H +Fl_Widget_Type.o: ../FL/Fl_Menu_Button.H ../FL/Fl_Menu_.H ../FL/Fl_Choice.H +Fl_Widget_Type.o: ../FL/Fl_Input_Choice.H ../FL/Fl_Window.H +Fl_Widget_Type.o: ../FL/Fl_Menu_Bar.H alignment_panel.h +Fl_Widget_Type.o: ../FL/Fl_Text_Buffer.H ../FL/Fl_Text_Display.H +Fl_Widget_Type.o: ../FL/fl_draw.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H +Fl_Widget_Type.o: ../FL/Fl_Valuator.H ../FL/Fl_Text_Buffer.H +Fl_Widget_Type.o: ../FL/Fl_Double_Window.H ../FL/Fl_Window.H +Fl_Widget_Type.o: ../FL/Fl_Preferences.H ../FL/Fl_Tooltip.H ../FL/Fl_Button.H +Fl_Widget_Type.o: ../FL/Fl_Box.H ../FL/Fl_Light_Button.H +Fl_Widget_Type.o: ../FL/Fl_Check_Button.H ../FL/Fl_Light_Button.H +Fl_Widget_Type.o: ../FL/Fl_Button.H ../FL/Fl_Spinner.H +Fl_Widget_Type.o: ../FL/Fl_Repeat_Button.H ../FL/Fl.H +Fl_Widget_Type.o: ../FL/Fl_Return_Button.H ../FL/Fl_Round_Button.H +Fl_Widget_Type.o: ../FL/fl_message.H ../FL/fl_ask.H ../FL/Fl_Slider.H +Fl_Widget_Type.o: ../src/flstring.h ../FL/Fl_Export.H ../config.h +Fl_Widget_Type.o: widget_panel.h ../FL/Fl_Value_Input.H ../FL/Fl_Input.H +Fl_Widget_Type.o: Shortcut_Button.h CodeEditor.h ../FL/Fl_Text_Editor.H +Fl_Widget_Type.o: ../FL/Fl_Text_Display.H ../FL/fl_show_colormap.H +Fl_Window_Type.o: ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H +Fl_Window_Type.o: ../FL/Fl_Overlay_Window.H ../FL/Fl_Double_Window.H +Fl_Window_Type.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_Window_Type.o: ../FL/fl_message.H ../FL/fl_ask.H ../FL/fl_draw.H ../FL/x.H +Fl_Window_Type.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H +Fl_Window_Type.o: ../FL/Fl_Round_Button.H ../FL/Fl_Light_Button.H +Fl_Window_Type.o: ../FL/Fl_Button.H Fl_Widget_Type.h Fl_Type.h +Fl_Window_Type.o: ../FL/Fl_Widget.H ../FL/Fl_Menu.H ../FL/Fl_Menu_Item.H +Fl_Window_Type.o: Fluid_Image.h ../FL/Fl_Shared_Image.H ../FL/Fl_Tabs.H +Fl_Window_Type.o: ../FL/Fl_Pack.H ../FL/Fl_Group.H ../FL/Fl_Wizard.H +Fl_Window_Type.o: ../FL/Fl_Menu_.H ../FL/Fl_Menu_Button.H ../FL/Fl_Menu_.H +Fl_Window_Type.o: ../FL/Fl_Choice.H ../FL/Fl_Input_Choice.H ../FL/Fl_Input.H +Fl_Window_Type.o: ../FL/Fl_Input_.H ../FL/Fl_Window.H ../FL/Fl_Menu_Bar.H +Fl_Window_Type.o: undo.h alignment_panel.h ../FL/Fl_Text_Buffer.H +Fl_Window_Type.o: ../FL/Fl_Text_Display.H ../FL/fl_draw.H +Fl_Window_Type.o: ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H +Fl_Window_Type.o: ../FL/Fl_Text_Buffer.H ../FL/Fl_Double_Window.H +Fl_Window_Type.o: ../FL/Fl_Preferences.H ../FL/Fl_Tooltip.H ../FL/Fl_Button.H +Fl_Window_Type.o: ../FL/Fl_Box.H ../FL/Fl_Light_Button.H +Fl_Window_Type.o: ../FL/Fl_Check_Button.H ../FL/Fl_Spinner.H +Fl_Window_Type.o: ../FL/Fl_Repeat_Button.H ../FL/Fl.H +Fl_Window_Type.o: ../FL/Fl_Return_Button.H widget_panel.h +Fl_Window_Type.o: ../FL/Fl_Value_Input.H ../FL/Fl_Input.H Shortcut_Button.h +Fl_Window_Type.o: CodeEditor.h ../FL/Fl_Text_Editor.H ../FL/Fl_Text_Display.H +Fl_Window_Type.o: ../src/flstring.h ../FL/Fl_Export.H ../config.h +Fluid_Image.o: ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H +Fluid_Image.o: ../FL/Fl_Widget.H Fl_Type.h ../FL/Fl_Menu.H +Fluid_Image.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Widget.H ../FL/Fl_Image.H +Fluid_Image.o: Fluid_Image.h ../FL/Fl_Shared_Image.H ../FL/fl_draw.H +Fluid_Image.o: ../FL/Fl_Tabs.H ../FL/Fl_Group.H ../FL/Fl_Pack.H +Fluid_Image.o: ../FL/Fl_Group.H ../FL/Fl_Wizard.H ../FL/Fl_Menu_.H +Fluid_Image.o: ../FL/Fl_Menu_Button.H ../FL/Fl_Menu_.H ../FL/Fl_Choice.H +Fluid_Image.o: ../FL/Fl_Input_Choice.H ../FL/Fl_Input.H ../FL/Fl_Input_.H +Fluid_Image.o: ../FL/Fl_Window.H ../FL/Fl_Menu_Bar.H ../src/flstring.h +Fluid_Image.o: ../FL/Fl_Export.H ../config.h ../FL/filename.H +Fluid_Image.o: ../FL/Fl_File_Chooser.H ../FL/Fl_Double_Window.H +Fluid_Image.o: ../FL/Fl_Window.H ../FL/Fl_Button.H ../FL/Fl_Preferences.H +Fluid_Image.o: ../FL/Fl_Tile.H ../FL/Fl_File_Browser.H ../FL/Fl_Browser.H +Fluid_Image.o: ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H +Fluid_Image.o: ../FL/Fl_Valuator.H ../FL/Fl_File_Icon.H ../FL/Fl.H +Fluid_Image.o: ../FL/filename.H ../FL/Fl_Box.H ../FL/Fl_Check_Button.H +Fluid_Image.o: ../FL/Fl_Light_Button.H ../FL/Fl_Button.H +Fluid_Image.o: ../FL/Fl_File_Input.H ../FL/Fl_Return_Button.H ../FL/fl_ask.H +about_panel.o: about_panel.h ../FL/Fl.H ../FL/Enumerations.H +about_panel.o: ../FL/Fl_Export.H ../FL/Fl_Double_Window.H ../FL/Fl_Window.H +about_panel.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Box.H +about_panel.o: ../FL/Fl_Button.H ../FL/Fl_Return_Button.H ../FL/Fl_Button.H +about_panel.o: ../FL/Fl_Pixmap.H ../FL/Fl_Image.H +align_widget.o: ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H +align_widget.o: ../FL/Fl_Window.H Fl_Widget_Type.h Fl_Type.h +align_widget.o: ../FL/Fl_Widget.H ../FL/Fl_Menu.H ../FL/Fl_Menu_Item.H +align_widget.o: ../FL/Fl_Widget.H ../FL/Fl_Image.H Fluid_Image.h +align_widget.o: ../FL/Fl_Shared_Image.H ../FL/fl_draw.H ../FL/Fl_Tabs.H +align_widget.o: ../FL/Fl_Group.H ../FL/Fl_Pack.H ../FL/Fl_Group.H +align_widget.o: ../FL/Fl_Wizard.H ../FL/Fl_Menu_.H ../FL/Fl_Menu_Button.H +align_widget.o: ../FL/Fl_Menu_.H ../FL/Fl_Choice.H ../FL/Fl_Input_Choice.H +align_widget.o: ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/Fl_Menu_Bar.H undo.h +alignment_panel.o: alignment_panel.h ../FL/Fl.H ../FL/Enumerations.H +alignment_panel.o: ../FL/Fl_Export.H ../FL/Fl_Text_Buffer.H +alignment_panel.o: ../FL/Fl_Text_Display.H ../FL/fl_draw.H ../FL/Fl_Group.H +alignment_panel.o: ../FL/Fl_Widget.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H +alignment_panel.o: ../FL/Fl_Valuator.H ../FL/Fl_Text_Buffer.H +alignment_panel.o: ../FL/Fl_Double_Window.H ../FL/Fl_Window.H +alignment_panel.o: ../FL/Fl_Preferences.H ../FL/Fl_Tooltip.H +alignment_panel.o: ../FL/Fl_Widget.H ../FL/Fl_Button.H ../FL/Fl_Tabs.H +alignment_panel.o: ../FL/Fl_Group.H ../FL/Fl_Box.H ../FL/Fl_Input.H +alignment_panel.o: ../FL/Fl_Input_.H ../FL/Fl_Light_Button.H +alignment_panel.o: ../FL/Fl_Choice.H ../FL/Fl_Menu_.H ../FL/Fl_Menu_Item.H +alignment_panel.o: ../FL/Fl_Image.H ../FL/Fl_Check_Button.H +alignment_panel.o: ../FL/Fl_Light_Button.H ../FL/Fl_Button.H +alignment_panel.o: ../FL/Fl_Spinner.H ../FL/Fl_Repeat_Button.H ../FL/Fl.H +alignment_panel.o: ../FL/Fl_Return_Button.H ../FL/Fl_Round_Button.H +code.o: ../src/flstring.h ../FL/Fl_Export.H ../config.h ../FL/Fl.H +code.o: ../FL/Enumerations.H ../FL/Fl_Export.H Fl_Type.h ../FL/Fl_Widget.H +code.o: ../FL/Fl_Menu.H ../FL/Fl_Menu_Item.H ../FL/Fl_Widget.H +code.o: ../FL/Fl_Image.H Fluid_Image.h ../FL/Fl_Shared_Image.H +code.o: ../FL/fl_draw.H ../FL/Fl_Tabs.H ../FL/Fl_Group.H ../FL/Fl_Pack.H +code.o: ../FL/Fl_Group.H ../FL/Fl_Wizard.H ../FL/Fl_Menu_.H +code.o: ../FL/Fl_Menu_Button.H ../FL/Fl_Menu_.H ../FL/Fl_Choice.H +code.o: ../FL/Fl_Input_Choice.H ../FL/Fl_Input.H ../FL/Fl_Input_.H +code.o: ../FL/Fl_Window.H ../FL/Fl_Menu_Bar.H alignment_panel.h +code.o: ../FL/Fl_Text_Buffer.H ../FL/Fl_Text_Display.H ../FL/fl_draw.H +code.o: ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H +code.o: ../FL/Fl_Text_Buffer.H ../FL/Fl_Double_Window.H ../FL/Fl_Window.H +code.o: ../FL/Fl_Preferences.H ../FL/Fl_Tooltip.H ../FL/Fl_Button.H +code.o: ../FL/Fl_Box.H ../FL/Fl_Light_Button.H ../FL/Fl_Check_Button.H +code.o: ../FL/Fl_Light_Button.H ../FL/Fl_Button.H ../FL/Fl_Spinner.H +code.o: ../FL/Fl_Repeat_Button.H ../FL/Fl.H ../FL/Fl_Return_Button.H +code.o: ../FL/Fl_Round_Button.H ../FL/filename.H +factory.o: ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/Fl_Group.H +factory.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Widget.H ../FL/Fl_Image.H +factory.o: ../FL/Fl_Pixmap.H ../src/flstring.h ../FL/Fl_Export.H ../config.h +factory.o: undo.h Fl_Widget_Type.h Fl_Type.h ../FL/Fl_Widget.H +factory.o: ../FL/Fl_Menu.H ../FL/Fl_Menu_Item.H Fluid_Image.h +factory.o: ../FL/Fl_Shared_Image.H ../FL/fl_draw.H ../FL/Fl_Tabs.H +factory.o: ../FL/Fl_Group.H ../FL/Fl_Pack.H ../FL/Fl_Wizard.H +factory.o: ../FL/Fl_Menu_.H ../FL/Fl_Menu_Button.H ../FL/Fl_Menu_.H +factory.o: ../FL/Fl_Choice.H ../FL/Fl_Input_Choice.H ../FL/Fl_Input.H +factory.o: ../FL/Fl_Input_.H ../FL/Fl_Window.H ../FL/Fl_Menu_Bar.H +factory.o: ../FL/Fl_Box.H ../FL/Fl_Button.H ../FL/Fl_Return_Button.H +factory.o: ../FL/Fl_Button.H ../FL/Fl_Repeat_Button.H ../FL/Fl.H +factory.o: ../FL/Fl_Light_Button.H ../FL/Fl_Check_Button.H +factory.o: ../FL/Fl_Light_Button.H ../FL/Fl_Round_Button.H ../FL/Fl_Browser.H +factory.o: ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H +factory.o: ../FL/Fl_Valuator.H ../FL/Fl_Check_Browser.H +factory.o: ../FL/Fl_File_Browser.H ../FL/Fl_Browser.H ../FL/Fl_File_Icon.H +factory.o: ../FL/filename.H ../FL/Fl_Counter.H ../FL/Fl_Spinner.H +factory.o: ../FL/Fl_File_Input.H ../FL/Fl_Text_Display.H ../FL/fl_draw.H +factory.o: ../FL/Fl_Text_Buffer.H ../FL/Fl_Text_Editor.H +factory.o: ../FL/Fl_Text_Display.H ../FL/Fl_Clock.H ../FL/Fl_Help_View.H +factory.o: ../FL/Fl_Shared_Image.H ../FL/Fl_Progress.H ../FL/Fl_Adjuster.H +factory.o: ../FL/Fl_Dial.H ../FL/Fl_Roller.H ../FL/Fl_Scrollbar.H +factory.o: ../FL/Fl_Output.H ../FL/Fl_Input.H ../FL/Fl_Value_Input.H +factory.o: ../FL/Fl_Value_Output.H ../FL/Fl_Value_Slider.H +factory.o: ../FL/Fl_Multi_Label.H +file.o: ../src/flstring.h ../FL/Fl_Export.H ../config.h alignment_panel.h +file.o: ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H +file.o: ../FL/Fl_Text_Buffer.H ../FL/Fl_Text_Display.H ../FL/fl_draw.H +file.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Scrollbar.H +file.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl_Text_Buffer.H +file.o: ../FL/Fl_Double_Window.H ../FL/Fl_Window.H ../FL/Fl_Preferences.H +file.o: ../FL/Fl_Tooltip.H ../FL/Fl_Widget.H ../FL/Fl_Button.H +file.o: ../FL/Fl_Tabs.H ../FL/Fl_Group.H ../FL/Fl_Box.H ../FL/Fl_Input.H +file.o: ../FL/Fl_Input_.H ../FL/Fl_Light_Button.H ../FL/Fl_Choice.H +file.o: ../FL/Fl_Menu_.H ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H +file.o: ../FL/Fl_Check_Button.H ../FL/Fl_Light_Button.H ../FL/Fl_Button.H +file.o: ../FL/Fl_Spinner.H ../FL/Fl_Repeat_Button.H ../FL/Fl.H +file.o: ../FL/Fl_Return_Button.H ../FL/Fl_Round_Button.H ../FL/fl_message.H +file.o: ../FL/fl_ask.H Fl_Widget_Type.h Fl_Type.h ../FL/Fl_Menu.H +file.o: Fluid_Image.h ../FL/Fl_Shared_Image.H ../FL/fl_draw.H ../FL/Fl_Pack.H +file.o: ../FL/Fl_Wizard.H ../FL/Fl_Menu_.H ../FL/Fl_Menu_Button.H +file.o: ../FL/Fl_Input_Choice.H ../FL/Fl_Window.H ../FL/Fl_Menu_Bar.H +fluid.o: ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H +fluid.o: ../FL/Fl_Double_Window.H ../FL/Fl_Window.H ../FL/Fl_Group.H +fluid.o: ../FL/Fl_Widget.H ../FL/Fl_Box.H ../FL/Fl_Button.H +fluid.o: ../FL/Fl_File_Icon.H ../FL/Fl.H ../FL/Fl_Help_Dialog.H +fluid.o: ../FL/Fl_Help_View.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H +fluid.o: ../FL/Fl_Valuator.H ../FL/fl_draw.H ../FL/Fl_Shared_Image.H +fluid.o: ../FL/Fl_Group.H ../FL/Fl_Input.H ../FL/Fl_Input_.H +fluid.o: ../FL/Fl_Hold_Browser.H ../FL/Fl_Browser.H ../FL/Fl_Browser_.H +fluid.o: ../FL/Fl_Menu_Bar.H ../FL/Fl_Menu_.H ../FL/Fl_Menu_Item.H +fluid.o: ../FL/Fl_Image.H ../FL/fl_ask.H ../FL/fl_draw.H +fluid.o: ../FL/Fl_File_Chooser.H ../FL/Fl_Choice.H ../FL/Fl_Menu_Button.H +fluid.o: ../FL/Fl_Preferences.H ../FL/Fl_Tile.H ../FL/Fl_File_Browser.H +fluid.o: ../FL/Fl_File_Icon.H ../FL/filename.H ../FL/Fl_Check_Button.H +fluid.o: ../FL/Fl_Light_Button.H ../FL/Fl_Button.H ../FL/Fl_File_Input.H +fluid.o: ../FL/Fl_Return_Button.H ../FL/fl_message.H ../FL/fl_ask.H +fluid.o: ../FL/filename.H ../src/flstring.h ../FL/Fl_Export.H ../config.h +fluid.o: alignment_panel.h ../FL/Fl_Text_Buffer.H ../FL/Fl_Text_Display.H +fluid.o: ../FL/Fl_Text_Buffer.H ../FL/Fl_Tooltip.H ../FL/Fl_Widget.H +fluid.o: ../FL/Fl_Tabs.H ../FL/Fl_Light_Button.H ../FL/Fl_Spinner.H +fluid.o: ../FL/Fl_Repeat_Button.H ../FL/Fl_Round_Button.H function_panel.h +fluid.o: CodeEditor.h ../FL/Fl_Text_Editor.H ../FL/Fl_Text_Display.H +fluid.o: ../FL/Fl_Window.H template_panel.h ../FL/Fl_Browser.H +fluid.o: print_panel.cxx print_panel.h ../FL/Fl_Progress.H ../FL/Fl_Pixmap.H +fluid.o: about_panel.h undo.h Fl_Type.h ../FL/Fl_Menu.H Fluid_Image.h +fluid.o: ../FL/Fl_Shared_Image.H ../FL/Fl_Pack.H ../FL/Fl_Wizard.H +fluid.o: ../FL/Fl_Menu_.H ../FL/Fl_Input_Choice.H +function_panel.o: function_panel.h ../FL/Fl.H ../FL/Enumerations.H +function_panel.o: ../FL/Fl_Export.H ../FL/Fl_Double_Window.H +function_panel.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +function_panel.o: ../FL/Fl_Group.H ../FL/Fl_Light_Button.H ../FL/Fl_Box.H +function_panel.o: ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/Fl_Return_Button.H +function_panel.o: ../FL/Fl_Button.H ../FL/Fl_Button.H CodeEditor.h +function_panel.o: ../FL/Fl_Text_Buffer.H ../FL/Fl_Text_Editor.H +function_panel.o: ../FL/Fl_Text_Display.H ../FL/fl_draw.H +function_panel.o: ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H +function_panel.o: ../FL/Fl_Text_Buffer.H ../FL/Fl_Menu_Button.H +function_panel.o: ../FL/Fl_Menu_.H ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H +function_panel.o: ../FL/Fl_Window.H ../FL/Fl_Tabs.H ../FL/Fl_Pixmap.H +function_panel.o: Fl_Type.h ../FL/Fl_Widget.H ../FL/Fl_Menu.H Fluid_Image.h +function_panel.o: ../FL/Fl_Shared_Image.H ../FL/fl_draw.H ../FL/Fl_Pack.H +function_panel.o: ../FL/Fl_Wizard.H ../FL/Fl_Menu_.H ../FL/Fl_Choice.H +function_panel.o: ../FL/Fl_Input_Choice.H ../FL/Fl_Menu_Bar.H undo.h +template_panel.o: template_panel.h ../FL/Fl.H ../FL/Enumerations.H +template_panel.o: ../FL/Fl_Export.H ../FL/Fl_Double_Window.H +template_panel.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +template_panel.o: ../FL/Fl_Browser.H ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H +template_panel.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl_Box.H +template_panel.o: ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/Fl_Group.H +template_panel.o: ../FL/Fl_Button.H ../FL/Fl_Return_Button.H +template_panel.o: ../FL/Fl_Button.H ../src/flstring.h ../FL/Fl_Export.H +template_panel.o: ../config.h ../FL/filename.H ../FL/fl_ask.H +template_panel.o: ../FL/Fl_Shared_Image.H ../FL/Fl_Image.H +template_panel.o: ../FL/Fl_Preferences.H +undo.o: ../FL/Fl.H ../FL/Enumerations.H ../FL/Fl_Export.H Fl_Type.h +undo.o: ../FL/Fl_Widget.H ../FL/Fl_Menu.H ../FL/Fl_Menu_Item.H +undo.o: ../FL/Fl_Widget.H ../FL/Fl_Image.H Fluid_Image.h +undo.o: ../FL/Fl_Shared_Image.H ../FL/fl_draw.H ../FL/Fl_Tabs.H +undo.o: ../FL/Fl_Group.H ../FL/Fl_Pack.H ../FL/Fl_Group.H ../FL/Fl_Wizard.H +undo.o: ../FL/Fl_Menu_.H ../FL/Fl_Menu_Button.H ../FL/Fl_Menu_.H +undo.o: ../FL/Fl_Choice.H ../FL/Fl_Input_Choice.H ../FL/Fl_Input.H +undo.o: ../FL/Fl_Input_.H ../FL/Fl_Window.H ../FL/Fl_Menu_Bar.H undo.h +undo.o: ../FL/Fl_Preferences.H ../src/flstring.h ../FL/Fl_Export.H +undo.o: ../config.h +widget_panel.o: widget_panel.h ../FL/Fl.H ../FL/Enumerations.H +widget_panel.o: ../FL/Fl_Export.H ../FL/Fl_Double_Window.H ../FL/Fl_Window.H +widget_panel.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Tabs.H +widget_panel.o: ../FL/Fl_Group.H ../FL/Fl_Input.H ../FL/Fl_Input_.H +widget_panel.o: ../FL/Fl_Choice.H ../FL/Fl_Menu_.H ../FL/Fl_Menu_Item.H +widget_panel.o: ../FL/Fl_Image.H ../FL/Fl_Button.H ../FL/Fl_Box.H +widget_panel.o: ../FL/Fl_Value_Input.H ../FL/Fl_Valuator.H ../FL/Fl_Input.H +widget_panel.o: ../FL/Fl_Light_Button.H Shortcut_Button.h CodeEditor.h +widget_panel.o: ../FL/Fl_Text_Buffer.H ../FL/Fl_Text_Editor.H +widget_panel.o: ../FL/Fl_Text_Display.H ../FL/fl_draw.H ../FL/Fl_Scrollbar.H +widget_panel.o: ../FL/Fl_Slider.H ../FL/Fl_Text_Buffer.H +widget_panel.o: ../FL/Fl_Return_Button.H ../FL/Fl_Button.H diff --git a/Utilities/FLTK/fluid/makefile.wat b/Utilities/FLTK/fluid/makefile.wat new file mode 100644 index 0000000000..8a1a5d9fc9 --- /dev/null +++ b/Utilities/FLTK/fluid/makefile.wat @@ -0,0 +1,76 @@ +# +# "$Id: makefile.wat 4359 2005-05-19 16:07:13Z mike $" +# +# FLUID makefile for the Fast Light Tool Kit (FLTK). +# +# Copyright 1998-2004 by Bill Spitzak and others. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. +# +# Please report all bugs and problems to "fltk-bugs@fltk.org". +# + +OBJECTS = & + Fl_Function_Type.obj & + Fl_Menu_Type.obj & + Fl_Group_Type.obj & + Fl_Widget_Type.obj & + Fl_Type.obj & + Fl_Window_Type.obj & + Fluid_Image.obj & + code.obj & + factory.obj & + file.obj & + align_widget.obj & + about_panel.obj & + widget_panel.obj & + alignment_panel.obj & + function_panel.obj + +# fluid.obj should not be in the list, because the watcom.mif file +# assumes an object file with the same name as the target executable + +################################################################ + +!include ../watcom.mif + +all: $(ODIR)/fluid$(EXEEXT) + +$(ODIR)\fluid$(EXEEXT): $(OBJECTS) $(LIBS) + +# +# Clean all directories +# +clean : .SYMBOLIC + @echo Cleaning up. +CLEANEXTS = exe map sym obj lk1 + @for %a in ($(CLEANEXTS)) do -rm -f $(ODIR)\*.%a + -rm -f *.err + +# +# Note: The rebuild target can only be used if you have the original .fl +# files. This is normally only used by the FLTK maintainers... +# + +rebuild: + ./fluid -c about_panel.fl + ./fluid -c alignment_panel.fl + ./fluid -c function_panel.fl + ./fluid -c widget_panel.fl + +# +# End of "$Id: makefile.wat 4359 2005-05-19 16:07:13Z mike $". +# diff --git a/Utilities/FLTK/fluid/pixmaps/.cvsignore b/Utilities/FLTK/fluid/pixmaps/.cvsignore new file mode 100644 index 0000000000..3df5b20556 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/.cvsignore @@ -0,0 +1 @@ +*.bck diff --git a/Utilities/FLTK/fluid/pixmaps/flAdjuster.xpm b/Utilities/FLTK/fluid/pixmaps/flAdjuster.xpm new file mode 100644 index 0000000000..12ae646b47 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flAdjuster.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flAdjuster_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"b c #2020ff", +"c c none", +"d c #c0c0c0", +"e c #8080ff", +"f c #e0e0e0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"fffffffffffffffc", +"fdddafdddafdddac", +"fdddafdddafdddac", +"fdddafdddafdddac", +"fdddafdddafdddac", +"fdddafdddafdddac", +"fdddafdddafdddac", +"aaaaaaaaaaaaaaac", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flBox.xpm b/Utilities/FLTK/fluid/pixmaps/flBox.xpm new file mode 100644 index 0000000000..881170c09d --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flBox.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flBox_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"b c #2020ff", +"c c none", +"d c #c0c0c0", +"e c #909090", +"f c #000000", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"dddddddddddddddc", +"dddddddddddddddc", +"deeeeeeeeeeeeedc", +"deeeeeeeeeeeeedc", +"deeeeeeeeeeeeedc", +"deeeeeeeeeeeeedc", +"deeeeeeeeeeeeedc", +"deeeeeeeeeeeeedc", +"deeeeeeeeeeeeedc", +"deeeeeeeeeeeeedc", +"dddddddddddddddc", +"dddddddddddddddc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flBrowser.xpm b/Utilities/FLTK/fluid/pixmaps/flBrowser.xpm new file mode 100644 index 0000000000..50b1d0a42c --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flBrowser.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flBrowser_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"b c #808080", +"c c none", +"d c #c0c0c0", +"e c #ffffff", +"f c #000000", +/* pixels */ +"cccccccccccccccc", +"dddddddddddddddc", +"dfffffffffffffdc", +"dfeeeeeeeeebbfdc", +"dfeeeeeeeeebdfdc", +"dfeeeeeeeeebdfdc", +"dfeeeeeeeeebffdc", +"dfeeeeeeeeebdfdc", +"dfeeeeeeeeebdfdc", +"dfeeeeeeeeebdfdc", +"dfeeeeeeeeebdfdc", +"dfbbbbbbbbbbbfdc", +"dfbdddfddddbdfdc", +"dfffffffffffffdc", +"dddddddddddddddc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flButton.xpm b/Utilities/FLTK/fluid/pixmaps/flButton.xpm new file mode 100644 index 0000000000..509293e6d6 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flButton.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flButton_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"b c #2020ff", +"c c none", +"d c #a0a0a0", +"e c #8080ff", +"f c #d0d0d0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"ffffffffffffffac", +"fdddddddddddddac", +"fdddddddddddddac", +"fdddddddddddddac", +"fdddddddddddddac", +"fdddddddddddddac", +"fdddddddddddddac", +"aaaaaaaaaaaaaaac", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flCheckBrowser.xpm b/Utilities/FLTK/fluid/pixmaps/flCheckBrowser.xpm new file mode 100644 index 0000000000..77ffc56b49 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flCheckBrowser.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flCheckBrowser_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"b c #808080", +"c c none", +"d c #c0c0c0", +"e c #ffffff", +"f c #000000", +/* pixels */ +"cccccccccccccccc", +"dddddddddddddddc", +"dfffffffffffffdc", +"dfeeeeeeeeebbfdc", +"dfefffeeeeebdfdc", +"dfefefeeeeebdfdc", +"dfefffeeeeebffdc", +"dfeeeeeeeeebdfdc", +"dfefffeeeeebdfdc", +"dfefefeeeeebdfdc", +"dfefffeeeeebdfdc", +"dfbbbbbbbbbbbfdc", +"dfbdddfddddbdfdc", +"dfffffffffffffdc", +"dddddddddddddddc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flCheckButton.xpm b/Utilities/FLTK/fluid/pixmaps/flCheckButton.xpm new file mode 100644 index 0000000000..24f51cb392 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flCheckButton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static const char *flCheckButton_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 7 1", +/* colors */ +"a c #606060", +"b c #2020ff", +"c c none", +"d c #ffffff", +"e c #8080ff", +"f c #d0d0d0", +"' c #000000", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccaaaaaaaaaaccc", +"cccaddddddddfccc", +"cccadddddd''fccc", +"cccaddddd''dfccc", +"cccaddddd''dfccc", +"ccca''dd''ddfccc", +"cccad''''dddfccc", +"cccadd''ddddfccc", +"cccaddddddddfccc", +"cccaaaaaaaaaaccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flChoice.xpm b/Utilities/FLTK/fluid/pixmaps/flChoice.xpm new file mode 100644 index 0000000000..85f54963cb --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flChoice.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flChoice_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +". c #000000", +"c c none", +"d c #b0b0b0", +"e c #ffffff", +"f c #d0d0d0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"ffffffffffffffff", +"feeeeeafddddddda", +"feeeeeafddddddda", +"feeeeeaf.......a", +"feeeeeafd.....da", +"feeeeeafdd...dda", +"feeeeeafddd.ddda", +"feeeeeafddddddda", +"feeeeeafddddddda", +"aaaaaaaaaaaaaaaa", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flClass.xpm b/Utilities/FLTK/fluid/pixmaps/flClass.xpm new file mode 100644 index 0000000000..cd551bc72e --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flClass.xpm @@ -0,0 +1,27 @@ +/* XPM */ +static const char *flClass_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 4 1", +/* colors */ +". c none", +"a c #000000", +"b c #c0e0c0", +"c c #000000", +/* pixels */ +"................", +"................", +"...aaaaaaaaaaaaa", +"..abbbbbbbbbbbc.", +".abbbbbbbbbbbc..", +".abbbbbbbbbbbc..", +"abbbbbbbbbbbc...", +"abbbbbbbbbbbc...", +"abbbbbbbbbbbc...", +"abbbbbbbbbbbc...", +".abbbbbbbbbbbc..", +".abbbbbbbbbbbc..", +"..cbbbbbbbbbbbc.", +"...ccccccccccccc", +"................", +"................", +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flClock.xpm b/Utilities/FLTK/fluid/pixmaps/flClock.xpm new file mode 100644 index 0000000000..f69f0bf79f --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flClock.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static const char *flClock_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 5 1", +/* colors */ +". c none", +"a c #000000", +"b c #c0c0c0", +"c c #000000", +"' c #202080", +/* pixels */ +"................", +"................", +"....aaaaaaa.....", +"..aabbbbbbbcc...", +".abbbbbbbbb'bc..", +".abb'bbbbb'bbc..", +"abbbb'bbb'bbbbc.", +"abbbbb'b'bbbbbc.", +"abbbbbb'bbbbbbc.", +"abbbbbbbbbbbbbc.", +"abbbbbbbbbbbbbc.", +".abbbbbbbbbbbc..", +".abbbbbbbbbbbc..", +"..ccbbbbbbbcc...", +"....ccccccc.....", +"................", +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flCode.xpm b/Utilities/FLTK/fluid/pixmaps/flCode.xpm new file mode 100644 index 0000000000..7a10b26167 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flCode.xpm @@ -0,0 +1,27 @@ +/* XPM */ +static const char *flCode_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 4 1", +/* colors */ +". c none", +"a c #000000", +"b c #c0e0c0", +"c c #000000", +/* pixels */ +"................", +"................", +"aaaaaaaaaaaaaaaa", +"abbbbbbbbbbbbbbc", +"abbbbbbbbbbbbbbc", +"abbbbbbbbbbbbbbc", +"abbbbbbbbbbbbbbc", +"abbbbbbbbbbbbbbc", +"abbbbbbbbbbbbbbc", +"abbbbbbbbbbbbbbc", +"abbbbbbbbbbbbbbc", +"abbbbbbbbbbbbbbc", +"abbbbbbbbbbbbbbc", +"accccccccccccccc", +"................", +"................", +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flCodeBlock.xpm b/Utilities/FLTK/fluid/pixmaps/flCodeBlock.xpm new file mode 100644 index 0000000000..dd18f425a2 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flCodeBlock.xpm @@ -0,0 +1,27 @@ +/* XPM */ +static const char *flCodeBlock_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 4 1", +/* colors */ +". c none", +"a c #000000", +"b c #c0e0c0", +"c c #000000", +/* pixels */ +".......aa.......", +"......abbc......", +".....abbbbc.....", +"....abbbbbbc....", +"...abbbbbbbbc...", +"..abbbbbbbbbbc..", +".abbbbbbbbbbbbc.", +"abbbbbbbbbbbbbbc", +"abbbbbbbbbbbbbbc", +".abbbbbbbbbbbbc.", +"..abbbbbbbbbbc..", +"...abbbbbbbbc...", +"....abbbbbbc....", +".....abbbbc.....", +"......abbc......", +".......ac.......", +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flComment.xpm b/Utilities/FLTK/fluid/pixmaps/flComment.xpm new file mode 100644 index 0000000000..191b139104 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flComment.xpm @@ -0,0 +1,27 @@ +/* XPM */ +static const char *flComment_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 4 1", +/* colors */ +". c none", +"a c #000000", +"b c #c0e0c0", +"c c #000000", +/* pixels */ +"................", +"................", +".aaaaaaaaaaaaaa.", +".abbbbbbbbbbbbc.", +".abbbbbccbbccbc.", +".abbbbccbbccbbc.", +".abbbbccbbccbbc.", +".abbbccbbccbbbc.", +".abbbccbbccbbbc.", +".abbccbbccbbbbc.", +".abbccbbccbbbbc.", +".abccbbccbbbbbc.", +".abbbbbbbbbbbbc.", +".accccccccccccc.", +"................", +"................", +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flCounter.xpm b/Utilities/FLTK/fluid/pixmaps/flCounter.xpm new file mode 100644 index 0000000000..995b7efb10 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flCounter.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flCounter_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"' c #000000", +"c c none", +"d c #c0c0c0", +"e c #ffffff", +"f c #e0e0e0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"fffffffffffffffc", +"fdddaeeeeefdddac", +"fd'daee'eefd'dac", +"f''dae''eefd''ac", +"f''daee'eefd''ac", +"fd'dae'''efd'dac", +"fdddaeeeeefdddac", +"aaaaaaaaaaaaaaac", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flDeclaration.xpm b/Utilities/FLTK/fluid/pixmaps/flDeclaration.xpm new file mode 100644 index 0000000000..dd6a4de473 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flDeclaration.xpm @@ -0,0 +1,27 @@ +/* XPM */ +static const char *flDeclaration_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 4 1", +/* colors */ +". c none", +"a c #000000", +"b c #c0e0c0", +"c c #000000", +/* pixels */ +"................", +"................", +"...aaaaaaaaaaaaa", +"...abbbbbbbbbbbc", +"...abbbbbbbbbbbc", +"..abbbbbbbbbbbc.", +"..abbbbbbbbbbbc.", +"..abbbbbbbbbbbc.", +".abbbbbbbbbbbc..", +".abbbbbbbbbbbc..", +".abbbbbbbbbbbc..", +"abbbbbbbbbbbc...", +"abbbbbbbbbbbc...", +"acccccccccccc...", +"................", +"................", +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flDeclarationBlock.xpm b/Utilities/FLTK/fluid/pixmaps/flDeclarationBlock.xpm new file mode 100644 index 0000000000..ec4df041b7 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flDeclarationBlock.xpm @@ -0,0 +1,27 @@ +/* XPM */ +static const char *flDeclarationBlock_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 4 1", +/* colors */ +". c none", +"a c #000000", +"b c #c0e0c0", +"c c #000000", +/* pixels */ +".......aa.......", +"......abbc......", +".....abbbbc.....", +"....abbbbbbc....", +"...abbbbbbbbc...", +"..abbbcbbcbbbc..", +".abbbccccccbbbc.", +"abbbbbcbbcbbbbbc", +"abbbbbcbbcbbbbbc", +".abbbccccccbbbc.", +"..abbbcbbcbbbc..", +"...abbbbbbbbc...", +"....abbbbbbc....", +".....abbbbc.....", +"......abbc......", +".......ac.......", +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flDial.xpm b/Utilities/FLTK/fluid/pixmaps/flDial.xpm new file mode 100644 index 0000000000..29376ac42e --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flDial.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static const char *flDial_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 5 1", +/* colors */ +". c none", +"a c #000000", +"b c #c0c0c0", +"c c #000000", +"' c #202080", +/* pixels */ +"................", +"................", +"....aaaaaaa.....", +"..aabbbbbbbcc...", +".abbbbbbbbbbbc..", +".ab''bbbbbbbbc..", +"ab'bb'bbbbbbbbc.", +"ab'bb'bbbbbbbbc.", +"abb''bbbbbbbbbc.", +"abbbbbbbbbbbbbc.", +"abbbbbbbbbbbbbc.", +".abbbbbbbbbbbc..", +".abbbbbbbbbbbc..", +"..ccbbbbbbbcc...", +"....ccccccc.....", +"................", +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flFileBrowser.xpm b/Utilities/FLTK/fluid/pixmaps/flFileBrowser.xpm new file mode 100644 index 0000000000..98b02e9dd5 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flFileBrowser.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flFileBrowser_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #ffff00", +"b c #808080", +"c c none", +"d c #c0c0c0", +"e c #ffffff", +"f c #000000", +/* pixels */ +"cccccccccccccccc", +"dddddddddddddddc", +"dfffffffffffffdc", +"dfeeeeeeeeebbfdc", +"dfeefffeeeebdfdc", +"dfefaaafffebdfdc", +"dfefaaaaafebffdc", +"dfefaaaaafebdfdc", +"dfefaaaaafebdfdc", +"dfefffffffebdfdc", +"dfeeeeeeeeebdfdc", +"dfbbbbbbbbbbbfdc", +"dfbdddfddddbdfdc", +"dfffffffffffffdc", +"dddddddddddddddc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flFileInput.xpm b/Utilities/FLTK/fluid/pixmaps/flFileInput.xpm new file mode 100644 index 0000000000..014c2248eb --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flFileInput.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flFileInput_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"f c #606060", +". c #000000", +"c c none", +"d c #ffffff", +"e c #8080ff", +"a c #d0d0d0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"ffffffffffffffff", +"faaaaaaaafaaaaaa", +"ffffffffffffffff", +"fdddddddddddddda", +"fdd...dd..ddddda", +"fd.ddd.d..ddddda", +"fd.ddd.d..ddddda", +"fd.....d..ddddda", +"fd.ddd.d..ddddda", +"fd.ddd.d..ddddda", +"fdddddddddddddda", +"aaaaaaaaaaaaaaaa", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flFunction.xpm b/Utilities/FLTK/fluid/pixmaps/flFunction.xpm new file mode 100644 index 0000000000..54f6cef9a4 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flFunction.xpm @@ -0,0 +1,27 @@ +/* XPM */ +static const char *flFunction_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 4 1", +/* colors */ +". c none", +"a c #000000", +"b c #c0e0c0", +"c c #000000", +/* pixels */ +"................", +"................", +"....aaaaaaaa....", +"..aabbbbbbbbcc..", +".abbbbbbbbbbbbc.", +".abbbbbbbbbbbbc.", +"abbbbbbbbbbbbbbc", +"abbbbbbbbbbbbbbc", +"abbbbbbbbbbbbbbc", +"abbbbbbbbbbbbbbc", +".abbbbbbbbbbbbc.", +".abbbbbbbbbbbbc.", +"..ccbbbbbbbbcc..", +"....cccccccc....", +"................", +"................", +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flGroup.xpm b/Utilities/FLTK/fluid/pixmaps/flGroup.xpm new file mode 100644 index 0000000000..daa21cfccf --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flGroup.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flGroup_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"b c #2020ff", +"c c none", +"d c #c0c0c0", +"e c #8080ff", +"f c #000000", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"dddddddddddddddc", +"dfffffffffffffdc", +"dfdddddddddddfdc", +"dfdddddddddddfdc", +"dfdddddddddddfdc", +"dfdddddddddddfdc", +"dfdddddddddddfdc", +"dfdddddddddddfdc", +"dfdddddddddddfdc", +"dfdddddddddddfdc", +"dfffffffffffffdc", +"dddddddddddddddc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flHelp.xpm b/Utilities/FLTK/fluid/pixmaps/flHelp.xpm new file mode 100644 index 0000000000..6a9c0a0fa7 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flHelp.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flHelp_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"b c #808080", +"c c none", +"d c #c0c0c0", +"e c #ffffff", +"f c #000000", +/* pixels */ +"cccccccccccccccc", +"dddddddddddddddc", +"dfffffffffffffdc", +"dfeeeeeeeeebbfdc", +"dfeeeffeeeebdfdc", +"dfeeffeeeeebdfdc", +"dfeffeeeeeebffdc", +"dfeeffeeeeebdfdc", +"dfeeeffeeeebdfdc", +"dfeeeeeeeeebdfdc", +"dfeeeeeeeeebdfdc", +"dfbbbbbbbbbbbfdc", +"dfbdddfddddbdfdc", +"dfffffffffffffdc", +"dddddddddddddddc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flInput.xpm b/Utilities/FLTK/fluid/pixmaps/flInput.xpm new file mode 100644 index 0000000000..0d4f04c830 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flInput.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flInput_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"f c #606060", +". c #000000", +"c c none", +"d c #ffffff", +"e c #8080ff", +"a c #d0d0d0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"ffffffffffffffff", +"fdddddddddddddda", +"fdd...dd..ddddda", +"fd.ddd.d..ddddda", +"fd.ddd.d..ddddda", +"fd.....d..ddddda", +"fd.ddd.d..ddddda", +"fd.ddd.d..ddddda", +"fdddddddddddddda", +"aaaaaaaaaaaaaaaa", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flLightButton.xpm b/Utilities/FLTK/fluid/pixmaps/flLightButton.xpm new file mode 100644 index 0000000000..bd14fc7a01 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flLightButton.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flLightButton_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"b c #ffff00", +"c c none", +"d c #a0a0a0", +"e c #8080ff", +"f c #d0d0d0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"ffffffffffffffac", +"fdddddddddddddac", +"fdaaaaddddddddac", +"fdabbfddddddddac", +"fdabbfddddddddac", +"fdafffddddddddac", +"fdddddddddddddac", +"aaaaaaaaaaaaaaac", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flMenuButton.xpm b/Utilities/FLTK/fluid/pixmaps/flMenuButton.xpm new file mode 100644 index 0000000000..1cf862490d --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flMenuButton.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flMenuButton_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +". c #000000", +"c c none", +"d c #b0b0b0", +"e c #ffffff", +"f c #d0d0d0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"ffffffffffffffff", +"fdddddddddddddda", +"fdddddddddddddda", +"fddddddd.......a", +"fdddddddd.ddd.da", +"fddddddddd.d.dda", +"fdddddddddd.ddda", +"fdddddddddddddda", +"fdddddddddddddda", +"aaaaaaaaaaaaaaaa", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flMenubar.xpm b/Utilities/FLTK/fluid/pixmaps/flMenubar.xpm new file mode 100644 index 0000000000..d72436df52 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flMenubar.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flMenubar_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +". c #2020cf", +"c c none", +"d c #b0b0b0", +"e c #ffffff", +"f c #e0e0e0", +/* pixels */ +"cccccccccccccccc", +"ffffffffffffffff", +"dddddddddddddddd", +"dddddddddddddddd", +"dddddddddddddddd", +"dddffffffffffffd", +"aaafddddddddddaa", +"cccfddddddddddac", +"cccfddddddddddac", +"cccfddddddddddac", +"cccfddddddddddac", +"cccfddddddddddac", +"cccfddddddddddac", +"cccfddddddddddac", +"cccfaaaaaaaaaaac", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flMenuitem.xpm b/Utilities/FLTK/fluid/pixmaps/flMenuitem.xpm new file mode 100644 index 0000000000..73228fc04b --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flMenuitem.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flMenuitem_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +". c #000000", +"c c none", +"d c #b0b0b0", +"e c #d0d0d0", +"f c #c0c0c0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccffffccccccccc", +"c.fffffffccccf.c", +"c.ffffffffffff.c", +"c.eeeeeeeeeeee.c", +"c.ee.ee.eeeeee.c", +"c.e.e.e.eee..e.c", +"c.e...e..e.eee.c", +"c.e.e.e..e.eee.c", +"c.e.e.e..ee..e.c", +"c.eeeeeeeeeeee.c", +"c.ffffffffffff.c", +"c.fccccfffffff.c", +"cccccccccffffccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flOutput.xpm b/Utilities/FLTK/fluid/pixmaps/flOutput.xpm new file mode 100644 index 0000000000..0588f7a227 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flOutput.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flOutput_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"f c #606060", +". c #000000", +"c c none", +"d c #d0d0d0", +"e c #8080ff", +"a c #d0d0d0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"ffffffffffffffff", +"fdddddddddddddda", +"fdd...ddddddddda", +"fd.ddd.dddddddda", +"fd.ddd.dddddddda", +"fd.....dddddddda", +"fd.ddd.dddddddda", +"fd.ddd.dddddddda", +"fdddddddddddddda", +"aaaaaaaaaaaaaaaa", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flPack.xpm b/Utilities/FLTK/fluid/pixmaps/flPack.xpm new file mode 100644 index 0000000000..8161c98f74 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flPack.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flPack_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"b c #f0f0f0", +"c c none", +"d c #c0c0c0", +"e c #8080ff", +"f c #000000", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"dddddddddddddddc", +"dfffffffffffffdc", +"dfddfddfddfddfdc", +"dfddfddfddfddfdc", +"dfddfddfddfddfdc", +"dfddfddfddfddfdc", +"dfddfddfddfddfdc", +"dfddfddfddfddfdc", +"dfddfddfddfddfdc", +"dfddfddfddfddfdc", +"dfffffffffffffdc", +"dddddddddddddddc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flProgress.xpm b/Utilities/FLTK/fluid/pixmaps/flProgress.xpm new file mode 100644 index 0000000000..02890f2607 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flProgress.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flProgress_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"f c #606060", +". c #f0f000", +"c c none", +"d c #ffffff", +"e c #8080ff", +"a c #d0d0d0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"ffffffffffffffff", +"f.........ddddda", +"f.........ddddda", +"f.........ddddda", +"f.........ddddda", +"f.........ddddda", +"f.........ddddda", +"aaaaaaaaaaaaaaaa", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flRepeatButton.xpm b/Utilities/FLTK/fluid/pixmaps/flRepeatButton.xpm new file mode 100644 index 0000000000..1ee05f398b --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flRepeatButton.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flRepeatButton_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"' c #000000", +"c c none", +"d c #a0a0a0", +"e c #8080ff", +"f c #d0d0d0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"ffffffffffffffac", +"fdddddddddddddac", +"fdddddddddddddac", +"fdddddddddddddac", +"fdddd''d''d''dac", +"fdddd''d''d''dac", +"fdddddddddddddac", +"aaaaaaaaaaaaaaac", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flReturnButton.xpm b/Utilities/FLTK/fluid/pixmaps/flReturnButton.xpm new file mode 100644 index 0000000000..d875e01a0f --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flReturnButton.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flReturnButton_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"' c #000000", +"c c none", +"d c #a0a0a0", +"e c #8080ff", +"f c #d0d0d0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"ffffffffffffffac", +"fdddddddddddddac", +"fddddddd'dd''dac", +"fdddddd''dd''dac", +"fddddd'''''''dac", +"fdddddd''dddddac", +"fddddddd'dddddac", +"aaaaaaaaaaaaaaac", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flRoller.xpm b/Utilities/FLTK/fluid/pixmaps/flRoller.xpm new file mode 100644 index 0000000000..1000bb5bd0 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flRoller.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flRoller_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #e0e0e0", +"' c #000000", +"c c none", +"d c #c0c0c0", +"e c #ffffff", +"f c #606060", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"aaaaaaaaaaaaaaac", +"a'f'ee'ddd'dd'f'", +"a'f'ee'ddd'dd'f'", +"a'f'ee'ddd'dd'f'", +"a'f'ee'ddd'dd'f'", +"a'f'ee'ddd'dd'f'", +"a'f'ee'ddd'dd'f'", +"''''''''''''''''", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flRoundButton.xpm b/Utilities/FLTK/fluid/pixmaps/flRoundButton.xpm new file mode 100644 index 0000000000..c9658e6067 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flRoundButton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static const char *flRoundButton_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 7 1", +/* colors */ +"a c #606060", +"b c #2020ff", +". c none", +"d c #ffffff", +"e c #8080ff", +"f c #d0d0d0", +"# c #000000", +/* pixels */ +"................", +"................", +"......aaa.......", +"....aadddaa.....", +"...adddddddf....", +"...add###ddf....", +"..add#####ddf...", +"..add#####ddf...", +"..add#####ddf...", +"...add###ddf....", +"...adddddddf....", +"....ffdddff.....", +"......fff.......", +"................", +"................", +"................" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flScroll.xpm b/Utilities/FLTK/fluid/pixmaps/flScroll.xpm new file mode 100644 index 0000000000..9dcdd2411d --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flScroll.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flScroll_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"b c #f0f0f0", +"c c none", +"d c #c0c0c0", +"e c #8080ff", +"f c #000000", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"dddddddddddddddc", +"dfffffffffffffdc", +"dfddddddddbbbfdc", +"dfddddddddbddfdc", +"dfddddddddbddfdc", +"dfddddddddbfffdc", +"dfddddddddbddfdc", +"dfbbbbbbbbbbbfdc", +"dfbdddfdddbddfdc", +"dfbdddfdddbddfdc", +"dfffffffffffffdc", +"dddddddddddddddc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flScrollBar.xpm b/Utilities/FLTK/fluid/pixmaps/flScrollBar.xpm new file mode 100644 index 0000000000..c18a08ca15 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flScrollBar.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flScrollBar_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"b c #2020ff", +"c c none", +"d c #c0c0c0", +"e c #8080ff", +"f c #e0e0e0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"aaaaaaaaaaaaaaaa", +"adddfffffddddddf", +"ad'dfdddadddd'df", +"a''dfdddadddd''f", +"a''dfdddadddd''f", +"ad'dfdddadddd'df", +"adddfaaaaddddddf", +"afffffffffffffff", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flSlider.xpm b/Utilities/FLTK/fluid/pixmaps/flSlider.xpm new file mode 100644 index 0000000000..524268de5e --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flSlider.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flSlider_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"b c #2020ff", +"c c none", +"d c #c0c0c0", +"e c #8080ff", +"f c #e0e0e0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"aaaaaaaaaaaaaaaa", +"afffffdddddddddf", +"afdddadddddddddf", +"afdddadddddddddf", +"afdddadddddddddf", +"afdddadddddddddf", +"afaaaadddddddddf", +"afffffffffffffff", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flSpinner.xpm b/Utilities/FLTK/fluid/pixmaps/flSpinner.xpm new file mode 100644 index 0000000000..840d87b89e --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flSpinner.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static const char *flSpinner_xpm[]={ +"16 16 6 1", +". c None", +"c c #000000", +"d c #606060", +"b c #c0c0c0", +"# c #e0e0e0", +"a c #ffffff", +"................", +"................", +"................", +"................", +"###############.", +"#aaaaaaaaa#bcbd.", +"#aaaaaacaa#cccd.", +"#aaaaaccaaddddd.", +"#aaaaaacaa####d.", +"#aaaaaccca#cccd.", +"#aaaaaaaaa#bcbd.", +"ddddddddddddddd.", +"................", +"................", +"................", +"................"}; diff --git a/Utilities/FLTK/fluid/pixmaps/flSubmenu.xpm b/Utilities/FLTK/fluid/pixmaps/flSubmenu.xpm new file mode 100644 index 0000000000..18439f8b28 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flSubmenu.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flSubmenu_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +". c #000000", +"c c none", +"d c #b0b0b0", +"e c #d0d0d0", +"f c #c0c0c0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccffffccccccccc", +"c.fffffffccccf.c", +"c.ffffffffffff.c", +"c.eeeeeeeeeeee.c", +"c.ee.eeeee.eee.c", +"c.e.e.eeee..ee.c", +"c.e...eeee...e.c", +"c.e.e.eeee..ee.c", +"c.e.e.eeee.eee.c", +"c.eeeeeeeee.....", +"c.fffffffff.ffff", +"c.fccccffff.ffff", +"cccccccccff.ffff", +"ccccccccccc.ffff" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flTabs.xpm b/Utilities/FLTK/fluid/pixmaps/flTabs.xpm new file mode 100644 index 0000000000..8aec7937b9 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flTabs.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flTabs_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #a0a0a0", +"b c #2020ff", +"c c none", +"d c #c0c0c0", +"e c #8080ff", +"f c #000000", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"dddddddddddddddc", +"ddffffdffffddddc", +"dfddddfaaaafdddc", +"dfddddfaaaafdddc", +"dfddddffffffffdc", +"dfdddddddddddfdc", +"dfdddddddddddfdc", +"dfdddddddddddfdc", +"dfdddddddddddfdc", +"dfdddddddddddfdc", +"dfffffffffffffdc", +"dddddddddddddddc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flTextDisplay.xpm b/Utilities/FLTK/fluid/pixmaps/flTextDisplay.xpm new file mode 100644 index 0000000000..990c4a0a08 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flTextDisplay.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flTextDisplay_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"f c #606060", +". c #000000", +"c c none", +"d c #d0d0d0", +"e c #8080ff", +"a c #d0d0d0", +/* pixels */ +"cccccccccccccccc", +"ffffffffffffffff", +"fdddddddddddddda", +"fdd...ddddddddda", +"fd.ddd.dddddddda", +"fd.ddd.dddddddda", +"fd.....dddddddda", +"fd.ddd.dddddddda", +"fd.ddd.dddddddda", +"fdddddddddddddda", +"fdddddddddddddda", +"fdddddddddddddda", +"fdddddddddddddda", +"fdddddddddddddda", +"aaaaaaaaaaaaaaaa", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flTextEdit.xpm b/Utilities/FLTK/fluid/pixmaps/flTextEdit.xpm new file mode 100644 index 0000000000..8a892d897a --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flTextEdit.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flTextEdit_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"f c #606060", +". c #000000", +"c c none", +"d c #ffffff", +"e c #8080ff", +"a c #d0d0d0", +/* pixels */ +"cccccccccccccccc", +"ffffffffffffffff", +"fdddddddddddddda", +"fdd...dd..ddddda", +"fd.ddd.d..ddddda", +"fd.ddd.d..ddddda", +"fd.....d..ddddda", +"fd.ddd.d..ddddda", +"fd.ddd.d..ddddda", +"fdddddddddddddda", +"fdddddddddddddda", +"fdddddddddddddda", +"fdddddddddddddda", +"fdddddddddddddda", +"aaaaaaaaaaaaaaaa", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flTile.xpm b/Utilities/FLTK/fluid/pixmaps/flTile.xpm new file mode 100644 index 0000000000..c64f78fefb --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flTile.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flTile_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"b c #f0f0f0", +"c c none", +"d c #c0c0c0", +"e c #8080ff", +"f c #000000", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"dddddddddddddddd", +"dfffffffffffffbd", +"dfdddddbfdddddbd", +"dfdddddbfdddddbd", +"dfdddddbfdddddbdc", +"dfbbbbbbfbbbbbbd", +"dfffffffffffffbd", +"dfdddddbfdddddbd", +"dfdddddbfdddddbd", +"dfdddddbfdddddbd", +"dfbbbbbbfbbbbbbd", +"dddddddddddddddd", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flValueInput.xpm b/Utilities/FLTK/fluid/pixmaps/flValueInput.xpm new file mode 100644 index 0000000000..dc56bd8658 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flValueInput.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flValueInput_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"f c #606060", +". c #000000", +"c c none", +"d c #ffffff", +"e c #8080ff", +"a c #d0d0d0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"ffffffffffffffff", +"fdddddddddddddda", +"fdd...dd..ddddda", +"fd.dd..d..ddddda", +"fd.d.d.d..ddddda", +"fd..dd.d..ddddda", +"fd.ddd.d..ddddda", +"fdd...dd..ddddda", +"fdddddddddddddda", +"aaaaaaaaaaaaaaaa", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flValueOutput.xpm b/Utilities/FLTK/fluid/pixmaps/flValueOutput.xpm new file mode 100644 index 0000000000..c6d1de1606 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flValueOutput.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flValueOutput_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"f c #606060", +". c #000000", +"c c none", +"d c #d0d0d0", +"e c #8080ff", +"a c #d0d0d0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"ffffffffffffffff", +"fdddddddddddddda", +"fdd...ddddddddda", +"fd.dd..dddddddda", +"fd.d.d.dddddddda", +"fd..dd.dddddddda", +"fd.ddd.dddddddda", +"fdd...ddddddddda", +"fdddddddddddddda", +"aaaaaaaaaaaaaaaa", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flValueSlider.xpm b/Utilities/FLTK/fluid/pixmaps/flValueSlider.xpm new file mode 100644 index 0000000000..819a4f5e43 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flValueSlider.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flValueSlider_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"b c #2020ff", +"c c none", +"d c #c0c0c0", +"' c #000000", +"f c #e0e0e0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"aaaaaaaaaaaaaaaa", +"adddddfffffddddf", +"add'ddfdddaddddf", +"ad''ddfdddaddddf", +"add'ddfdddaddddf", +"ad'''dfdddaddddf", +"adddddfaaaaddddf", +"afffffffffffffff", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flWidgetClass.xpm b/Utilities/FLTK/fluid/pixmaps/flWidgetClass.xpm new file mode 100644 index 0000000000..79c3377687 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flWidgetClass.xpm @@ -0,0 +1,31 @@ +/* XPM */ +static const char *flWidgetClass_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 8 1", +/* colors */ +"a c #606060", +"b c #2020ff", +"c c none", +"d c #a0a0a0", +"e c #8080ff", +"f c #d0d0d0", +"g c #c0e0c0", +"h c #000000", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"ffffffffffffffff", +"feebbbbbbbeebeea", +"feebbbbbbbeebeea", +"fdddhhhhhhhhhhda", +"fddhgggggggghdda", +"fdhgggggggghddda", +"fdhgggggggghddda", +"fdhgggggggghddda", +"fdhgggggggghddda", +"fddhgggggggghdda", +"fdddhhhhhhhhhhda", +"faaaaaaaaaaaaaaa", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flWindow.xpm b/Utilities/FLTK/fluid/pixmaps/flWindow.xpm new file mode 100644 index 0000000000..9581a26463 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flWindow.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flWindow_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"b c #2020ff", +"c c none", +"d c #a0a0a0", +"e c #8080ff", +"f c #d0d0d0", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"ffffffffffffffff", +"feebbbbbbbeebeea", +"feebbbbbbbeebeea", +"fdddddddddddddda", +"fdddddddddddddda", +"fdddddddddddddda", +"fdddddddddddddda", +"fdddddddddddddda", +"fdddddddddddddda", +"fdddddddddddddda", +"fdddddddddddddda", +"faaaaaaaaaaaaaaa", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/flWizard.xpm b/Utilities/FLTK/fluid/pixmaps/flWizard.xpm new file mode 100644 index 0000000000..2347b93407 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/flWizard.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *flWizard_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"a c #606060", +"b c #f0f0f0", +"c c none", +"d c #c0c0c0", +"e c #8080ff", +"f c #000000", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"dddddddddddddddc", +"dfffffffffffffdc", +"dfdddddddddddfdc", +"dfdddddddddddfdc", +"dfdddddddddddfdc", +"dfdddddddddddfdc", +"dfdddddddddddfdc", +"dfbbbbbbbbbbbfdc", +"dfbddddfbdbddfdc", +"dfbddddfbdbddfdc", +"dfffffffffffffdc", +"dddddddddddddddc", +"cccccccccccccccc", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/lock.xpm b/Utilities/FLTK/fluid/pixmaps/lock.xpm new file mode 100644 index 0000000000..3ce4b4c108 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/lock.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static const char *lock_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 6 1", +/* colors */ +"` c #000000", +"a c #c08080", +"b c #FFc0c0", +"c c none", +"d c #FFc0c0", +"e c #804040", +/* pixels */ +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccccccccc", +"cccccccccc```ccc", +"ccccccccc`daa`cc", +"cccccccc`da`bd`c", +"cccccccc`a`c`d`c", +"ccccccc`````````", +"ccccccc`dddaaae`", +"ccccccc`daa`aae`", +"ccccccc`da`eaae`", +"ccccccc`da`daee`", +"ccccccc`````````", +"cccccccccccccccc" +}; diff --git a/Utilities/FLTK/fluid/pixmaps/print_color.xpm b/Utilities/FLTK/fluid/pixmaps/print_color.xpm new file mode 100644 index 0000000000..149d67b297 --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/print_color.xpm @@ -0,0 +1,44 @@ +/* XPM */ +static char * print_color_xpm[] = { +"24 24 17 1", +" c None", +". c #FFFF00", +"+ c #C8FF00", +"@ c #00FF00", +"# c #FFC800", +"$ c #FF0000", +"% c #00FFFF", +"& c #000000", +"* c #FF00FF", +"= c #00FFC8", +"- c #FF00C8", +"; c #00C800", +"> c #C80000", +", c #0000C8", +"' c #0000FF", +") c #00C8FF", +"! c #C800FF", +" ...... ", +" .......... ", +" ............ ", +" .............. ", +" .............. ", +" ................ ", +" ................ ", +" ................ ", +" +@@@@@@+#$$$$$$# ", +" %@@@@@@@&&$$$$$$$* ", +" %%@@@@@@&&&&$$$$$$** ", +" %%%=@@@@&&&&&&$$$$-*** ", +" %%%%@@@;&&&&&&>$$$**** ", +"%%%%%%@@&&&&&&&&$$******", +"%%%%%%%@&&&&&&&&$*******", +"%%%%%%%%,&&&&&&,********", +"%%%%%%%%''''''''********", +"%%%%%%%%''''''''********", +"%%%%%%%%''''''''********", +" %%%%%%%)''''''!******* ", +" %%%%%%%%''''''******** ", +" %%%%%%%%''''******** ", +" %%%%%%%%''******** ", +" %%%%%% ****** "}; diff --git a/Utilities/FLTK/fluid/pixmaps/print_gray.xpm b/Utilities/FLTK/fluid/pixmaps/print_gray.xpm new file mode 100644 index 0000000000..4d5057bebf --- /dev/null +++ b/Utilities/FLTK/fluid/pixmaps/print_gray.xpm @@ -0,0 +1,44 @@ +/* XPM */ +static char * print_gray_xpm[] = { +"24 24 17 1", +" c None", +". c #E3E3E3", +"+ c #D2D2D2", +"@ c #969696", +"# c #C2C2C2", +"$ c #4C4C4C", +"% c #B2B2B2", +"& c #000000", +"* c #696969", +"= c #ACACAC", +"- c #626262", +"; c #767676", +"> c #3C3C3C", +", c #161616", +"' c #1C1C1C", +") c #929292", +"! c #585858", +" ...... ", +" .......... ", +" ............ ", +" .............. ", +" .............. ", +" ................ ", +" ................ ", +" ................ ", +" +@@@@@@+#$$$$$$# ", +" %@@@@@@@&&$$$$$$$* ", +" %%@@@@@@&&&&$$$$$$** ", +" %%%=@@@@&&&&&&$$$$-*** ", +" %%%%@@@;&&&&&&>$$$**** ", +"%%%%%%@@&&&&&&&&$$******", +"%%%%%%%@&&&&&&&&$*******", +"%%%%%%%%,&&&&&&,********", +"%%%%%%%%''''''''********", +"%%%%%%%%''''''''********", +"%%%%%%%%''''''''********", +" %%%%%%%)''''''!******* ", +" %%%%%%%%''''''******** ", +" %%%%%%%%''''******** ", +" %%%%%%%%''******** ", +" %%%%%% ****** "}; diff --git a/Utilities/FLTK/fluid/print_panel.cxx b/Utilities/FLTK/fluid/print_panel.cxx new file mode 100644 index 0000000000..881bb01472 --- /dev/null +++ b/Utilities/FLTK/fluid/print_panel.cxx @@ -0,0 +1,591 @@ +// +// "$Id$" +// +// FLUID print panel for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// generated by Fast Light User Interface Designer (fluid) version 1.0107 + +#include "print_panel.h" +#include <stdio.h> +#include <stdlib.h> +#include "../src/flstring.h" +#include <FL/Fl_Preferences.H> +extern Fl_Preferences fluid_prefs; + +Fl_Double_Window *print_panel=(Fl_Double_Window *)0; + +Fl_Group *print_panel_controls=(Fl_Group *)0; + +Fl_Choice *print_choice=(Fl_Choice *)0; + +static void cb_print_choice(Fl_Choice*, void*) { + print_update_status(); +} + +Fl_Button *print_properties=(Fl_Button *)0; + +static void cb_print_properties(Fl_Button*, void*) { + print_properties_panel->show(); +} + +Fl_Box *print_status=(Fl_Box *)0; + +Fl_Round_Button *print_all=(Fl_Round_Button *)0; + +static void cb_print_all(Fl_Round_Button*, void*) { + print_from->deactivate(); +print_to->deactivate(); +} + +Fl_Round_Button *print_pages=(Fl_Round_Button *)0; + +static void cb_print_pages(Fl_Round_Button*, void*) { + print_from->activate(); +print_to->activate(); +} + +Fl_Round_Button *print_selection=(Fl_Round_Button *)0; + +static void cb_print_selection(Fl_Round_Button*, void*) { + print_from->deactivate(); +print_to->deactivate(); +} + +Fl_Input *print_from=(Fl_Input *)0; + +Fl_Input *print_to=(Fl_Input *)0; + +Fl_Spinner *print_copies=(Fl_Spinner *)0; + +static void cb_print_copies(Fl_Spinner*, void*) { + if (print_copies->value() == 1) { + print_collate_button->deactivate(); + print_collate_group[0]->deactivate(); + print_collate_group[1]->deactivate(); +} else { + print_collate_button->activate(); + print_collate_group[0]->activate(); + print_collate_group[1]->activate(); +}; +} + +Fl_Check_Button *print_collate_button=(Fl_Check_Button *)0; + +static void cb_print_collate_button(Fl_Check_Button*, void*) { + int i = print_collate_button->value() != 0; +print_collate_group[i]->show(); +print_collate_group[1 - i]->hide(); +} + +Fl_Group *print_collate_group[2]={(Fl_Group *)0}; + +static void cb_Cancel(Fl_Button*, void*) { + print_panel->hide(); +} + +Fl_Progress *print_progress=(Fl_Progress *)0; + +Fl_Double_Window *print_properties_panel=(Fl_Double_Window *)0; + +static void cb_print_properties_panel(Fl_Double_Window*, void*) { + print_properties_panel->hide(); +print_update_status(); +} + +Fl_Choice *print_page_size=(Fl_Choice *)0; + +Fl_Menu_Item menu_print_page_size[] = { + {"Letter", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, + {"A4", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +#include <FL/Fl_Pixmap.H> +static const char *idata_print_color[] = { +"24 24 17 1", +" \tc None", +".\tc #FFFF00", +"+\tc #C8FF00", +"@\tc #00FF00", +"#\tc #FFC800", +"$\tc #FF0000", +"%\tc #00FFFF", +"&\tc #000000", +"*\tc #FF00FF", +"=\tc #00FFC8", +"-\tc #FF00C8", +";\tc #00C800", +">\tc #C80000", +",\tc #0000C8", +"\'\tc #0000FF", +")\tc #00C8FF", +"!\tc #C800FF", +" ...... ", +" .......... ", +" ............ ", +" .............. ", +" .............. ", +" ................ ", +" ................ ", +" ................ ", +" +@@@@@@+#$$$$$$# ", +" %@@@@@@@&&$$$$$$$* ", +" %%@@@@@@&&&&$$$$$$** ", +" %%%=@@@@&&&&&&$$$$-*** ", +" %%%%@@@;&&&&&&>$$$**** ", +"%%%%%%@@&&&&&&&&$$******", +"%%%%%%%@&&&&&&&&$*******", +"%%%%%%%%,&&&&&&,********", +"%%%%%%%%\'\'\'\'\'\'\'\'********", +"%%%%%%%%\'\'\'\'\'\'\'\'********", +"%%%%%%%%\'\'\'\'\'\'\'\'********", +" %%%%%%%)\'\'\'\'\'\'!******* ", +" %%%%%%%%\'\'\'\'\'\'******** ", +" %%%%%%%%\'\'\'\'******** ", +" %%%%%%%%\'\'******** ", +" %%%%%% ****** " +}; +static Fl_Pixmap image_print_color(idata_print_color); + +static const char *idata_print_gray[] = { +"24 24 17 1", +" \tc None", +".\tc #E3E3E3", +"+\tc #D2D2D2", +"@\tc #969696", +"#\tc #C2C2C2", +"$\tc #4C4C4C", +"%\tc #B2B2B2", +"&\tc #000000", +"*\tc #696969", +"=\tc #ACACAC", +"-\tc #626262", +";\tc #767676", +">\tc #3C3C3C", +",\tc #161616", +"\'\tc #1C1C1C", +")\tc #929292", +"!\tc #585858", +" ...... ", +" .......... ", +" ............ ", +" .............. ", +" .............. ", +" ................ ", +" ................ ", +" ................ ", +" +@@@@@@+#$$$$$$# ", +" %@@@@@@@&&$$$$$$$* ", +" %%@@@@@@&&&&$$$$$$** ", +" %%%=@@@@&&&&&&$$$$-*** ", +" %%%%@@@;&&&&&&>$$$**** ", +"%%%%%%@@&&&&&&&&$$******", +"%%%%%%%@&&&&&&&&$*******", +"%%%%%%%%,&&&&&&,********", +"%%%%%%%%\'\'\'\'\'\'\'\'********", +"%%%%%%%%\'\'\'\'\'\'\'\'********", +"%%%%%%%%\'\'\'\'\'\'\'\'********", +" %%%%%%%)\'\'\'\'\'\'!******* ", +" %%%%%%%%\'\'\'\'\'\'******** ", +" %%%%%%%%\'\'\'\'******** ", +" %%%%%%%%\'\'******** ", +" %%%%%% ****** " +}; +static Fl_Pixmap image_print_gray(idata_print_gray); + +Fl_Button *print_output_mode[4]={(Fl_Button *)0}; + +static void cb_Save(Fl_Return_Button*, void*) { + print_properties_panel->hide(); + +char name[1024]; +int val; +const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); + +snprintf(name, sizeof(name), "%s/page_size", printer); +fluid_prefs.set(name, print_page_size->value()); + +snprintf(name, sizeof(name), "%s/output_mode", printer); +for (val = 0; val < 4; val ++) { + if (print_output_mode[val]->value()) break; +} +fluid_prefs.set(name, val); +} + +static void cb_Cancel1(Fl_Button*, void*) { + print_properties_panel->hide(); +print_update_status(); +} + +static void cb_Use(Fl_Button*, void*) { + print_properties_panel->hide(); +} + +Fl_Double_Window* make_print_panel() { + Fl_Double_Window* w; + { Fl_Double_Window* o = print_panel = new Fl_Double_Window(465, 235, "Print"); + w = o; + { Fl_Group* o = print_panel_controls = new Fl_Group(10, 10, 447, 216); + { Fl_Choice* o = print_choice = new Fl_Choice(113, 10, 181, 25, "Printer:"); + o->down_box(FL_BORDER_BOX); + o->labelfont(1); + o->callback((Fl_Callback*)cb_print_choice); + o->when(FL_WHEN_CHANGED); + } + { Fl_Button* o = print_properties = new Fl_Button(294, 10, 105, 25, "Properties..."); + o->callback((Fl_Callback*)cb_print_properties); + } + { Fl_Box* o = print_status = new Fl_Box(111, 41, 288, 17, "printer/job status"); + o->align(68|FL_ALIGN_INSIDE); + } + { Fl_Group* o = new Fl_Group(10, 86, 227, 105, "Print Range"); + o->box(FL_THIN_DOWN_BOX); + o->labelfont(1); + o->align(FL_ALIGN_TOP_LEFT); + { Fl_Round_Button* o = print_all = new Fl_Round_Button(20, 96, 38, 25, "All"); + o->type(102); + o->down_box(FL_ROUND_DOWN_BOX); + o->value(1); + o->callback((Fl_Callback*)cb_print_all); + } + { Fl_Round_Button* o = print_pages = new Fl_Round_Button(20, 126, 64, 25, "Pages"); + o->type(102); + o->down_box(FL_ROUND_DOWN_BOX); + o->callback((Fl_Callback*)cb_print_pages); + } + { Fl_Round_Button* o = print_selection = new Fl_Round_Button(20, 156, 82, 25, "Selection"); + o->type(102); + o->down_box(FL_ROUND_DOWN_BOX); + o->callback((Fl_Callback*)cb_print_selection); + } + { Fl_Input* o = print_from = new Fl_Input(136, 126, 28, 25, "From:"); + o->type(2); + o->textfont(4); + o->deactivate(); + } + { Fl_Input* o = print_to = new Fl_Input(199, 126, 28, 25, "To:"); + o->type(2); + o->textfont(4); + o->deactivate(); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(247, 86, 210, 105, "Copies"); + o->box(FL_THIN_DOWN_BOX); + o->labelfont(1); + o->align(FL_ALIGN_TOP_LEFT); + { Fl_Spinner* o = print_copies = new Fl_Spinner(321, 96, 45, 25, "# Copies:"); + o->callback((Fl_Callback*)cb_print_copies); + o->when(FL_WHEN_CHANGED); + } + { Fl_Check_Button* o = print_collate_button = new Fl_Check_Button(376, 96, 64, 25, "Collate"); + o->down_box(FL_DOWN_BOX); + o->callback((Fl_Callback*)cb_print_collate_button); + o->when(FL_WHEN_CHANGED); + o->deactivate(); + } + { Fl_Group* o = print_collate_group[0] = new Fl_Group(257, 131, 191, 50); + o->deactivate(); + { Fl_Box* o = new Fl_Box(287, 141, 30, 40, "1"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + o->deactivate(); + } + { Fl_Box* o = new Fl_Box(272, 136, 30, 40, "1"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + o->deactivate(); + } + { Fl_Box* o = new Fl_Box(257, 131, 30, 40, "1"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + o->deactivate(); + } + { Fl_Box* o = new Fl_Box(352, 141, 30, 40, "2"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + o->deactivate(); + } + { Fl_Box* o = new Fl_Box(337, 136, 30, 40, "2"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + o->deactivate(); + } + { Fl_Box* o = new Fl_Box(322, 131, 30, 40, "2"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + o->deactivate(); + } + { Fl_Box* o = new Fl_Box(417, 141, 30, 40, "3"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + o->deactivate(); + } + { Fl_Box* o = new Fl_Box(402, 136, 30, 40, "3"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + o->deactivate(); + } + { Fl_Box* o = new Fl_Box(387, 131, 30, 40, "3"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + o->deactivate(); + } + o->end(); + } + { Fl_Group* o = print_collate_group[1] = new Fl_Group(257, 131, 191, 50); + o->hide(); + o->deactivate(); + { Fl_Box* o = new Fl_Box(287, 141, 30, 40, "3"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + } + { Fl_Box* o = new Fl_Box(272, 136, 30, 40, "2"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + } + { Fl_Box* o = new Fl_Box(257, 131, 30, 40, "1"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + } + { Fl_Box* o = new Fl_Box(352, 141, 30, 40, "3"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + } + { Fl_Box* o = new Fl_Box(337, 136, 30, 40, "2"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + } + { Fl_Box* o = new Fl_Box(322, 131, 30, 40, "1"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + } + { Fl_Box* o = new Fl_Box(417, 141, 30, 40, "3"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + } + { Fl_Box* o = new Fl_Box(402, 136, 30, 40, "2"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + } + { Fl_Box* o = new Fl_Box(387, 131, 30, 40, "1"); + o->box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->labelsize(11); + o->align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE); + } + o->end(); + } + o->end(); + } + { Fl_Return_Button* o = new Fl_Return_Button(309, 201, 70, 25, "Print"); + o->callback((Fl_Callback*)print_cb); + } + { Fl_Button* o = new Fl_Button(389, 201, 68, 25, "Cancel"); + o->callback((Fl_Callback*)cb_Cancel); + } + o->end(); + } + { Fl_Progress* o = print_progress = new Fl_Progress(10, 203, 289, 21); + o->selection_color((Fl_Color)4); + o->hide(); + } + o->set_modal(); + o->end(); + } + { Fl_Double_Window* o = print_properties_panel = new Fl_Double_Window(290, 130, "Printer Properties"); + w = o; + o->callback((Fl_Callback*)cb_print_properties_panel); + { Fl_Choice* o = print_page_size = new Fl_Choice(110, 10, 80, 25, "Page Size:"); + o->down_box(FL_BORDER_BOX); + o->labelfont(1); + o->menu(menu_print_page_size); + } + { Fl_Group* o = new Fl_Group(110, 45, 170, 40, "Output Mode:"); + o->labelfont(1); + o->align(FL_ALIGN_LEFT); + { Fl_Button* o = print_output_mode[0] = new Fl_Button(110, 45, 30, 40); + o->type(102); + o->box(FL_BORDER_BOX); + o->down_box(FL_BORDER_BOX); + o->value(1); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_FOREGROUND_COLOR); + o->image(image_print_color); + } + { Fl_Button* o = print_output_mode[1] = new Fl_Button(150, 50, 40, 30); + o->type(102); + o->box(FL_BORDER_BOX); + o->down_box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_FOREGROUND_COLOR); + o->image(image_print_color); + } + { Fl_Button* o = print_output_mode[2] = new Fl_Button(200, 45, 30, 40); + o->type(102); + o->box(FL_BORDER_BOX); + o->down_box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_FOREGROUND_COLOR); + o->image(image_print_gray); + } + { Fl_Button* o = print_output_mode[3] = new Fl_Button(240, 50, 40, 30); + o->type(102); + o->box(FL_BORDER_BOX); + o->down_box(FL_BORDER_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_FOREGROUND_COLOR); + o->image(image_print_gray); + } + o->end(); + } + { Fl_Return_Button* o = new Fl_Return_Button(123, 95, 79, 25, "Save"); + o->callback((Fl_Callback*)cb_Save); + } + { Fl_Button* o = new Fl_Button(212, 95, 68, 25, "Cancel"); + o->callback((Fl_Callback*)cb_Cancel1); + } + { Fl_Button* o = new Fl_Button(60, 95, 53, 25, "Use"); + o->callback((Fl_Callback*)cb_Use); + } + o->set_modal(); + o->end(); + } + return w; +} +void print_cb(Fl_Return_Button *, void *); + +void print_load() { + FILE *lpstat; +char line[1024], name[1024], *nptr, qname[2048], *qptr, defname[1024]; +int i; + +if (print_choice->size() > 1) { + for (i = 1; print_choice->text(i); i ++) { + free(print_choice->menu()[i].user_data()); + } +} + +print_choice->clear(); +print_choice->add("Print To File", 0, 0, 0, FL_MENU_DIVIDER); +print_choice->value(0); + +defname[0] = '\0'; + +if ((lpstat = popen("lpstat -p -d", "r")) != NULL) { + while (fgets(line, sizeof(line), lpstat)) { + if (!strncmp(line, "printer ", 8) && + sscanf(line + 8, "%s", name) == 1) { + for (nptr = name, qptr = qname; *nptr; *qptr++ = *nptr++) { + if (*nptr == '/') *qptr++ = '\\'; + } + *qptr = '\0'; + + print_choice->add(qname, 0, 0, (void *)strdup(name), 0); + } else if (!strncmp(line, "system default destination: ", 28)) { + if (sscanf(line + 28, "%s", defname) != 1) defname[0] = '\0'; + } + } + pclose(lpstat); +} + +if (defname[0]) { + for (i = 1; print_choice->text(i); i ++) { + if (!strcmp((char *)print_choice->menu()[i].user_data(), defname)) { + print_choice->value(i); + break; + } + } +} else if (print_choice->size() > 2) print_choice->value(1); + + +print_update_status(); +} + +void print_update_status() { + FILE *lpstat; +char command[1024]; +static char status[1024]; +const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); + +if (print_choice->value()) { + snprintf(command, sizeof(command), "lpstat -p '%s'", printer); + if ((lpstat = popen(command, "r")) != NULL) { + fgets(status, sizeof(status), lpstat); + pclose(lpstat); + } else strcpy(status, "printer status unavailable"); +} else status[0] = '\0'; + +print_status->label(status); + +char name[1024]; +int val; + +snprintf(name, sizeof(name), "%s/page_size", printer); +fluid_prefs.get(name, val, 0); +print_page_size->value(val); + +snprintf(name, sizeof(name), "%s/output_mode", printer); +fluid_prefs.get(name, val, 0); +print_output_mode[val]->setonly(); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/print_panel.fl b/Utilities/FLTK/fluid/print_panel.fl new file mode 100644 index 0000000000..723dbe841e --- /dev/null +++ b/Utilities/FLTK/fluid/print_panel.fl @@ -0,0 +1,370 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +comment {// +// "$Id$" +// +// FLUID print panel for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +} {in_source in_header +} + +decl {\#include <stdio.h>} {} + +decl {\#include <stdlib.h>} {} + +decl {\#include "../src/flstring.h"} {} + +decl {\#include <FL/Fl_Preferences.H>} {} + +decl {extern Fl_Preferences fluid_prefs;} {} + +Function {make_print_panel()} {open +} { + Fl_Window print_panel { + label Print open + xywh {342 21 465 235} type Double modal visible + } { + Fl_Group print_panel_controls {open + xywh {10 10 447 216} + } { + Fl_Choice print_choice { + label {Printer:} + callback {print_update_status();} open + xywh {113 10 181 25} down_box BORDER_BOX labelfont 1 when 1 + } {} + Fl_Button print_properties { + label {Properties...} + callback {print_properties_panel->show();} + xywh {294 10 105 25} + } + Fl_Box print_status { + label {printer/job status} + xywh {111 41 288 17} align 84 + } + Fl_Group {} { + label {Print Range} open + xywh {10 86 227 105} box THIN_DOWN_BOX labelfont 1 align 5 + } { + Fl_Round_Button print_all { + label All + callback {print_from->deactivate(); +print_to->deactivate();} + xywh {20 96 38 25} type Radio down_box ROUND_DOWN_BOX value 1 + } + Fl_Round_Button print_pages { + label Pages + callback {print_from->activate(); +print_to->activate();} + xywh {20 126 64 25} type Radio down_box ROUND_DOWN_BOX + } + Fl_Round_Button print_selection { + label Selection + callback {print_from->deactivate(); +print_to->deactivate();} + xywh {20 156 82 25} type Radio down_box ROUND_DOWN_BOX + } + Fl_Input print_from { + label {From:} + xywh {136 126 28 25} type Int textfont 4 deactivate + } + Fl_Input print_to { + label {To:} + xywh {199 126 28 25} type Int textfont 4 deactivate + } + } + Fl_Group {} { + label Copies open + xywh {247 86 210 105} box THIN_DOWN_BOX labelfont 1 align 5 + } { + Fl_Spinner print_copies { + label {\# Copies:} + callback {if (print_copies->value() == 1) { + print_collate_button->deactivate(); + print_collate_group[0]->deactivate(); + print_collate_group[1]->deactivate(); +} else { + print_collate_button->activate(); + print_collate_group[0]->activate(); + print_collate_group[1]->activate(); +}} selected + xywh {321 96 45 25} when 1 + } + Fl_Check_Button print_collate_button { + label Collate + callback {int i = print_collate_button->value() != 0; +print_collate_group[i]->show(); +print_collate_group[1 - i]->hide();} + xywh {376 96 64 25} down_box DOWN_BOX when 1 deactivate + } + Fl_Group {print_collate_group[0]} { + xywh {257 131 191 50} deactivate + } { + Fl_Box {} { + label 1 + xywh {287 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate + } + Fl_Box {} { + label 1 + xywh {272 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate + } + Fl_Box {} { + label 1 + xywh {257 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate + } + Fl_Box {} { + label 2 + xywh {352 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate + } + Fl_Box {} { + label 2 + xywh {337 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate + } + Fl_Box {} { + label 2 + xywh {322 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate + } + Fl_Box {} { + label 3 + xywh {417 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate + } + Fl_Box {} { + label 3 + xywh {402 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate + } + Fl_Box {} { + label 3 + xywh {387 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate + } + } + Fl_Group {print_collate_group[1]} { + xywh {257 131 191 50} hide deactivate + } { + Fl_Box {} { + label 3 + xywh {287 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 + } + Fl_Box {} { + label 2 + xywh {272 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 + } + Fl_Box {} { + label 1 + xywh {257 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 + } + Fl_Box {} { + label 3 + xywh {352 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 + } + Fl_Box {} { + label 2 + xywh {337 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 + } + Fl_Box {} { + label 1 + xywh {322 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 + } + Fl_Box {} { + label 3 + xywh {417 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 + } + Fl_Box {} { + label 2 + xywh {402 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 + } + Fl_Box {} { + label 1 + xywh {387 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 + } + } + } + Fl_Return_Button {} { + label Print + callback print_cb + xywh {309 201 70 25} + } + Fl_Button {} { + label Cancel + callback {print_panel->hide();} + xywh {389 201 68 25} + } + } + Fl_Progress print_progress { + xywh {10 203 289 21} selection_color 4 hide + } + } + Fl_Window print_properties_panel { + label {Printer Properties} + callback {print_properties_panel->hide(); +print_update_status();} open + xywh {340 213 290 130} type Double modal visible + } { + Fl_Choice print_page_size { + label {Page Size:} + xywh {110 10 80 25} down_box BORDER_BOX labelfont 1 + } { + MenuItem {} { + label Letter + xywh {0 0 35 25} + } + MenuItem {} { + label A4 + xywh {0 0 35 25} + } + } + Fl_Group {} { + label {Output Mode:} open + xywh {110 45 170 40} labelfont 1 align 4 + } { + Fl_Button {print_output_mode[0]} { + image {pixmaps/print_color.xpm} xywh {110 45 30 40} type Radio box BORDER_BOX down_box BORDER_BOX value 1 color 7 selection_color 0 + } + Fl_Button {print_output_mode[1]} { + image {pixmaps/print_color.xpm} xywh {150 50 40 30} type Radio box BORDER_BOX down_box BORDER_BOX color 7 selection_color 0 + } + Fl_Button {print_output_mode[2]} { + image {pixmaps/print_gray.xpm} xywh {200 45 30 40} type Radio box BORDER_BOX down_box BORDER_BOX color 7 selection_color 0 + } + Fl_Button {print_output_mode[3]} { + image {pixmaps/print_gray.xpm} xywh {240 50 40 30} type Radio box BORDER_BOX down_box BORDER_BOX color 7 selection_color 0 + } + } + Fl_Return_Button {} { + label Save + callback {print_properties_panel->hide(); + +char name[1024]; +int val; +const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); + +snprintf(name, sizeof(name), "%s/page_size", printer); +fluid_prefs.set(name, print_page_size->value()); + +snprintf(name, sizeof(name), "%s/output_mode", printer); +for (val = 0; val < 4; val ++) { + if (print_output_mode[val]->value()) break; +} +fluid_prefs.set(name, val);} + xywh {123 95 79 25} + } + Fl_Button {} { + label Cancel + callback {print_properties_panel->hide(); +print_update_status();} + xywh {212 95 68 25} + } + Fl_Button {} { + label Use + callback {print_properties_panel->hide();} + xywh {60 95 53 25} + } + } +} + +decl {void print_cb(Fl_Return_Button *, void *);} {public +} + +Function {print_load()} {open return_type void +} { + code {FILE *lpstat; +char line[1024], name[1024], *nptr, qname[2048], *qptr, defname[1024]; +int i; + +if (print_choice->size() > 1) { + for (i = 1; print_choice->text(i); i ++) { + free(print_choice->menu()[i].user_data()); + } +} + +print_choice->clear(); +print_choice->add("Print To File", 0, 0, 0, FL_MENU_DIVIDER); +print_choice->value(0); + +defname[0] = '\\0'; + +if ((lpstat = popen("lpstat -p -d", "r")) != NULL) { + while (fgets(line, sizeof(line), lpstat)) { + if (!strncmp(line, "printer ", 8) && + sscanf(line + 8, "%s", name) == 1) { + for (nptr = name, qptr = qname; *nptr; *qptr++ = *nptr++) { + if (*nptr == '/') *qptr++ = '\\\\'; + } + *qptr = '\\0'; + + print_choice->add(qname, 0, 0, (void *)strdup(name), 0); + } else if (!strncmp(line, "system default destination: ", 28)) { + if (sscanf(line + 28, "%s", defname) != 1) defname[0] = '\\0'; + } + } + pclose(lpstat); +} + +if (defname[0]) { + for (i = 1; print_choice->text(i); i ++) { + if (!strcmp((char *)print_choice->menu()[i].user_data(), defname)) { + print_choice->value(i); + break; + } + } +} else if (print_choice->size() > 2) print_choice->value(1); + + +print_update_status();} {} +} + +Function {print_update_status()} {open return_type void +} { + code {FILE *lpstat; +char command[1024]; +static char status[1024]; +const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); + +if (print_choice->value()) { + snprintf(command, sizeof(command), "lpstat -p '%s'", printer); + if ((lpstat = popen(command, "r")) != NULL) { + fgets(status, sizeof(status), lpstat); + pclose(lpstat); + } else strcpy(status, "printer status unavailable"); +} else status[0] = '\\0'; + +print_status->label(status); + +char name[1024]; +int val; + +snprintf(name, sizeof(name), "%s/page_size", printer); +fluid_prefs.get(name, val, 0); +print_page_size->value(val); + +snprintf(name, sizeof(name), "%s/output_mode", printer); +fluid_prefs.get(name, val, 0); +print_output_mode[val]->setonly();} {} +} + +comment { +// +// End of "$Id$". +//} {in_source in_header +} diff --git a/Utilities/FLTK/fluid/print_panel.h b/Utilities/FLTK/fluid/print_panel.h new file mode 100644 index 0000000000..123936f527 --- /dev/null +++ b/Utilities/FLTK/fluid/print_panel.h @@ -0,0 +1,71 @@ +// +// "$Id$" +// +// FLUID print panel for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// generated by Fast Light User Interface Designer (fluid) version 1.0107 + +#ifndef print_panel_h +#define print_panel_h +#include <FL/Fl.H> +#include <FL/Fl_Double_Window.H> +extern Fl_Double_Window *print_panel; +#include <FL/Fl_Group.H> +extern Fl_Group *print_panel_controls; +#include <FL/Fl_Choice.H> +extern Fl_Choice *print_choice; +#include <FL/Fl_Button.H> +extern Fl_Button *print_properties; +#include <FL/Fl_Box.H> +extern Fl_Box *print_status; +#include <FL/Fl_Round_Button.H> +extern Fl_Round_Button *print_all; +extern Fl_Round_Button *print_pages; +extern Fl_Round_Button *print_selection; +#include <FL/Fl_Input.H> +extern Fl_Input *print_from; +extern Fl_Input *print_to; +#include <FL/Fl_Spinner.H> +extern Fl_Spinner *print_copies; +#include <FL/Fl_Check_Button.H> +extern Fl_Check_Button *print_collate_button; +extern Fl_Group *print_collate_group[2]; +#include <FL/Fl_Return_Button.H> +extern void print_cb(Fl_Return_Button*, void*); +#include <FL/Fl_Progress.H> +extern Fl_Progress *print_progress; +extern Fl_Double_Window *print_properties_panel; +extern Fl_Choice *print_page_size; +extern Fl_Button *print_output_mode[4]; +Fl_Double_Window* make_print_panel(); +extern Fl_Menu_Item menu_print_page_size[]; +extern void print_cb(Fl_Return_Button *, void *); +void print_load(); +void print_update_status(); +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/template_panel.cxx b/Utilities/FLTK/fluid/template_panel.cxx new file mode 100644 index 0000000000..01b1a35dd7 --- /dev/null +++ b/Utilities/FLTK/fluid/template_panel.cxx @@ -0,0 +1,260 @@ +// +// "$Id$" +// +// FLUID template support for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// generated by Fast Light User Interface Designer (fluid) version 1.0107 + +#include "template_panel.h" +#include <stdio.h> +#include <stdlib.h> +#include "../src/flstring.h" +#include <errno.h> +#include <FL/filename.H> +#include <FL/fl_ask.H> +#include <FL/Fl_Shared_Image.H> +#include <FL/Fl_Preferences.H> +#if defined(WIN32) && !defined(__CYGWIN__) +#include <io.h> +#else +#include <unistd.h> +#endif // WIN32 && !__CYGWIN__ +extern Fl_Preferences fluid_prefs; + +Fl_Double_Window *template_panel=(Fl_Double_Window *)0; + +static void cb_template_panel(Fl_Double_Window*, void*) { + Fl_Shared_Image *img = (Fl_Shared_Image *)template_preview->image(); +if (img) img->release(); +template_preview->image(0); + +template_browser->deselect(); +template_name->value(""); +template_instance->value(""); +template_panel->hide(); +} + +Fl_Browser *template_browser=(Fl_Browser *)0; + +static void cb_template_browser(Fl_Browser*, void*) { + if (Fl::event_clicks()) { + template_panel->hide(); + return; +} +Fl_Shared_Image *img = (Fl_Shared_Image *)template_preview->image(); +if (img) img->release(); +template_preview->image(0); +template_preview->redraw(); + +int item = template_browser->value(); + +if (item <= 1) template_instance->deactivate(); +else template_instance->activate(); + +if (item < 1) { + template_submit->deactivate(); + template_delete->deactivate(); + return; +} + +template_submit->activate(); + +const char *flfile = (const char *)template_browser->data(item); +if (!flfile) { + template_delete->deactivate(); + return; +} + +template_name->value(template_browser->text(item)); + +template_delete->activate(); + +char pngfile[1024], *ext; + +strlcpy(pngfile, flfile, sizeof(pngfile)); +if ((ext = strrchr(pngfile, '.')) == NULL) return; +strcpy(ext, ".png"); + +img = Fl_Shared_Image::get(pngfile); + +if (img) { + template_preview->image(img); + template_preview->redraw(); +}; +} + +Fl_Box *template_preview=(Fl_Box *)0; + +Fl_Input *template_name=(Fl_Input *)0; + +static void cb_template_name(Fl_Input*, void*) { + if (strlen(template_name->value())) { + template_submit->activate(); + if (Fl::event_key() == FL_Enter) template_panel->hide(); +} else template_submit->deactivate(); +} + +Fl_Input *template_instance=(Fl_Input *)0; + +Fl_Button *template_delete=(Fl_Button *)0; + +static void cb_Cancel(Fl_Button*, void*) { + Fl_Shared_Image *img = (Fl_Shared_Image *)template_preview->image(); +if (img) img->release(); +template_preview->image(0); + +template_browser->deselect(); +template_name->value(""); +template_instance->value(""); +template_panel->hide(); +} + +Fl_Return_Button *template_submit=(Fl_Return_Button *)0; + +static void cb_template_submit(Fl_Return_Button*, void*) { + Fl_Shared_Image *img = (Fl_Shared_Image *)template_preview->image(); +if (img) img->release(); +template_preview->image(0); + +template_panel->hide(); +} + +Fl_Double_Window* make_template_panel() { + Fl_Double_Window* w; + { Fl_Double_Window* o = template_panel = new Fl_Double_Window(460, 355, "New/Save Template"); + w = o; + o->callback((Fl_Callback*)cb_template_panel); + { Fl_Browser* o = template_browser = new Fl_Browser(10, 28, 180, 250, "Available Templates:"); + o->type(2); + o->labelfont(1); + o->callback((Fl_Callback*)cb_template_browser); + o->align(FL_ALIGN_TOP_LEFT); + o->when(3); + } + { Fl_Box* o = template_preview = new Fl_Box(200, 28, 250, 250); + o->box(FL_THIN_DOWN_BOX); + o->align(69|FL_ALIGN_INSIDE); + Fl_Group::current()->resizable(o); + } + { Fl_Input* o = template_name = new Fl_Input(124, 288, 326, 25, "Template Name:"); + o->labelfont(1); + o->textfont(4); + o->callback((Fl_Callback*)cb_template_name); + o->when(3); + } + { Fl_Input* o = template_instance = new Fl_Input(124, 288, 326, 25, "Instance Name:"); + o->labelfont(1); + o->textfont(4); + o->hide(); + } + { Fl_Group* o = new Fl_Group(10, 323, 440, 25); + { Fl_Button* o = template_delete = new Fl_Button(10, 323, 133, 25, "Delete Template"); + o->callback((Fl_Callback*)template_delete_cb); + } + { Fl_Box* o = new Fl_Box(153, 323, 126, 25); + Fl_Group::current()->resizable(o); + } + { Fl_Button* o = new Fl_Button(289, 323, 72, 25, "Cancel"); + o->callback((Fl_Callback*)cb_Cancel); + } + { Fl_Return_Button* o = template_submit = new Fl_Return_Button(371, 323, 79, 25, "Save"); + o->callback((Fl_Callback*)cb_template_submit); + } + o->end(); + } + o->set_modal(); + o->end(); + } + return w; +} + +void template_clear() { + int i; +void *filename; + +for (i = 1; i <= template_browser->size(); i ++) { + if ((filename = template_browser->data(i)) != NULL) free(filename); +} + +template_browser->deselect(); +template_browser->clear(); +} + +void template_delete_cb(Fl_Button *, void *) { + int item = template_browser->value(); +if (item < 1) return; + +const char *name = template_browser->text(item); +const char *flfile = (const char *)template_browser->data(item); +if (!flfile) return; + +if (!fl_choice("Are you sure you want to delete the template \"%s\"?", + "Cancel", "Delete", 0, name)) return; + +if (unlink(flfile)) { + fl_alert("Unable to delete template \"%s\":\n%s", name, strerror(errno)); + return; +} + +template_browser->remove(item); +template_browser->do_callback(); +} + +void template_load() { + int i; +char name[1024], filename[1024], path[1024], *ptr; +struct dirent **files; +int num_files; + +fluid_prefs.getUserdataPath(path, sizeof(path)); +strlcat(path, "templates", sizeof(path)); + +num_files = fl_filename_list(path, &files); + +for (i = 0; i < num_files; i ++) { + if (fl_filename_match(files[i]->d_name, "*.fl")) { + // Format the name as the filename with "_" replaced with " " + // and without the trailing ".fl"... + strlcpy(name, files[i]->d_name, sizeof(name)); + *strstr(name, ".fl") = '\0'; + + for (ptr = name; *ptr; ptr ++) { + if (*ptr == '_') *ptr = ' '; + } + + // Add the template to the browser... + snprintf(filename, sizeof(filename), "%s/%s", path, files[i]->d_name); + template_browser->add(name, strdup(filename)); + } + + free(files[i]); +} + +if (num_files > 0) free(files); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/template_panel.fl b/Utilities/FLTK/fluid/template_panel.fl new file mode 100644 index 0000000000..8192ead447 --- /dev/null +++ b/Utilities/FLTK/fluid/template_panel.fl @@ -0,0 +1,244 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +comment {// +// "$Id$" +// +// FLUID template support for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +} {in_source in_header +} + +decl {\#include <stdio.h>} {} + +decl {\#include <stdlib.h>} {} + +decl {\#include "../src/flstring.h"} {} + +decl {\#include <errno.h>} {} + +decl {\#include <FL/filename.H>} {} + +decl {\#include <FL/fl_ask.H>} {} + +decl {\#include <FL/Fl_Shared_Image.H>} {} + +decl {\#include <FL/Fl_Preferences.H>} {} + +declblock {\#if defined(WIN32) && !defined(__CYGWIN__)} {selected after {\#endif // WIN32 && !__CYGWIN__} +} { + decl {\#include <io.h>} {} + decl {\#else} {} + decl {\#include <unistd.h>} {} +} + +decl {extern Fl_Preferences fluid_prefs;} {} + +Function {make_template_panel()} {open +} { + Fl_Window template_panel { + label {New/Save Template} + callback {Fl_Shared_Image *img = (Fl_Shared_Image *)template_preview->image(); +if (img) img->release(); +template_preview->image(0); + +template_browser->deselect(); +template_name->value(""); +template_instance->value(""); +template_panel->hide();} open + xywh {340 237 460 355} type Double resizable modal visible + } { + Fl_Browser template_browser { + label {Available Templates:} + callback {if (Fl::event_clicks()) { + template_panel->hide(); + return; +} +Fl_Shared_Image *img = (Fl_Shared_Image *)template_preview->image(); +if (img) img->release(); +template_preview->image(0); +template_preview->redraw(); + +int item = template_browser->value(); + +if (item <= 1) template_instance->deactivate(); +else template_instance->activate(); + +if (item < 1) { + template_submit->deactivate(); + template_delete->deactivate(); + return; +} + +template_submit->activate(); + +const char *flfile = (const char *)template_browser->data(item); +if (!flfile) { + template_delete->deactivate(); + return; +} + +template_name->value(template_browser->text(item)); + +template_delete->activate(); + +char pngfile[1024], *ext; + +strlcpy(pngfile, flfile, sizeof(pngfile)); +if ((ext = strrchr(pngfile, '.')) == NULL) return; +strcpy(ext, ".png"); + +img = Fl_Shared_Image::get(pngfile); + +if (img) { + template_preview->image(img); + template_preview->redraw(); +}} + xywh {10 28 180 250} type Hold labelfont 1 align 5 when 3 + } + Fl_Box template_preview { + xywh {200 28 250 250} box THIN_DOWN_BOX align 85 resizable + } + Fl_Input template_name { + label {Template Name:} + callback {if (strlen(template_name->value())) { + template_submit->activate(); + if (Fl::event_key() == FL_Enter) template_panel->hide(); +} else template_submit->deactivate();} + xywh {124 288 326 25} labelfont 1 when 3 textfont 4 + } + Fl_Input template_instance { + label {Instance Name:} + xywh {124 288 326 25} labelfont 1 textfont 4 hide + } + Fl_Group {} { + xywh {10 323 440 25} + } { + Fl_Button template_delete { + label {Delete Template} + callback template_delete_cb + xywh {10 323 133 25} + } + Fl_Box {} { + xywh {153 323 126 25} resizable + } + Fl_Button {} { + label Cancel + callback {Fl_Shared_Image *img = (Fl_Shared_Image *)template_preview->image(); +if (img) img->release(); +template_preview->image(0); + +template_browser->deselect(); +template_name->value(""); +template_instance->value(""); +template_panel->hide();} + xywh {289 323 72 25} + } + Fl_Return_Button template_submit { + label Save + callback {Fl_Shared_Image *img = (Fl_Shared_Image *)template_preview->image(); +if (img) img->release(); +template_preview->image(0); + +template_panel->hide();} + xywh {371 323 79 25} + } + } + } +} + +Function {template_clear()} {return_type void +} { + code {int i; +void *filename; + +for (i = 1; i <= template_browser->size(); i ++) { + if ((filename = template_browser->data(i)) != NULL) free(filename); +} + +template_browser->deselect(); +template_browser->clear();} {} +} + +Function {template_delete_cb(Fl_Button *, void *)} {return_type void +} { + code {int item = template_browser->value(); +if (item < 1) return; + +const char *name = template_browser->text(item); +const char *flfile = (const char *)template_browser->data(item); +if (!flfile) return; + +if (!fl_choice("Are you sure you want to delete the template \\"%s\\"?", + "Cancel", "Delete", 0, name)) return; + +if (unlink(flfile)) { + fl_alert("Unable to delete template \\"%s\\":\\n%s", name, strerror(errno)); + return; +} + +template_browser->remove(item); +template_browser->do_callback();} {} +} + +Function {template_load()} {open return_type void +} { + code {int i; +char name[1024], filename[1024], path[1024], *ptr; +struct dirent **files; +int num_files; + +fluid_prefs.getUserdataPath(path, sizeof(path)); +strlcat(path, "templates", sizeof(path)); + +num_files = fl_filename_list(path, &files); + +for (i = 0; i < num_files; i ++) { + if (fl_filename_match(files[i]->d_name, "*.fl")) { + // Format the name as the filename with "_" replaced with " " + // and without the trailing ".fl"... + strlcpy(name, files[i]->d_name, sizeof(name)); + *strstr(name, ".fl") = '\\0'; + + for (ptr = name; *ptr; ptr ++) { + if (*ptr == '_') *ptr = ' '; + } + + // Add the template to the browser... + snprintf(filename, sizeof(filename), "%s/%s", path, files[i]->d_name); + template_browser->add(name, strdup(filename)); + } + + free(files[i]); +} + +if (num_files > 0) free(files);} {} +} + +comment { +// +// End of "$Id$". +//} {in_source in_header +} diff --git a/Utilities/FLTK/fluid/template_panel.h b/Utilities/FLTK/fluid/template_panel.h new file mode 100644 index 0000000000..df5898a88f --- /dev/null +++ b/Utilities/FLTK/fluid/template_panel.h @@ -0,0 +1,56 @@ +// +// "$Id$" +// +// FLUID template support for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// generated by Fast Light User Interface Designer (fluid) version 1.0107 + +#ifndef template_panel_h +#define template_panel_h +#include <FL/Fl.H> +#include <FL/Fl_Double_Window.H> +extern Fl_Double_Window *template_panel; +#include <FL/Fl_Browser.H> +extern Fl_Browser *template_browser; +#include <FL/Fl_Box.H> +extern Fl_Box *template_preview; +#include <FL/Fl_Input.H> +extern Fl_Input *template_name; +extern Fl_Input *template_instance; +#include <FL/Fl_Group.H> +#include <FL/Fl_Button.H> +extern void template_delete_cb(Fl_Button*, void*); +extern Fl_Button *template_delete; +#include <FL/Fl_Return_Button.H> +extern Fl_Return_Button *template_submit; +Fl_Double_Window* make_template_panel(); +void template_clear(); +void template_delete_cb(Fl_Button *, void *); +void template_load(); +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/undo.cxx b/Utilities/FLTK/fluid/undo.cxx new file mode 100644 index 0000000000..e23b6ca161 --- /dev/null +++ b/Utilities/FLTK/fluid/undo.cxx @@ -0,0 +1,189 @@ +// +// "$Id$" +// +// FLUID undo support for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include "Fl_Type.h" +#include "undo.h" +#include <FL/Fl_Preferences.H> +#include "../src/flstring.h" +#if defined(WIN32) && !defined(__CYGWIN__) +# include <io.h> +# include <windows.h> +# define getpid (int)GetCurrentProcessId +// Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs +// on Windows, which is supposed to be POSIX compliant... +# define unlink _unlink +#else +# include <unistd.h> +#endif // WIN32 && !__CYGWIN__ + + +extern Fl_Preferences fluid_prefs; // FLUID preferences +extern Fl_Menu_Item Main_Menu[]; // Main menu + +#define UNDO_ITEM 25 // Undo menu item index +#define REDO_ITEM 26 // Redo menu item index + + +// +// This file implements an undo system using temporary files; ideally +// we'd like to do this in memory, however the current data structures +// and design aren't well-suited... Instead, we save and restore +// checkpoint files. +// + + +int undo_current = 0; // Current undo level in buffer +int undo_last = 0; // Last undo level in buffer +int undo_max = 0; // Maximum undo level used +int undo_save = -1; // Last undo level that was saved +static int undo_paused = 0; // Undo checkpointing paused? + + +// Return the undo filename +static char *undo_filename(int level, char *buf, int bufsize) { + static char undo_path[1024] = ""; // Undo path + + + if (!undo_path[0]) fluid_prefs.getUserdataPath(undo_path, sizeof(undo_path)); + + snprintf(buf, bufsize, "%sundo_%d_%d.fl", undo_path, getpid(), level); + return buf; +} + + +// Redo menu callback +void redo_cb(Fl_Widget *, void *) { + char filename[1024]; // Undo checkpoint file + + if (undo_current >= undo_last) return; + + undo_suspend(); + if (!read_file(undo_filename(undo_current + 1, filename, sizeof(filename)), 0)) { + // Unable to read checkpoint file, don't redo... + undo_resume(); + return; + } + + undo_current ++; + + // Update modified flag... + set_modflag(undo_current != undo_save); + + // Update undo/redo menu items... + if (undo_current >= undo_last) Main_Menu[REDO_ITEM].deactivate(); + Main_Menu[UNDO_ITEM].activate(); +} + +// Undo menu callback +void undo_cb(Fl_Widget *, void *) { + char filename[1024]; // Undo checkpoint file + + if (undo_current <= 0) return; + + if (undo_current == undo_last) { + write_file(undo_filename(undo_current, filename, sizeof(filename))); + } + + undo_suspend(); + if (!read_file(undo_filename(undo_current - 1, filename, sizeof(filename)), 0)) { + // Unable to read checkpoint file, don't undo... + undo_resume(); + return; + } + + undo_current --; + + // Update modified flag... + set_modflag(undo_current != undo_save); + + // Update undo/redo menu items... + if (undo_current <= 0) Main_Menu[UNDO_ITEM].deactivate(); + Main_Menu[REDO_ITEM].activate(); +} + +// Save current file to undo buffer +void undo_checkpoint() { + char filename[1024]; // Undo checkpoint filename + +// printf("undo_checkpoint(): undo_current=%d, undo_paused=%d, modflag=%d\n", +// undo_current, undo_paused, modflag); + + // Don't checkpoint if undo_suspend() has been called... + if (undo_paused) return; + + // Save the current UI to a checkpoint file... + if (!write_file(undo_filename(undo_current, filename, sizeof(filename)))) { + // Don't attempt to do undo stuff if we can't write a checkpoint file... + perror(filename); + return; + } + + // Update the saved level... + if (modflag && undo_current <= undo_save) undo_save = -1; + else if (!modflag) undo_save = undo_current; + + // Update the current undo level... + undo_current ++; + undo_last = undo_current; + if (undo_current > undo_max) undo_max = undo_current; + + // Enable the Undo and disable the Redo menu items... + Main_Menu[UNDO_ITEM].activate(); + Main_Menu[REDO_ITEM].deactivate(); +} + +// Clear undo buffer +void undo_clear() { + char filename[1024]; // Undo checkpoint filename + + + // Remove old checkpoint files... + for (int i = 0; i <= undo_max; i ++) { + unlink(undo_filename(i, filename, sizeof(filename))); + } + + // Reset current, last, and save indices... + undo_current = undo_last = undo_max = 0; + if (modflag) undo_save = -1; + else undo_save = 0; +} + +// Resume undo checkpoints +void undo_resume() { + undo_paused = 0; +} + +// Suspend undo checkpoints +void undo_suspend() { + undo_paused = 1; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/undo.h b/Utilities/FLTK/fluid/undo.h new file mode 100644 index 0000000000..949f150e53 --- /dev/null +++ b/Utilities/FLTK/fluid/undo.h @@ -0,0 +1,46 @@ +// +// "$Id$" +// +// FLUID undo definitions for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifndef undo_h +# define undo_h + +extern int undo_current; // Current undo level in buffer +extern int undo_last; // Last undo level in buffer +extern int undo_save; // Last undo level that was saved + +void redo_cb(Fl_Widget *, void *); // Redo menu callback +void undo_cb(Fl_Widget *, void *); // Undo menu callback +void undo_checkpoint(); // Save current file to undo buffer +void undo_clear(); // Clear undo buffer +void undo_resume(); // Resume undo checkpoints +void undo_suspend(); // Suspend undo checkpoints + +#endif // !undo_h + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/widget_panel.cxx b/Utilities/FLTK/fluid/widget_panel.cxx new file mode 100644 index 0000000000..1adf4c4367 --- /dev/null +++ b/Utilities/FLTK/fluid/widget_panel.cxx @@ -0,0 +1,764 @@ +// +// "$Id$" +// +// Widget panel for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// generated by Fast Light User Interface Designer (fluid) version 1.0107 + +#include "widget_panel.h" + +static void cb_(Fl_Tabs* o, void* v) { + propagate_load((Fl_Group *)o,v); +} + +Fl_Value_Input *widget_x_input=(Fl_Value_Input *)0; + +Fl_Value_Input *widget_y_input=(Fl_Value_Input *)0; + +Fl_Value_Input *widget_w_input=(Fl_Value_Input *)0; + +Fl_Value_Input *widget_h_input=(Fl_Value_Input *)0; + +Fl_Input *v_input[4]={(Fl_Input *)0}; + +Fl_Button *wLiveMode=(Fl_Button *)0; + +Fl_Double_Window* make_widget_panel() { + Fl_Double_Window* w; + { Fl_Double_Window* o = new Fl_Double_Window(410, 355); + w = o; + o->labelsize(11); + w->hotspot(o); + { Fl_Tabs* o = new Fl_Tabs(5, 5, 400, 310); + o->selection_color((Fl_Color)4); + o->labelsize(11); + o->labelcolor(FL_BACKGROUND2_COLOR); + o->callback((Fl_Callback*)cb_); + o->when(FL_WHEN_NEVER); + { Fl_Group* o = new Fl_Group(5, 25, 400, 290, "GUI"); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->when(FL_WHEN_NEVER); + { Fl_Group* o = new Fl_Group(90, 35, 300, 20, "Label:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(FL_ALIGN_LEFT); + { Fl_Input* o = new Fl_Input(90, 35, 180, 20); + o->tooltip("The label text for the widget."); + o->labelfont(1); + o->labelsize(11); + o->textsize(11); + o->callback((Fl_Callback*)label_cb); + o->when(FL_WHEN_CHANGED); + Fl_Group::current()->resizable(o); + } + { Fl_Choice* o = new Fl_Choice(270, 35, 120, 20); + o->tooltip("The label style for the widget."); + o->box(FL_THIN_UP_BOX); + o->down_box(FL_BORDER_BOX); + o->labelfont(1); + o->labelsize(11); + o->textsize(11); + o->callback((Fl_Callback*)labeltype_cb); + o->menu(labeltypemenu); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(90, 60, 300, 20, "Image:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(FL_ALIGN_LEFT); + { Fl_Input* o = new Fl_Input(90, 60, 230, 20); + o->tooltip("The active image for the widget."); + o->labelfont(1); + o->labelsize(11); + o->textsize(11); + o->callback((Fl_Callback*)image_cb); + Fl_Group::current()->resizable(o); + } + { Fl_Button* o = new Fl_Button(320, 60, 70, 20, "Browse..."); + o->tooltip("Click to choose the active image."); + o->labelsize(11); + o->callback((Fl_Callback*)image_browse_cb); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(90, 85, 300, 20, "Inactive:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(FL_ALIGN_LEFT); + { Fl_Input* o = new Fl_Input(90, 85, 230, 20); + o->tooltip("The inactive image for the widget."); + o->labelfont(1); + o->labelsize(11); + o->textsize(11); + o->callback((Fl_Callback*)inactive_cb); + Fl_Group::current()->resizable(o); + } + { Fl_Button* o = new Fl_Button(320, 85, 70, 20, "Browse..."); + o->tooltip("Click to choose the inactive image."); + o->labelsize(11); + o->callback((Fl_Callback*)inactive_browse_cb); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(90, 110, 300, 20, "Alignment:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(FL_ALIGN_LEFT); + { Fl_Button* o = new Fl_Button(90, 110, 45, 20, "Clip"); + o->tooltip("Clip the label to the inside of the widget."); + o->type(1); + o->selection_color(FL_INACTIVE_COLOR); + o->labelsize(11); + o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_CLIP)); + o->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE); + } + { Fl_Button* o = new Fl_Button(140, 110, 50, 20, "Wrap"); + o->tooltip("Wrap the label text."); + o->type(1); + o->selection_color(FL_INACTIVE_COLOR); + o->labelsize(11); + o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_WRAP)); + } + { Fl_Button* o = new Fl_Button(195, 110, 65, 20, "Text/Image"); + o->tooltip("Show the label text over the image."); + o->type(1); + o->selection_color(FL_INACTIVE_COLOR); + o->labelsize(11); + o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_TEXT_OVER_IMAGE)); + } + { Fl_Button* o = new Fl_Button(265, 110, 20, 20, "@-1<-"); + o->tooltip("Left-align the label."); + o->type(1); + o->selection_color(FL_INACTIVE_COLOR); + o->labelsize(11); + o->labelcolor(FL_INACTIVE_COLOR); + o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_LEFT)); + } + { Fl_Button* o = new Fl_Button(290, 110, 20, 20, "@-1->"); + o->tooltip("Right-align the label."); + o->type(1); + o->selection_color(FL_INACTIVE_COLOR); + o->labelsize(11); + o->labelcolor(FL_INACTIVE_COLOR); + o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_RIGHT)); + } + { Fl_Button* o = new Fl_Button(315, 110, 20, 20, "@-18"); + o->tooltip("Top-align the label."); + o->type(1); + o->selection_color(FL_INACTIVE_COLOR); + o->labelsize(11); + o->labelcolor(FL_INACTIVE_COLOR); + o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_TOP)); + } + { Fl_Button* o = new Fl_Button(340, 110, 20, 20, "@-12"); + o->tooltip("Bottom-align the label."); + o->type(1); + o->selection_color(FL_INACTIVE_COLOR); + o->labelsize(11); + o->labelcolor(FL_INACTIVE_COLOR); + o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_BOTTOM)); + } + { Fl_Button* o = new Fl_Button(365, 110, 20, 20, "@-3square"); + o->tooltip("Show the label inside the widget."); + o->type(1); + o->selection_color(FL_INACTIVE_COLOR); + o->labelsize(11); + o->labelcolor(FL_INACTIVE_COLOR); + o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_INSIDE)); + } + { Fl_Box* o = new Fl_Box(390, 110, 0, 20); + o->labelsize(11); + Fl_Group::current()->resizable(o); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(90, 145, 300, 20, "Position:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(FL_ALIGN_LEFT); + { Fl_Value_Input* o = widget_x_input = new Fl_Value_Input(90, 145, 55, 20, "X:"); + o->tooltip("The X position of the widget."); + o->labelsize(11); + o->maximum(2048); + o->step(1); + o->textsize(11); + o->callback((Fl_Callback*)x_cb); + o->align(FL_ALIGN_TOP_LEFT); + } + { Fl_Value_Input* o = widget_y_input = new Fl_Value_Input(150, 145, 55, 20, "Y:"); + o->tooltip("The Y position of the widget."); + o->labelsize(11); + o->maximum(2048); + o->step(1); + o->textsize(11); + o->callback((Fl_Callback*)y_cb); + o->align(FL_ALIGN_TOP_LEFT); + } + { Fl_Value_Input* o = widget_w_input = new Fl_Value_Input(210, 145, 55, 20, "Width:"); + o->tooltip("The width of the widget."); + o->labelsize(11); + o->maximum(2048); + o->step(1); + o->textsize(11); + o->callback((Fl_Callback*)w_cb); + o->align(FL_ALIGN_TOP_LEFT); + } + { Fl_Value_Input* o = widget_h_input = new Fl_Value_Input(270, 145, 55, 20, "Height:"); + o->tooltip("The height of the widget."); + o->labelsize(11); + o->maximum(2048); + o->step(1); + o->textsize(11); + o->callback((Fl_Callback*)h_cb); + o->align(FL_ALIGN_TOP_LEFT); + } + { Fl_Light_Button* o = new Fl_Light_Button(330, 145, 55, 20, "Relative"); + o->tooltip("If set, widgets inside a widget class of type Fl_Group are repositioned relat\ +ive to the origin at construction time"); + o->labelsize(11); + o->callback((Fl_Callback*)wc_relative_cb); + } + { Fl_Box* o = new Fl_Box(389, 145, 1, 20); + Fl_Group::current()->resizable(o); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(90, 180, 300, 20, "Values:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(FL_ALIGN_LEFT); + { Fl_Value_Input* o = new Fl_Value_Input(90, 180, 55, 20, "Size:"); + o->tooltip("The size of the slider."); + o->labelsize(11); + o->step(0.010101); + o->textsize(11); + o->callback((Fl_Callback*)slider_size_cb); + o->align(FL_ALIGN_TOP_LEFT); + } + { Fl_Value_Input* o = new Fl_Value_Input(150, 180, 55, 20, "Minimum:"); + o->tooltip("The minimum value of the widget."); + o->labelsize(11); + o->textsize(11); + o->callback((Fl_Callback*)min_cb); + o->align(FL_ALIGN_TOP_LEFT); + } + { Fl_Value_Input* o = new Fl_Value_Input(210, 180, 55, 20, "Maximum:"); + o->tooltip("The maximum value of the widget."); + o->labelsize(11); + o->value(1); + o->textsize(11); + o->callback((Fl_Callback*)max_cb); + o->align(FL_ALIGN_TOP_LEFT); + } + { Fl_Value_Input* o = new Fl_Value_Input(270, 180, 55, 20, "Step:"); + o->tooltip("The resolution of the widget value."); + o->labelsize(11); + o->textsize(11); + o->callback((Fl_Callback*)step_cb); + o->align(FL_ALIGN_TOP_LEFT); + } + { Fl_Value_Input* o = new Fl_Value_Input(330, 180, 55, 20, "Value:"); + o->tooltip("The current widget value."); + o->labelsize(11); + o->textsize(11); + o->callback((Fl_Callback*)value_cb); + o->align(FL_ALIGN_TOP_LEFT); + } + { Fl_Box* o = new Fl_Box(390, 180, 0, 20); + Fl_Group::current()->resizable(o); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(90, 180, 300, 20, "Size Range:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(FL_ALIGN_LEFT); + o->hide(); + { Fl_Value_Input* o = new Fl_Value_Input(90, 180, 55, 20, "Minimum Size:"); + o->tooltip("The size of the slider."); + o->labelsize(11); + o->maximum(2048); + o->step(1); + o->textsize(11); + o->callback((Fl_Callback*)min_w_cb); + o->align(FL_ALIGN_TOP_LEFT); + } + { Fl_Value_Input* o = new Fl_Value_Input(150, 180, 55, 20); + o->tooltip("The minimum value of the widget."); + o->labelsize(11); + o->maximum(2048); + o->step(1); + o->textsize(11); + o->callback((Fl_Callback*)min_h_cb); + o->align(FL_ALIGN_TOP_LEFT); + } + { Fl_Button* o = new Fl_Button(210, 180, 25, 20, "set"); + o->labelsize(11); + o->callback((Fl_Callback*)set_min_size_cb); + } + { Fl_Value_Input* o = new Fl_Value_Input(240, 180, 55, 20, "Maximum Size:"); + o->tooltip("The maximum value of the widget."); + o->labelsize(11); + o->maximum(2048); + o->step(1); + o->textsize(11); + o->callback((Fl_Callback*)max_w_cb); + o->align(FL_ALIGN_TOP_LEFT); + } + { Fl_Value_Input* o = new Fl_Value_Input(300, 180, 55, 20); + o->tooltip("The resolution of the widget value."); + o->labelsize(11); + o->maximum(2048); + o->step(1); + o->textsize(11); + o->callback((Fl_Callback*)max_h_cb); + o->align(FL_ALIGN_TOP_LEFT); + } + { Fl_Button* o = new Fl_Button(360, 180, 25, 20, "set"); + o->labelsize(11); + o->callback((Fl_Callback*)set_max_size_cb); + } + { Fl_Box* o = new Fl_Box(390, 180, 0, 20); + Fl_Group::current()->resizable(o); + } + o->end(); + } + { Shortcut_Button* o = new Shortcut_Button(90, 205, 300, 20, "Shortcut:"); + o->tooltip("The shortcut key for the widget."); + o->box(FL_DOWN_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_BACKGROUND2_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(1); + o->labelsize(11); + o->labelcolor(FL_FOREGROUND_COLOR); + o->callback((Fl_Callback*)shortcut_in_cb); + o->align(FL_ALIGN_LEFT); + o->when(FL_WHEN_RELEASE); + } + { Fl_Group* o = new Fl_Group(90, 230, 300, 20, "X Class:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(FL_ALIGN_LEFT); + { Fl_Input* o = new Fl_Input(90, 230, 95, 20, ":"); + o->tooltip("The X resource class."); + o->labelfont(1); + o->labelsize(11); + o->textsize(11); + o->callback((Fl_Callback*)xclass_cb); + Fl_Group::current()->resizable(o); + } + { Fl_Light_Button* o = new Fl_Light_Button(190, 230, 60, 20, "Border"); + o->tooltip("Add a border around the window."); + o->selection_color((Fl_Color)1); + o->labelsize(11); + o->callback((Fl_Callback*)border_cb); + } + { Fl_Light_Button* o = new Fl_Light_Button(255, 230, 55, 20, "Modal"); + o->tooltip("Make the window modal."); + o->selection_color((Fl_Color)1); + o->labelsize(11); + o->callback((Fl_Callback*)modal_cb); + } + { Fl_Light_Button* o = new Fl_Light_Button(315, 230, 75, 20, "Nonmodal"); + o->tooltip("Make the window non-modal."); + o->selection_color((Fl_Color)1); + o->labelsize(11); + o->callback((Fl_Callback*)non_modal_cb); + o->align(132|FL_ALIGN_INSIDE); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(90, 255, 305, 20, "Attributes:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(FL_ALIGN_LEFT); + { Fl_Light_Button* o = new Fl_Light_Button(90, 255, 60, 20, "Visible"); + o->tooltip("Show the widget."); + o->selection_color((Fl_Color)1); + o->labelsize(11); + o->callback((Fl_Callback*)visible_cb); + } + { Fl_Light_Button* o = new Fl_Light_Button(155, 255, 60, 20, "Active"); + o->tooltip("Activate the widget."); + o->selection_color((Fl_Color)1); + o->labelsize(11); + o->callback((Fl_Callback*)active_cb); + } + { Fl_Light_Button* o = new Fl_Light_Button(220, 255, 75, 20, "Resizable"); + o->tooltip("Make the widget resizable."); + o->selection_color((Fl_Color)1); + o->labelsize(11); + o->callback((Fl_Callback*)resizable_cb); + o->when(FL_WHEN_CHANGED); + } + { Fl_Light_Button* o = new Fl_Light_Button(300, 255, 70, 20, "Hotspot"); + o->tooltip("Center the window under this widget."); + o->selection_color((Fl_Color)1); + o->labelsize(11); + o->callback((Fl_Callback*)hotspot_cb); + o->when(FL_WHEN_CHANGED); + } + { Fl_Box* o = new Fl_Box(390, 255, 0, 20); + o->labelsize(11); + Fl_Group::current()->resizable(o); + } + o->end(); + } + { Fl_Input* o = new Fl_Input(90, 280, 300, 20, "Tooltip:"); + o->tooltip("The tooltip text for the widget."); + o->labelfont(1); + o->labelsize(11); + o->textsize(11); + o->callback((Fl_Callback*)tooltip_cb); + } + { Fl_Box* o = new Fl_Box(90, 300, 300, 5); + o->labelsize(11); + Fl_Group::current()->resizable(o); + } + o->end(); + Fl_Group::current()->resizable(o); + } + { Fl_Group* o = new Fl_Group(5, 25, 400, 290, "Style"); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->when(FL_WHEN_NEVER); + o->hide(); + { Fl_Group* o = new Fl_Group(90, 35, 300, 20, "Label Font:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(FL_ALIGN_LEFT); + { Fl_Choice* o = new Fl_Choice(90, 35, 160, 20); + o->tooltip("The style of the label text."); + o->box(FL_THIN_UP_BOX); + o->down_box(FL_BORDER_BOX); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)labelfont_cb); + Fl_Group::current()->resizable(o); + o->menu(fontmenu); + } + { Fl_Value_Input* o = new Fl_Value_Input(250, 35, 50, 20); + o->tooltip("The size of the label text."); + o->labelsize(11); + o->maximum(100); + o->step(1); + o->value(14); + o->textsize(11); + o->callback((Fl_Callback*)labelsize_cb); + } + { Fl_Button* o = new Fl_Button(300, 35, 90, 20, "Label Color"); + o->tooltip("The color of the label text."); + o->labelsize(11); + o->callback((Fl_Callback*)labelcolor_cb); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(90, 60, 300, 20, "Box:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(FL_ALIGN_LEFT); + { Fl_Choice* o = new Fl_Choice(90, 60, 210, 20); + o->tooltip("The \"up\" box of the widget."); + o->box(FL_THIN_UP_BOX); + o->down_box(FL_BORDER_BOX); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)box_cb); + Fl_Group::current()->resizable(o); + o->menu(boxmenu); + } + { Fl_Button* o = new Fl_Button(300, 60, 90, 20, "Color"); + o->tooltip("The background color of the widget."); + o->labelsize(11); + o->callback((Fl_Callback*)color_cb); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(90, 85, 300, 20, "Down Box:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(FL_ALIGN_LEFT); + { Fl_Choice* o = new Fl_Choice(90, 85, 210, 20); + o->tooltip("The \"down\" box of the widget."); + o->box(FL_THIN_UP_BOX); + o->down_box(FL_BORDER_BOX); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)down_box_cb); + Fl_Group::current()->resizable(o); + o->menu(boxmenu); + } + { Fl_Button* o = new Fl_Button(300, 85, 90, 20, "Select Color"); + o->tooltip("The selection color of the widget."); + o->labelsize(11); + o->callback((Fl_Callback*)color2_cb); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(90, 110, 300, 20, "Text Font:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(FL_ALIGN_LEFT); + { Fl_Choice* o = new Fl_Choice(90, 110, 160, 20); + o->tooltip("The value text style."); + o->box(FL_DOWN_BOX); + o->down_box(FL_BORDER_BOX); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)textfont_cb); + Fl_Group::current()->resizable(o); + o->menu(fontmenu); + } + { Fl_Value_Input* o = new Fl_Value_Input(250, 110, 50, 20); + o->tooltip("The value text size."); + o->labelsize(11); + o->maximum(100); + o->step(1); + o->value(14); + o->textsize(11); + o->callback((Fl_Callback*)textsize_cb); + } + { Fl_Button* o = new Fl_Button(300, 110, 90, 20, "Text Color"); + o->tooltip("The value text color."); + o->labelsize(11); + o->callback((Fl_Callback*)textcolor_cb); + } + o->end(); + } + { Fl_Box* o = new Fl_Box(90, 135, 300, 40); + o->labelsize(11); + Fl_Group::current()->resizable(o); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(5, 25, 400, 290, "C++"); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->when(FL_WHEN_NEVER); + o->hide(); + { Fl_Group* o = new Fl_Group(90, 35, 300, 20, "Class:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(FL_ALIGN_LEFT); + { Fl_Input* o = new Fl_Input(90, 35, 160, 20); + o->tooltip("The widget subclass."); + o->labelfont(1); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->callback((Fl_Callback*)subclass_cb, (void*)(4)); + Fl_Group::current()->resizable(o); + } + { Fl_Choice* o = new Fl_Choice(250, 35, 140, 20); + o->tooltip("The widget subtype."); + o->box(FL_THIN_UP_BOX); + o->down_box(FL_BORDER_BOX); + o->labelsize(11); + o->callback((Fl_Callback*)subtype_cb); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(90, 60, 300, 20, "Name:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(FL_ALIGN_LEFT); + { Fl_Input* o = new Fl_Input(90, 60, 240, 20); + o->tooltip("The name of the widget."); + o->labelfont(1); + o->labelsize(11); + o->textsize(11); + o->callback((Fl_Callback*)name_cb); + Fl_Group::current()->resizable(o); + } + { Fl_Light_Button* o = new Fl_Light_Button(330, 60, 60, 20, "public"); + o->tooltip("Make the widget publicly accessible."); + o->selection_color((Fl_Color)1); + o->labelsize(11); + o->callback((Fl_Callback*)name_public_cb); + o->when(FL_WHEN_CHANGED); + } + o->end(); + } + { Fl_Input* o = v_input[0] = new Fl_Input(90, 85, 300, 20, "Extra Code:"); + o->tooltip("Extra initialization code for the widget."); + o->labelfont(1); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->callback((Fl_Callback*)v_input_cb, (void*)(0)); + } + { Fl_Input* o = v_input[1] = new Fl_Input(90, 105, 300, 20); + o->tooltip("Extra initialization code for the widget."); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->callback((Fl_Callback*)v_input_cb, (void*)(1)); + } + { Fl_Input* o = v_input[2] = new Fl_Input(90, 125, 300, 20); + o->tooltip("Extra initialization code for the widget."); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->callback((Fl_Callback*)v_input_cb, (void*)(2)); + } + { Fl_Input* o = v_input[3] = new Fl_Input(90, 145, 300, 20); + o->tooltip("Extra initialization code for the widget."); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->callback((Fl_Callback*)v_input_cb, (void*)(3)); + } + { CodeEditor* o = new CodeEditor(90, 170, 300, 90, "Callback:"); + o->tooltip("The callback function or code for the widget. Use the variable name \'o\' to \ +access the Widget pointer and \'v\' to access the user value."); + o->box(FL_DOWN_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_SELECTION_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(1); + o->labelsize(11); + o->labelcolor(FL_FOREGROUND_COLOR); + o->textfont(4); + o->textsize(11); + o->callback((Fl_Callback*)callback_cb); + o->align(FL_ALIGN_LEFT); + o->when(FL_WHEN_RELEASE); + Fl_Group::current()->resizable(o); + } + { Fl_Group* o = new Fl_Group(90, 265, 300, 20, "User Data:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(FL_ALIGN_LEFT); + { Fl_Input* o = new Fl_Input(90, 265, 140, 20); + o->tooltip("The user data to pass into the callback code."); + o->labelfont(1); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->callback((Fl_Callback*)user_data_cb); + Fl_Group::current()->resizable(o); + } + { Fl_Choice* o = new Fl_Choice(285, 265, 105, 20, "When:"); + o->tooltip("When to call the callback function."); + o->box(FL_THIN_UP_BOX); + o->down_box(FL_BORDER_BOX); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)when_cb); + o->when(FL_WHEN_CHANGED); + o->menu(whenmenu); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(90, 290, 300, 20, "Type:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(FL_ALIGN_LEFT); + { Fl_Input* o = new Fl_Input(90, 290, 140, 20); + o->tooltip("The type of the user data."); + o->labelfont(1); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->callback((Fl_Callback*)user_data_type_cb); + Fl_Group::current()->resizable(o); + } + { Fl_Light_Button* o = new Fl_Light_Button(285, 290, 105, 20, "No Change"); + o->tooltip("Call the callback even if the value has not changed."); + o->selection_color((Fl_Color)1); + o->labelsize(11); + o->callback((Fl_Callback*)when_button_cb); + } + o->end(); + } + o->end(); + } + o->end(); + Fl_Group::current()->resizable(o); + } + { Fl_Group* o = new Fl_Group(8, 321, 391, 24); + o->labelsize(11); + { Fl_Box* o = new Fl_Box(8, 325, 20, 20); + o->labelsize(11); + Fl_Group::current()->resizable(o); + } + { Fl_Button* o = new Fl_Button(231, 325, 99, 20, "Hide &Overlays"); + o->tooltip("Hide the widget overlay box."); + o->labelsize(11); + o->labelcolor((Fl_Color)1); + o->callback((Fl_Callback*)overlay_cb); + } + { Fl_Button* o = new Fl_Button(80, 325, 80, 20, "Revert"); + o->labelsize(11); + o->callback((Fl_Callback*)revert_cb); + o->hide(); + } + { Fl_Return_Button* o = new Fl_Return_Button(335, 325, 64, 20, "Close"); + o->labelsize(11); + o->callback((Fl_Callback*)ok_cb); + } + { Fl_Button* o = new Fl_Button(329, 325, 70, 20, "Cancel"); + o->labelsize(11); + o->callback((Fl_Callback*)cancel_cb); + o->hide(); + } + { Fl_Button* o = wLiveMode = new Fl_Button(142, 325, 84, 20, "Live &Mode"); + o->tooltip("Create a live duplicate of the selected widgets to test resizing and menu beh\ +avior."); + o->type(1); + o->labelsize(11); + o->callback((Fl_Callback*)live_mode_cb); + } + o->end(); + } + o->size_range(o->w(), o->h()); + o->end(); + } + return w; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/widget_panel.fl b/Utilities/FLTK/fluid/widget_panel.fl new file mode 100644 index 0000000000..df6da0281e --- /dev/null +++ b/Utilities/FLTK/fluid/widget_panel.fl @@ -0,0 +1,549 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +comment {// +// "$Id: widget_panel.fl 4625 2005-11-02 13:55:13Z matt $" +// +// Widget panel for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +} {in_source in_header +} + +Function {make_widget_panel()} {open +} { + Fl_Window {} {open + xywh {353 184 410 355} type Double labelsize 11 resizable hotspot + code0 {o->size_range(o->w(), o->h());} visible + } { + Fl_Tabs {} { + callback {propagate_load((Fl_Group *)o,v);} open + xywh {5 5 400 310} selection_color 4 labelsize 11 labelcolor 7 when 0 resizable + } { + Fl_Group {} { + label GUI + callback propagate_load + xywh {5 25 400 290} labelsize 11 when 0 resizable + } { + Fl_Group {} { + label {Label:} + callback propagate_load + xywh {90 35 300 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Input {} { + callback label_cb + tooltip {The label text for the widget.} xywh {90 35 180 20} labelfont 1 labelsize 11 when 1 textsize 11 resizable + } + Fl_Choice {} { + callback labeltype_cb open + tooltip {The label style for the widget.} xywh {270 35 120 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 + code0 {extern Fl_Menu_Item labeltypemenu[];} + code1 {o->menu(labeltypemenu);} + } {} + } + Fl_Group {} { + label {Image:} + callback propagate_load + xywh {90 60 300 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Input {} { + callback image_cb + tooltip {The active image for the widget.} xywh {90 60 230 20} labelfont 1 labelsize 11 textsize 11 resizable + } + Fl_Button {} { + label {Browse...} + callback image_browse_cb + tooltip {Click to choose the active image.} xywh {320 60 70 20} labelsize 11 + } + } + Fl_Group {} { + label {Inactive:} + callback propagate_load + xywh {90 85 300 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Input {} { + callback inactive_cb + tooltip {The inactive image for the widget.} xywh {90 85 230 20} labelfont 1 labelsize 11 textsize 11 resizable + } + Fl_Button {} { + label {Browse...} + callback inactive_browse_cb + tooltip {Click to choose the inactive image.} xywh {320 85 70 20} labelsize 11 + } + } + Fl_Group {} { + label {Alignment:} + callback propagate_load + xywh {90 110 300 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Button {} { + label Clip + user_data FL_ALIGN_CLIP + callback align_cb + tooltip {Clip the label to the inside of the widget.} xywh {90 110 45 20} type Toggle selection_color 8 labelsize 11 align 16 + } + Fl_Button {} { + label Wrap + user_data FL_ALIGN_WRAP + callback align_cb selected + tooltip {Wrap the label text.} xywh {140 110 50 20} type Toggle selection_color 8 labelsize 11 + } + Fl_Button {} { + label {Text/Image} + user_data FL_ALIGN_TEXT_OVER_IMAGE + callback align_cb + tooltip {Show the label text over the image.} xywh {195 110 65 20} type Toggle selection_color 8 labelsize 11 + } + Fl_Button {} { + label {@-1<-} + user_data FL_ALIGN_LEFT + callback align_cb + tooltip {Left-align the label.} xywh {265 110 20 20} type Toggle selection_color 8 labelsize 11 labelcolor 8 + } + Fl_Button {} { + label {@-1->} + user_data FL_ALIGN_RIGHT + callback align_cb + tooltip {Right-align the label.} xywh {290 110 20 20} type Toggle selection_color 8 labelsize 11 labelcolor 8 + } + Fl_Button {} { + label {@-18} + user_data FL_ALIGN_TOP + callback align_cb + tooltip {Top-align the label.} xywh {315 110 20 20} type Toggle selection_color 8 labelsize 11 labelcolor 8 + } + Fl_Button {} { + label {@-12} + user_data FL_ALIGN_BOTTOM + callback align_cb + tooltip {Bottom-align the label.} xywh {340 110 20 20} type Toggle selection_color 8 labelsize 11 labelcolor 8 + } + Fl_Button {} { + label {@-3square} + user_data FL_ALIGN_INSIDE + callback align_cb + tooltip {Show the label inside the widget.} xywh {365 110 20 20} type Toggle selection_color 8 labelsize 11 labelcolor 8 + } + Fl_Box {} { + xywh {390 110 0 20} labelsize 11 resizable + } + } + Fl_Group {} { + label {Position:} + callback propagate_load open + xywh {90 145 300 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Value_Input widget_x_input { + label {X:} + callback x_cb + tooltip {The X position of the widget.} xywh {90 145 55 20} labelsize 11 align 5 maximum 2048 step 1 textsize 11 + } + Fl_Value_Input widget_y_input { + label {Y:} + callback y_cb + tooltip {The Y position of the widget.} xywh {150 145 55 20} labelsize 11 align 5 maximum 2048 step 1 textsize 11 + } + Fl_Value_Input widget_w_input { + label {Width:} + callback w_cb + tooltip {The width of the widget.} xywh {210 145 55 20} labelsize 11 align 5 maximum 2048 step 1 textsize 11 + } + Fl_Value_Input widget_h_input { + label {Height:} + callback h_cb + tooltip {The height of the widget.} xywh {270 145 55 20} labelsize 11 align 5 maximum 2048 step 1 textsize 11 + } + Fl_Light_Button {} { + label Relative + callback wc_relative_cb + tooltip {If set, widgets inside a widget class of type Fl_Group are repositioned relative to the origin at construction time} xywh {330 145 55 20} labelsize 11 + } + Fl_Box {} { + xywh {389 145 1 20} resizable + } + } + Fl_Group {} { + label {Values:} + callback propagate_load + xywh {90 180 300 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Value_Input {} { + label {Size:} + callback slider_size_cb + tooltip {The size of the slider.} xywh {90 180 55 20} labelsize 11 align 5 step 0.010101 textsize 11 + } + Fl_Value_Input {} { + label {Minimum:} + callback min_cb + tooltip {The minimum value of the widget.} xywh {150 180 55 20} labelsize 11 align 5 textsize 11 + } + Fl_Value_Input {} { + label {Maximum:} + callback max_cb + tooltip {The maximum value of the widget.} xywh {210 180 55 20} labelsize 11 align 5 value 1 textsize 11 + } + Fl_Value_Input {} { + label {Step:} + callback step_cb + tooltip {The resolution of the widget value.} xywh {270 180 55 20} labelsize 11 align 5 textsize 11 + } + Fl_Value_Input {} { + label {Value:} + callback value_cb + tooltip {The current widget value.} xywh {330 180 55 20} labelsize 11 align 5 textsize 11 + } + Fl_Box {} { + xywh {390 180 0 20} resizable + } + } + Fl_Group {} { + label {Size Range:} + callback propagate_load + xywh {90 180 300 20} labelfont 1 labelsize 11 align 4 hide + } { + Fl_Value_Input {} { + label {Minimum Size:} + callback min_w_cb + tooltip {The size of the slider.} xywh {90 180 55 20} labelsize 11 align 5 maximum 2048 step 1 textsize 11 + } + Fl_Value_Input {} { + callback min_h_cb + tooltip {The minimum value of the widget.} xywh {150 180 55 20} labelsize 11 align 5 maximum 2048 step 1 textsize 11 + } + Fl_Button {} { + label set + callback set_min_size_cb + xywh {210 180 25 20} labelsize 11 + } + Fl_Value_Input {} { + label {Maximum Size:} + callback max_w_cb + tooltip {The maximum value of the widget.} xywh {240 180 55 20} labelsize 11 align 5 maximum 2048 step 1 textsize 11 + } + Fl_Value_Input {} { + callback max_h_cb + tooltip {The resolution of the widget value.} xywh {300 180 55 20} labelsize 11 align 5 maximum 2048 step 1 textsize 11 + } + Fl_Button {} { + label set + callback set_max_size_cb + xywh {360 180 25 20} labelsize 11 + } + Fl_Box {} { + xywh {390 180 0 20} resizable + } + } + Fl_Button {} { + label {Shortcut:} + callback shortcut_in_cb + tooltip {The shortcut key for the widget.} xywh {90 205 300 20} box DOWN_BOX color 7 selection_color 7 labelfont 1 labelsize 11 align 4 + code0 {\#include "Shortcut_Button.h"} + class Shortcut_Button + } + Fl_Group {} { + label {X Class:} + callback propagate_load + xywh {90 230 300 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Input {} { + label {:} + callback xclass_cb + tooltip {The X resource class.} xywh {90 230 95 20} labelfont 1 labelsize 11 textsize 11 resizable + } + Fl_Light_Button {} { + label Border + callback border_cb + tooltip {Add a border around the window.} xywh {190 230 60 20} selection_color 1 labelsize 11 + } + Fl_Light_Button {} { + label Modal + callback modal_cb + tooltip {Make the window modal.} xywh {255 230 55 20} selection_color 1 labelsize 11 + } + Fl_Light_Button {} { + label Nonmodal + callback non_modal_cb + tooltip {Make the window non-modal.} xywh {315 230 75 20} selection_color 1 labelsize 11 align 148 + } + } + Fl_Group {} { + label {Attributes:} + callback propagate_load + xywh {90 255 305 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Light_Button {} { + label Visible + callback visible_cb + tooltip {Show the widget.} xywh {90 255 60 20} selection_color 1 labelsize 11 + } + Fl_Light_Button {} { + label Active + callback active_cb + tooltip {Activate the widget.} xywh {155 255 60 20} selection_color 1 labelsize 11 + } + Fl_Light_Button {} { + label Resizable + callback resizable_cb + tooltip {Make the widget resizable.} xywh {220 255 75 20} selection_color 1 labelsize 11 when 1 + } + Fl_Light_Button {} { + label Hotspot + callback hotspot_cb + tooltip {Center the window under this widget.} xywh {300 255 70 20} selection_color 1 labelsize 11 when 1 + } + Fl_Box {} { + xywh {390 255 0 20} labelsize 11 resizable + } + } + Fl_Input {} { + label {Tooltip:} + callback tooltip_cb + tooltip {The tooltip text for the widget.} xywh {90 280 300 20} labelfont 1 labelsize 11 textsize 11 + } + Fl_Box {} { + xywh {90 300 300 5} labelsize 11 resizable + } + } + Fl_Group {} { + label Style + callback propagate_load + xywh {5 25 400 290} labelsize 11 when 0 hide + } { + Fl_Group {} { + label {Label Font:} + callback propagate_load open + xywh {90 35 300 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Choice {} { + callback labelfont_cb open + tooltip {The style of the label text.} xywh {90 35 160 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 resizable + code0 {extern Fl_Menu_Item fontmenu[];} + code1 {o->menu(fontmenu);} + } {} + Fl_Value_Input {} { + callback labelsize_cb + tooltip {The size of the label text.} xywh {250 35 50 20} labelsize 11 maximum 100 step 1 value 14 textsize 11 + } + Fl_Button {} { + label {Label Color} + callback labelcolor_cb + tooltip {The color of the label text.} xywh {300 35 90 20} labelsize 11 + } + } + Fl_Group {} { + label {Box:} + callback propagate_load open + xywh {90 60 300 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Choice {} { + callback box_cb open + tooltip {The "up" box of the widget.} xywh {90 60 210 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 resizable + code0 {extern Fl_Menu_Item boxmenu[];} + code1 {o->menu(boxmenu);} + } {} + Fl_Button {} { + label Color + callback color_cb + tooltip {The background color of the widget.} xywh {300 60 90 20} labelsize 11 + } + } + Fl_Group {} { + label {Down Box:} + callback propagate_load open + xywh {90 85 300 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Choice {} { + callback down_box_cb open + tooltip {The "down" box of the widget.} xywh {90 85 210 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 resizable + code0 {extern Fl_Menu_Item boxmenu[];} + code1 {o->menu(boxmenu);} + } {} + Fl_Button {} { + label {Select Color} + callback color2_cb + tooltip {The selection color of the widget.} xywh {300 85 90 20} labelsize 11 + } + } + Fl_Group {} { + label {Text Font:} + callback propagate_load open + xywh {90 110 300 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Choice {} { + callback textfont_cb open + tooltip {The value text style.} xywh {90 110 160 20} box DOWN_BOX down_box BORDER_BOX labelfont 1 labelsize 11 resizable + code0 {extern Fl_Menu_Item fontmenu[];} + code1 {o->menu(fontmenu);} + } {} + Fl_Value_Input {} { + callback textsize_cb + tooltip {The value text size.} xywh {250 110 50 20} labelsize 11 maximum 100 step 1 value 14 textsize 11 + } + Fl_Button {} { + label {Text Color} + callback textcolor_cb + tooltip {The value text color.} xywh {300 110 90 20} labelsize 11 + } + } + Fl_Box {} { + xywh {90 135 300 40} labelsize 11 resizable + } + } + Fl_Group {} { + label {C++} + callback propagate_load + xywh {5 25 400 290} labelsize 11 when 0 hide + } { + Fl_Group {} { + label {Class:} + callback propagate_load + xywh {90 35 300 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Input {} { + user_data 4 + callback subclass_cb + tooltip {The widget subclass.} xywh {90 35 160 20} labelfont 1 labelsize 11 textfont 4 textsize 11 resizable + } + Fl_Choice {} { + callback subtype_cb open + tooltip {The widget subtype.} xywh {250 35 140 20} box THIN_UP_BOX down_box BORDER_BOX labelsize 11 + } {} + } + Fl_Group {} { + label {Name:} + callback propagate_load + xywh {90 60 300 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Input {} { + callback name_cb + tooltip {The name of the widget.} xywh {90 60 240 20} labelfont 1 labelsize 11 textsize 11 resizable + } + Fl_Light_Button {} { + label public + callback name_public_cb + tooltip {Make the widget publicly accessible.} xywh {330 60 60 20} selection_color 1 labelsize 11 when 1 + } + } + Fl_Input {v_input[0]} { + label {Extra Code:} + user_data 0 + callback v_input_cb + tooltip {Extra initialization code for the widget.} xywh {90 85 300 20} labelfont 1 labelsize 11 textfont 4 textsize 11 + } + Fl_Input {v_input[1]} { + user_data 1 + callback v_input_cb + tooltip {Extra initialization code for the widget.} xywh {90 105 300 20} labelsize 11 textfont 4 textsize 11 + } + Fl_Input {v_input[2]} { + user_data 2 + callback v_input_cb + tooltip {Extra initialization code for the widget.} xywh {90 125 300 20} labelsize 11 textfont 4 textsize 11 + } + Fl_Input {v_input[3]} { + user_data 3 + callback v_input_cb + tooltip {Extra initialization code for the widget.} xywh {90 145 300 20} labelsize 11 textfont 4 textsize 11 + } + Fl_Text_Editor {} { + label {Callback:} + callback callback_cb + tooltip {The callback function or code for the widget. Use the variable name 'o' to access the Widget pointer and 'v' to access the user value.} xywh {90 170 300 90} box DOWN_BOX labelfont 1 labelsize 11 align 4 textfont 4 textsize 11 resizable + code0 {\#include "CodeEditor.h"} + class CodeEditor + } + Fl_Group {} { + label {User Data:} + callback propagate_load + xywh {90 265 300 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Input {} { + callback user_data_cb + tooltip {The user data to pass into the callback code.} xywh {90 265 140 20} labelfont 1 labelsize 11 textfont 4 textsize 11 resizable + } + Fl_Choice {} { + label {When:} + callback when_cb open + tooltip {When to call the callback function.} xywh {285 265 105 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 when 1 + code0 {extern Fl_Menu_Item whenmenu[];} + code1 {o->menu(whenmenu);} + } {} + } + Fl_Group {} { + label {Type:} + callback propagate_load + xywh {90 290 300 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Input {} { + callback user_data_type_cb + tooltip {The type of the user data.} xywh {90 290 140 20} labelfont 1 labelsize 11 textfont 4 textsize 11 resizable + } + Fl_Light_Button {} { + label {No Change} + callback when_button_cb + tooltip {Call the callback even if the value has not changed.} xywh {285 290 105 20} selection_color 1 labelsize 11 + } + } + } + } + Fl_Group {} { + xywh {8 321 391 24} labelsize 11 + } { + Fl_Box {} { + xywh {8 325 20 20} labelsize 11 resizable + } + Fl_Button {} { + label {Hide &Overlays} + callback overlay_cb + tooltip {Hide the widget overlay box.} xywh {231 325 99 20} labelsize 11 labelcolor 1 + } + Fl_Button {} { + label Revert + callback revert_cb + xywh {80 325 80 20} labelsize 11 hide + } + Fl_Return_Button {} { + label Close + callback ok_cb + xywh {335 325 64 20} labelsize 11 + } + Fl_Button {} { + label Cancel + callback cancel_cb + xywh {329 325 70 20} labelsize 11 hide + } + Fl_Button wLiveMode { + label {Live &Mode} + callback live_mode_cb + tooltip {Create a live duplicate of the selected widgets to test resizing and menu behavior.} xywh {142 325 84 20} type Toggle labelsize 11 + } + } + } +} + +comment { +// +// End of "$Id: widget_panel.fl 4625 2005-11-02 13:55:13Z matt $". +//} {in_source in_header +} diff --git a/Utilities/FLTK/fluid/widget_panel.h b/Utilities/FLTK/fluid/widget_panel.h new file mode 100644 index 0000000000..bdb7468c23 --- /dev/null +++ b/Utilities/FLTK/fluid/widget_panel.h @@ -0,0 +1,119 @@ +// +// "$Id$" +// +// Widget panel for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// generated by Fast Light User Interface Designer (fluid) version 1.0107 + +#ifndef widget_panel_h +#define widget_panel_h +#include <FL/Fl.H> +#include <FL/Fl_Double_Window.H> +#include <FL/Fl_Tabs.H> +#include <FL/Fl_Group.H> +extern void propagate_load(Fl_Group*, void*); +#include <FL/Fl_Input.H> +extern void label_cb(Fl_Input*, void*); +#include <FL/Fl_Choice.H> +extern Fl_Menu_Item labeltypemenu[]; +extern void labeltype_cb(Fl_Choice*, void*); +extern void image_cb(Fl_Input*, void*); +#include <FL/Fl_Button.H> +extern void image_browse_cb(Fl_Button*, void*); +extern void inactive_cb(Fl_Input*, void*); +extern void inactive_browse_cb(Fl_Button*, void*); +extern void align_cb(Fl_Button*, void*); +#include <FL/Fl_Box.H> +#include <FL/Fl_Value_Input.H> +extern void x_cb(Fl_Value_Input*, void*); +extern Fl_Value_Input *widget_x_input; +extern void y_cb(Fl_Value_Input*, void*); +extern Fl_Value_Input *widget_y_input; +extern void w_cb(Fl_Value_Input*, void*); +extern Fl_Value_Input *widget_w_input; +extern void h_cb(Fl_Value_Input*, void*); +extern Fl_Value_Input *widget_h_input; +#include <FL/Fl_Light_Button.H> +extern void wc_relative_cb(Fl_Light_Button*, void*); +extern void slider_size_cb(Fl_Value_Input*, void*); +extern void min_cb(Fl_Value_Input*, void*); +extern void max_cb(Fl_Value_Input*, void*); +extern void step_cb(Fl_Value_Input*, void*); +extern void value_cb(Fl_Value_Input*, void*); +extern void min_w_cb(Fl_Value_Input*, void*); +extern void min_h_cb(Fl_Value_Input*, void*); +extern void set_min_size_cb(Fl_Button*, void*); +extern void max_w_cb(Fl_Value_Input*, void*); +extern void max_h_cb(Fl_Value_Input*, void*); +extern void set_max_size_cb(Fl_Button*, void*); +#include "Shortcut_Button.h" +extern void shortcut_in_cb(Shortcut_Button*, void*); +extern void xclass_cb(Fl_Input*, void*); +extern void border_cb(Fl_Light_Button*, void*); +extern void modal_cb(Fl_Light_Button*, void*); +extern void non_modal_cb(Fl_Light_Button*, void*); +extern void visible_cb(Fl_Light_Button*, void*); +extern void active_cb(Fl_Light_Button*, void*); +extern void resizable_cb(Fl_Light_Button*, void*); +extern void hotspot_cb(Fl_Light_Button*, void*); +extern void tooltip_cb(Fl_Input*, void*); +extern Fl_Menu_Item fontmenu[]; +extern void labelfont_cb(Fl_Choice*, void*); +extern void labelsize_cb(Fl_Value_Input*, void*); +extern void labelcolor_cb(Fl_Button*, void*); +extern Fl_Menu_Item boxmenu[]; +extern void box_cb(Fl_Choice*, void*); +extern void color_cb(Fl_Button*, void*); +extern void down_box_cb(Fl_Choice*, void*); +extern void color2_cb(Fl_Button*, void*); +extern void textfont_cb(Fl_Choice*, void*); +extern void textsize_cb(Fl_Value_Input*, void*); +extern void textcolor_cb(Fl_Button*, void*); +extern void subclass_cb(Fl_Input*, void*); +extern void subtype_cb(Fl_Choice*, void*); +extern void name_cb(Fl_Input*, void*); +extern void name_public_cb(Fl_Light_Button*, void*); +extern void v_input_cb(Fl_Input*, void*); +extern Fl_Input *v_input[4]; +#include "CodeEditor.h" +extern void callback_cb(CodeEditor*, void*); +extern void user_data_cb(Fl_Input*, void*); +extern Fl_Menu_Item whenmenu[]; +extern void when_cb(Fl_Choice*, void*); +extern void user_data_type_cb(Fl_Input*, void*); +extern void when_button_cb(Fl_Light_Button*, void*); +extern void overlay_cb(Fl_Button*, void*); +extern void revert_cb(Fl_Button*, void*); +#include <FL/Fl_Return_Button.H> +extern void ok_cb(Fl_Return_Button*, void*); +extern void cancel_cb(Fl_Button*, void*); +extern void live_mode_cb(Fl_Button*, void*); +extern Fl_Button *wLiveMode; +Fl_Double_Window* make_widget_panel(); +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/fluid/x-fluid.desktop b/Utilities/FLTK/fluid/x-fluid.desktop new file mode 100644 index 0000000000..994e6443cb --- /dev/null +++ b/Utilities/FLTK/fluid/x-fluid.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Type=MimeType +MimeType=application/x-fluid +Icon=fluid.png +Patterns=*.fl +Name=FLUID +Comment=FLUID GUI Design +Encoding=UTF-8 diff --git a/Utilities/FLTK/forms.h b/Utilities/FLTK/forms.h new file mode 100644 index 0000000000..967b24b67c --- /dev/null +++ b/Utilities/FLTK/forms.h @@ -0,0 +1,3 @@ +// this file allows some forms programs to be compiled with no change. +// put it in your include path. +#include <FL/forms.H> diff --git a/Utilities/FLTK/jpeg/CMakeLists.txt b/Utilities/FLTK/jpeg/CMakeLists.txt new file mode 100644 index 0000000000..eb05c48a3d --- /dev/null +++ b/Utilities/FLTK/jpeg/CMakeLists.txt @@ -0,0 +1,36 @@ +PROJECT(FLTKJPEG) + +INCLUDE_REGULAR_EXPRESSION("^(jchuff|jconfig|jdct|jdhuff|jerror|jinclude|jmemsys|jmorecfg|jpegint|jpeglib|jversion|jpeg).*$") + +INCLUDE_DIRECTORIES(${FLTKJPEG_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${FLTKJPEG_BINARY_DIR}) + +# memmgr back ends: compile only one of these into a working library +# (For now, let's use the mode that requires the image fit into memory. +# This is the recommended mode for Win32 anyway.) +SET(systemdependent_SRCS jmemnobs.c) + +# library object files common to compression and decompression +SET(common_SRCS +jcomapi.c jutils.c jerror.c jmemmgr.c +) + +# compression library object files +SET(compression_SRCS +jcapimin.c jcapistd.c jctrans.c jcparam.c jdatadst.c jcinit.c +jcmaster.c jcmarker.c jcmainct.c jcprepct.c jccoefct.c jccolor.c +jcsample.c jchuff.c jcphuff.c jcdctmgr.c jfdctfst.c jfdctflt.c +jfdctint.c +) + +# decompression library object files +SET(decompression_SRCS +jdapimin.c jdapistd.c jdtrans.c jdatasrc.c jdmaster.c +jdinput.c jdmarker.c jdhuff.c jdphuff.c jdmainct.c jdcoefct.c +jdpostct.c jddctmgr.c jidctfst.c jidctflt.c jidctint.c jidctred.c +jdsample.c jdcolor.c jquant1.c jquant2.c jdmerge.c +) + +ADD_LIBRARY(fltk_jpeg ${systemdependent_SRCS} ${common_SRCS} ${compression_SRCS} ${decompression_SRCS}) +INSTALL_TARGETS(/lib fltk_jpeg) + diff --git a/Utilities/FLTK/jpeg/Makefile b/Utilities/FLTK/jpeg/Makefile new file mode 100644 index 0000000000..715d9cd3c1 --- /dev/null +++ b/Utilities/FLTK/jpeg/Makefile @@ -0,0 +1,116 @@ +# +# "$Id: Makefile 4058 2005-02-28 00:11:07Z mike $" +# +# JPEG library makefile for the Fast Light Toolkit (FLTK). +# +# Copyright 1997-2005 by Easy Software Products. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. +# +# Please report all bugs and problems to "fltk-bugs@fltk.org". +# + +include ../makeinclude + + +# +# Object files... +# + +OBJS = jmemnobs.o \ + jcapimin.o jcapistd.o jccoefct.o jccolor.o jcdctmgr.o \ + jchuff.o jcinit.o jcmainct.o jcmarker.o jcmaster.o jcomapi.o \ + jcparam.o jcphuff.o jcprepct.o jcsample.o jctrans.o \ + jdapimin.o jdapistd.o jdatadst.o jdatasrc.o jdcoefct.o \ + jdcolor.o jddctmgr.o jdhuff.o jdinput.o jdmainct.o jdmarker.o \ + jdmaster.o jdmerge.o jdphuff.o jdpostct.o jdsample.o \ + jdtrans.o jerror.o jfdctflt.o jfdctfst.o jfdctint.o \ + jidctflt.o jidctfst.o jidctint.o jidctred.o jquant1.o \ + jquant2.o jutils.o jmemmgr.o + +LIBJPEG = ../lib/libfltk_jpeg$(LIBEXT) + + +# +# Make all targets... +# + +all: $(LIBJPEG) + + +# +# Clean all targets and object files... +# + +clean: + $(RM) $(OBJS) + $(RM) $(LIBJPEG) + + +# +# Install everything... +# + +install: + echo "Installing libfltk_jpeg$(LIBEXT) in $(libdir)..." + -$(MKDIR) $(libdir) + $(RM) $(libdir)/libfltk_jpeg$(LIBEXT) + $(CP) $(LIBJPEG) $(libdir) + $(RANLIB) $(libdir)/libfltk_jpeg$(LIBEXT) + echo "Installing jpeg headers in $(includedir)/FL/images..." + -$(MKDIR) $(includedir)/FL/images + $(CP) jconfig.h jerror.h jmorecfg.h jpeglib.h $(includedir)/FL/images + + +# +# Uninstall everything... +# + +uninstall: + echo "Uninstalling libfltk_jpeg$(LIBEXT) in $(libdir)..." + $(RM) $(libdir)/libfltk_jpeg$(LIBEXT) + echo "Uninstalling jpeg headers in $(includedir)/FL/images..." + $(RM) $(includedir)/FL/images/jconfig.h + $(RM) $(includedir)/FL/images/jerror.h + $(RM) $(includedir)/FL/images/jmorecfg.h + $(RM) $(includedir)/FL/images/jpeglib.h + + +# +# libfltk_jpeg.a +# + +$(LIBJPEG): $(OBJS) + echo Archiving $@... + $(RM) $@ + $(LIBCOMMAND) $@ $(OBJS) + $(RANLIB) $@ + + +# +# Make dependencies... +# + +depend: $(OBJS:.o=.c) + makedepend -Y -I.. -f makedepend $(OBJS:.o=.c) + +include makedepend + +$(OBJS): ../makeinclude + +# +# End of "$Id: Makefile 4058 2005-02-28 00:11:07Z mike $". +# diff --git a/Utilities/FLTK/jpeg/README b/Utilities/FLTK/jpeg/README new file mode 100644 index 0000000000..86cc20669d --- /dev/null +++ b/Utilities/FLTK/jpeg/README @@ -0,0 +1,385 @@ +The Independent JPEG Group's JPEG software +========================================== + +README for release 6b of 27-Mar-1998 +==================================== + +This distribution contains the sixth public release of the Independent JPEG +Group's free JPEG software. You are welcome to redistribute this software and +to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. + +Serious users of this software (particularly those incorporating it into +larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to +our electronic mailing list. Mailing list members are notified of updates +and have a chance to participate in technical discussions, etc. + +This software is the work of Tom Lane, Philip Gladstone, Jim Boucher, +Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, +Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG +Group. + +IJG is not affiliated with the official ISO JPEG standards committee. + + +DOCUMENTATION ROADMAP +===================== + +This file contains the following sections: + +OVERVIEW General description of JPEG and the IJG software. +LEGAL ISSUES Copyright, lack of warranty, terms of distribution. +REFERENCES Where to learn more about JPEG. +ARCHIVE LOCATIONS Where to find newer versions of this software. +RELATED SOFTWARE Other stuff you should get. +FILE FORMAT WARS Software *not* to get. +TO DO Plans for future IJG releases. + +Other documentation files in the distribution are: + +User documentation: + install.doc How to configure and install the IJG software. + usage.doc Usage instructions for cjpeg, djpeg, jpegtran, + rdjpgcom, and wrjpgcom. + *.1 Unix-style man pages for programs (same info as usage.doc). + wizard.doc Advanced usage instructions for JPEG wizards only. + change.log Version-to-version change highlights. +Programmer and internal documentation: + libjpeg.doc How to use the JPEG library in your own programs. + example.c Sample code for calling the JPEG library. + structure.doc Overview of the JPEG library's internal structure. + filelist.doc Road map of IJG files. + coderules.doc Coding style rules --- please read if you contribute code. + +Please read at least the files install.doc and usage.doc. Useful information +can also be found in the JPEG FAQ (Frequently Asked Questions) article. See +ARCHIVE LOCATIONS below to find out where to obtain the FAQ article. + +If you want to understand how the JPEG code works, we suggest reading one or +more of the REFERENCES, then looking at the documentation files (in roughly +the order listed) before diving into the code. + + +OVERVIEW +======== + +This package contains C software to implement JPEG image compression and +decompression. JPEG (pronounced "jay-peg") is a standardized compression +method for full-color and gray-scale images. JPEG is intended for compressing +"real-world" scenes; line drawings, cartoons and other non-realistic images +are not its strong suit. JPEG is lossy, meaning that the output image is not +exactly identical to the input image. Hence you must not use JPEG if you +have to have identical output bits. However, on typical photographic images, +very good compression levels can be obtained with no visible change, and +remarkably high compression levels are possible if you can tolerate a +low-quality image. For more details, see the references, or just experiment +with various compression settings. + +This software implements JPEG baseline, extended-sequential, and progressive +compression processes. Provision is made for supporting all variants of these +processes, although some uncommon parameter settings aren't implemented yet. +For legal reasons, we are not distributing code for the arithmetic-coding +variants of JPEG; see LEGAL ISSUES. We have made no provision for supporting +the hierarchical or lossless processes defined in the standard. + +We provide a set of library routines for reading and writing JPEG image files, +plus two sample applications "cjpeg" and "djpeg", which use the library to +perform conversion between JPEG and some other popular image file formats. +The library is intended to be reused in other applications. + +In order to support file conversion and viewing software, we have included +considerable functionality beyond the bare JPEG coding/decoding capability; +for example, the color quantization modules are not strictly part of JPEG +decoding, but they are essential for output to colormapped file formats or +colormapped displays. These extra functions can be compiled out of the +library if not required for a particular application. We have also included +"jpegtran", a utility for lossless transcoding between different JPEG +processes, and "rdjpgcom" and "wrjpgcom", two simple applications for +inserting and extracting textual comments in JFIF files. + +The emphasis in designing this software has been on achieving portability and +flexibility, while also making it fast enough to be useful. In particular, +the software is not intended to be read as a tutorial on JPEG. (See the +REFERENCES section for introductory material.) Rather, it is intended to +be reliable, portable, industrial-strength code. We do not claim to have +achieved that goal in every aspect of the software, but we strive for it. + +We welcome the use of this software as a component of commercial products. +No royalty is required, but we do ask for an acknowledgement in product +documentation, as described under LEGAL ISSUES. + + +LEGAL ISSUES +============ + +In plain English: + +1. We don't promise that this software works. (But if you find any bugs, + please let us know!) +2. You can use this software for whatever you want. You don't have to pay us. +3. You may not pretend that you wrote this software. If you use it in a + program, you must acknowledge somewhere in your documentation that + you've used the IJG code. + +In legalese: + +The authors make NO WARRANTY or representation, either express or implied, +with respect to this software, its quality, accuracy, merchantability, or +fitness for a particular purpose. This software is provided "AS IS", and you, +its user, assume the entire risk as to its quality and accuracy. + +This software is copyright (C) 1991-1998, Thomas G. Lane. +All Rights Reserved except as specified below. + +Permission is hereby granted to use, copy, modify, and distribute this +software (or portions thereof) for any purpose, without fee, subject to these +conditions: +(1) If any part of the source code for this software is distributed, then this +README file must be included, with this copyright and no-warranty notice +unaltered; and any additions, deletions, or changes to the original files +must be clearly indicated in accompanying documentation. +(2) If only executable code is distributed, then the accompanying +documentation must state that "this software is based in part on the work of +the Independent JPEG Group". +(3) Permission for use of this software is granted only if the user accepts +full responsibility for any undesirable consequences; the authors accept +NO LIABILITY for damages of any kind. + +These conditions apply to any software derived from or based on the IJG code, +not just to the unmodified library. If you use our work, you ought to +acknowledge us. + +Permission is NOT granted for the use of any IJG author's name or company name +in advertising or publicity relating to this software or products derived from +it. This software may be referred to only as "the Independent JPEG Group's +software". + +We specifically permit and encourage the use of this software as the basis of +commercial products, provided that all warranty or liability claims are +assumed by the product vendor. + + +ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, +sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. +ansi2knr.c is NOT covered by the above copyright and conditions, but instead +by the usual distribution terms of the Free Software Foundation; principally, +that you must include source code if you redistribute it. (See the file +ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part +of any program generated from the IJG code, this does not limit you more than +the foregoing paragraphs do. + +The Unix configuration script "configure" was produced with GNU Autoconf. +It is copyright by the Free Software Foundation but is freely distributable. +The same holds for its supporting scripts (config.guess, config.sub, +ltconfig, ltmain.sh). Another support script, install-sh, is copyright +by M.I.T. but is also freely distributable. + +It appears that the arithmetic coding option of the JPEG spec is covered by +patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot +legally be used without obtaining one or more licenses. For this reason, +support for arithmetic coding has been removed from the free JPEG software. +(Since arithmetic coding provides only a marginal gain over the unpatented +Huffman mode, it is unlikely that very many implementations will support it.) +So far as we are aware, there are no patent restrictions on the remaining +code. + +The IJG distribution formerly included code to read and write GIF files. +To avoid entanglement with the Unisys LZW patent, GIF reading support has +been removed altogether, and the GIF writer has been simplified to produce +"uncompressed GIFs". This technique does not use the LZW algorithm; the +resulting GIF files are larger than usual, but are readable by all standard +GIF decoders. + +We are required to state that + "The Graphics Interchange Format(c) is the Copyright property of + CompuServe Incorporated. GIF(sm) is a Service Mark property of + CompuServe Incorporated." + + +REFERENCES +========== + +We highly recommend reading one or more of these references before trying to +understand the innards of the JPEG software. + +The best short technical introduction to the JPEG compression algorithm is + Wallace, Gregory K. "The JPEG Still Picture Compression Standard", + Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. +(Adjacent articles in that issue discuss MPEG motion picture compression, +applications of JPEG, and related topics.) If you don't have the CACM issue +handy, a PostScript file containing a revised version of Wallace's article is +available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz. The file (actually +a preprint for an article that appeared in IEEE Trans. Consumer Electronics) +omits the sample images that appeared in CACM, but it includes corrections +and some added material. Note: the Wallace article is copyright ACM and IEEE, +and it may not be used for commercial purposes. + +A somewhat less technical, more leisurely introduction to JPEG can be found in +"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by +M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides +good explanations and example C code for a multitude of compression methods +including JPEG. It is an excellent source if you are comfortable reading C +code but don't know much about data compression in general. The book's JPEG +sample code is far from industrial-strength, but when you are ready to look +at a full implementation, you've got one here... + +The best full description of JPEG is the textbook "JPEG Still Image Data +Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published +by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp. +The book includes the complete text of the ISO JPEG standards (DIS 10918-1 +and draft DIS 10918-2). This is by far the most complete exposition of JPEG +in existence, and we highly recommend it. + +The JPEG standard itself is not available electronically; you must order a +paper copy through ISO or ITU. (Unless you feel a need to own a certified +official copy, we recommend buying the Pennebaker and Mitchell book instead; +it's much cheaper and includes a great deal of useful explanatory material.) +In the USA, copies of the standard may be ordered from ANSI Sales at (212) +642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI +doesn't take credit card orders, but Global does.) It's not cheap: as of +1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7% +shipping/handling. The standard is divided into two parts, Part 1 being the +actual specification, while Part 2 covers compliance testing methods. Part 1 +is titled "Digital Compression and Coding of Continuous-tone Still Images, +Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS +10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of +Continuous-tone Still Images, Part 2: Compliance testing" and has document +numbers ISO/IEC IS 10918-2, ITU-T T.83. + +Some extensions to the original JPEG standard are defined in JPEG Part 3, +a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84. IJG +currently does not support any Part 3 extensions. + +The JPEG standard does not specify all details of an interchangeable file +format. For the omitted details we follow the "JFIF" conventions, revision +1.02. A copy of the JFIF spec is available from: + Literature Department + C-Cube Microsystems, Inc. + 1778 McCarthy Blvd. + Milpitas, CA 95035 + phone (408) 944-6300, fax (408) 944-6314 +A PostScript version of this document is available by FTP at +ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text +version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing +the figures. + +The TIFF 6.0 file format specification can be obtained by FTP from +ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme +found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems. +IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6). +Instead, we recommend the JPEG design proposed by TIFF Technical Note #2 +(Compression tag 7). Copies of this Note can be obtained from ftp.sgi.com or +from ftp://ftp.uu.net/graphics/jpeg/. It is expected that the next revision +of the TIFF spec will replace the 6.0 JPEG design with the Note's design. +Although IJG's own code does not support TIFF/JPEG, the free libtiff library +uses our library to implement TIFF/JPEG per the Note. libtiff is available +from ftp://ftp.sgi.com/graphics/tiff/. + + +ARCHIVE LOCATIONS +================= + +The "official" archive site for this software is ftp.uu.net (Internet +address 192.48.96.9). The most recent released version can always be found +there in directory graphics/jpeg. This particular version will be archived +as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. If you don't have +direct Internet access, UUNET's archives are also available via UUCP; contact +help@uunet.uu.net for information on retrieving files that way. + +Numerous Internet sites maintain copies of the UUNET files. However, only +ftp.uu.net is guaranteed to have the latest official version. + +You can also obtain this software in DOS-compatible "zip" archive format from +the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or +on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12 +"JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net +release. + +The JPEG FAQ (Frequently Asked Questions) article is a useful source of +general information about JPEG. It is updated constantly and therefore is +not included in this distribution. The FAQ is posted every two weeks to +Usenet newsgroups comp.graphics.misc, news.answers, and other groups. +It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/ +and other news.answers archive sites, including the official news.answers +archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/. +If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu +with body + send usenet/news.answers/jpeg-faq/part1 + send usenet/news.answers/jpeg-faq/part2 + + +RELATED SOFTWARE +================ + +Numerous viewing and image manipulation programs now support JPEG. (Quite a +few of them use this library to do so.) The JPEG FAQ described above lists +some of the more popular free and shareware viewers, and tells where to +obtain them on Internet. + +If you are on a Unix machine, we highly recommend Jef Poskanzer's free +PBMPLUS software, which provides many useful operations on PPM-format image +files. In particular, it can convert PPM images to and from a wide range of +other formats, thus making cjpeg/djpeg considerably more useful. The latest +version is distributed by the NetPBM group, and is available from numerous +sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/. +Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is; +you are likely to have difficulty making it work on any non-Unix machine. + +A different free JPEG implementation, written by the PVRG group at Stanford, +is available from ftp://havefun.stanford.edu/pub/jpeg/. This program +is designed for research and experimentation rather than production use; +it is slower, harder to use, and less portable than the IJG code, but it +is easier to read and modify. Also, the PVRG code supports lossless JPEG, +which we do not. (On the other hand, it doesn't do progressive JPEG.) + + +FILE FORMAT WARS +================ + +Some JPEG programs produce files that are not compatible with our library. +The root of the problem is that the ISO JPEG committee failed to specify a +concrete file format. Some vendors "filled in the blanks" on their own, +creating proprietary formats that no one else could read. (For example, none +of the early commercial JPEG implementations for the Macintosh were able to +exchange compressed files.) + +The file format we have adopted is called JFIF (see REFERENCES). This format +has been agreed to by a number of major commercial JPEG vendors, and it has +become the de facto standard. JFIF is a minimal or "low end" representation. +We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF +Technical Note #2) for "high end" applications that need to record a lot of +additional data about an image. TIFF/JPEG is fairly new and not yet widely +supported, unfortunately. + +The upcoming JPEG Part 3 standard defines a file format called SPIFF. +SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should +be able to read the most common variant of SPIFF. SPIFF has some technical +advantages over JFIF, but its major claim to fame is simply that it is an +official standard rather than an informal one. At this point it is unclear +whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto +standard. IJG intends to support SPIFF once the standard is frozen, but we +have not decided whether it should become our default output format or not. +(In any case, our decoder will remain capable of reading JFIF indefinitely.) + +Various proprietary file formats incorporating JPEG compression also exist. +We have little or no sympathy for the existence of these formats. Indeed, +one of the original reasons for developing this free software was to help +force convergence on common, open format standards for JPEG files. Don't +use a proprietary file format! + + +TO DO +===== + +The major thrust for v7 will probably be improvement of visual quality. +The current method for scaling the quantization tables is known not to be +very good at low Q values. We also intend to investigate block boundary +smoothing, "poor man's variable quantization", and other means of improving +quality-vs-file-size performance without sacrificing compatibility. + +In future versions, we are considering supporting some of the upcoming JPEG +Part 3 extensions --- principally, variable quantization and the SPIFF file +format. + +As always, speeding things up is of great interest. + +Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net. diff --git a/Utilities/FLTK/jpeg/coderules.doc b/Utilities/FLTK/jpeg/coderules.doc new file mode 100644 index 0000000000..0ab5d9bd30 --- /dev/null +++ b/Utilities/FLTK/jpeg/coderules.doc @@ -0,0 +1,118 @@ +IJG JPEG LIBRARY: CODING RULES + +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. + + +Since numerous people will be contributing code and bug fixes, it's important +to establish a common coding style. The goal of using similar coding styles +is much more important than the details of just what that style is. + +In general we follow the recommendations of "Recommended C Style and Coding +Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and +Brader). This document is available in the IJG FTP archive (see +jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl). + +Block comments should be laid out thusly: + +/* + * Block comments in this style. + */ + +We indent statements in K&R style, e.g., + if (test) { + then-part; + } else { + else-part; + } +with two spaces per indentation level. (This indentation convention is +handled automatically by GNU Emacs and many other text editors.) + +Multi-word names should be written in lower case with underscores, e.g., +multi_word_name (not multiWordName). Preprocessor symbols and enum constants +are similar but upper case (MULTI_WORD_NAME). Names should be unique within +the first fifteen characters. (On some older systems, global names must be +unique within six characters. We accommodate this without cluttering the +source code by using macros to substitute shorter names.) + +We use function prototypes everywhere; we rely on automatic source code +transformation to feed prototype-less C compilers. Transformation is done +by the simple and portable tool 'ansi2knr.c' (courtesy of Ghostscript). +ansi2knr is not very bright, so it imposes a format requirement on function +declarations: the function name MUST BEGIN IN COLUMN 1. Thus all functions +should be written in the following style: + +LOCAL(int *) +function_name (int a, char *b) +{ + code... +} + +Note that each function definition must begin with GLOBAL(type), LOCAL(type), +or METHODDEF(type). These macros expand to "static type" or just "type" as +appropriate. They provide a readable indication of the routine's usage and +can readily be changed for special needs. (For instance, special linkage +keywords can be inserted for use in Windows DLLs.) + +ansi2knr does not transform method declarations (function pointers in +structs). We handle these with a macro JMETHOD, defined as + #ifdef HAVE_PROTOTYPES + #define JMETHOD(type,methodname,arglist) type (*methodname) arglist + #else + #define JMETHOD(type,methodname,arglist) type (*methodname) () + #endif +which is used like this: + struct function_pointers { + JMETHOD(void, init_entropy_encoder, (int somearg, jparms *jp)); + JMETHOD(void, term_entropy_encoder, (void)); + }; +Note the set of parentheses surrounding the parameter list. + +A similar solution is used for forward and external function declarations +(see the EXTERN and JPP macros). + +If the code is to work on non-ANSI compilers, we cannot rely on a prototype +declaration to coerce actual parameters into the right types. Therefore, use +explicit casts on actual parameters whenever the actual parameter type is not +identical to the formal parameter. Beware of implicit conversions to "int". + +It seems there are some non-ANSI compilers in which the sizeof() operator +is defined to return int, yet size_t is defined as long. Needless to say, +this is brain-damaged. Always use the SIZEOF() macro in place of sizeof(), +so that the result is guaranteed to be of type size_t. + + +The JPEG library is intended to be used within larger programs. Furthermore, +we want it to be reentrant so that it can be used by applications that process +multiple images concurrently. The following rules support these requirements: + +1. Avoid direct use of file I/O, "malloc", error report printouts, etc; +pass these through the common routines provided. + +2. Minimize global namespace pollution. Functions should be declared static +wherever possible. (Note that our method-based calling conventions help this +a lot: in many modules only the initialization function will ever need to be +called directly, so only that function need be externally visible.) All +global function names should begin with "jpeg_", and should have an +abbreviated name (unique in the first six characters) substituted by macro +when NEED_SHORT_EXTERNAL_NAMES is set. + +3. Don't use global variables; anything that must be used in another module +should be in the common data structures. + +4. Don't use static variables except for read-only constant tables. Variables +that should be private to a module can be placed into private structures (see +the system architecture document, structure.doc). + +5. Source file names should begin with "j" for files that are part of the +library proper; source files that are not part of the library, such as cjpeg.c +and djpeg.c, do not begin with "j". Keep source file names to eight +characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers. Keep +compression and decompression code in separate source files --- some +applications may want only one half of the library. + +Note: these rules (particularly #4) are not followed religiously in the +modules that are used in cjpeg/djpeg but are not part of the JPEG library +proper. Those modules are not really intended to be used in other +applications. diff --git a/Utilities/FLTK/jpeg/filelist.doc b/Utilities/FLTK/jpeg/filelist.doc new file mode 100644 index 0000000000..e14982ca55 --- /dev/null +++ b/Utilities/FLTK/jpeg/filelist.doc @@ -0,0 +1,210 @@ +IJG JPEG LIBRARY: FILE LIST + +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. + + +Here is a road map to the files in the IJG JPEG distribution. The +distribution includes the JPEG library proper, plus two application +programs ("cjpeg" and "djpeg") which use the library to convert JPEG +files to and from some other popular image formats. A third application +"jpegtran" uses the library to do lossless conversion between different +variants of JPEG. There are also two stand-alone applications, +"rdjpgcom" and "wrjpgcom". + + +THE JPEG LIBRARY +================ + +Include files: + +jpeglib.h JPEG library's exported data and function declarations. +jconfig.h Configuration declarations. Note: this file is not present + in the distribution; it is generated during installation. +jmorecfg.h Additional configuration declarations; need not be changed + for a standard installation. +jerror.h Declares JPEG library's error and trace message codes. +jinclude.h Central include file used by all IJG .c files to reference + system include files. +jpegint.h JPEG library's internal data structures. +jchuff.h Private declarations for Huffman encoder modules. +jdhuff.h Private declarations for Huffman decoder modules. +jdct.h Private declarations for forward & reverse DCT subsystems. +jmemsys.h Private declarations for memory management subsystem. +jversion.h Version information. + +Applications using the library should include jpeglib.h (which in turn +includes jconfig.h and jmorecfg.h). Optionally, jerror.h may be included +if the application needs to reference individual JPEG error codes. The +other include files are intended for internal use and would not normally +be included by an application program. (cjpeg/djpeg/etc do use jinclude.h, +since its function is to improve portability of the whole IJG distribution. +Most other applications will directly include the system include files they +want, and hence won't need jinclude.h.) + + +C source code files: + +These files contain most of the functions intended to be called directly by +an application program: + +jcapimin.c Application program interface: core routines for compression. +jcapistd.c Application program interface: standard compression. +jdapimin.c Application program interface: core routines for decompression. +jdapistd.c Application program interface: standard decompression. +jcomapi.c Application program interface routines common to compression + and decompression. +jcparam.c Compression parameter setting helper routines. +jctrans.c API and library routines for transcoding compression. +jdtrans.c API and library routines for transcoding decompression. + +Compression side of the library: + +jcinit.c Initialization: determines which other modules to use. +jcmaster.c Master control: setup and inter-pass sequencing logic. +jcmainct.c Main buffer controller (preprocessor => JPEG compressor). +jcprepct.c Preprocessor buffer controller. +jccoefct.c Buffer controller for DCT coefficient buffer. +jccolor.c Color space conversion. +jcsample.c Downsampling. +jcdctmgr.c DCT manager (DCT implementation selection & control). +jfdctint.c Forward DCT using slow-but-accurate integer method. +jfdctfst.c Forward DCT using faster, less accurate integer method. +jfdctflt.c Forward DCT using floating-point arithmetic. +jchuff.c Huffman entropy coding for sequential JPEG. +jcphuff.c Huffman entropy coding for progressive JPEG. +jcmarker.c JPEG marker writing. +jdatadst.c Data destination manager for stdio output. + +Decompression side of the library: + +jdmaster.c Master control: determines which other modules to use. +jdinput.c Input controller: controls input processing modules. +jdmainct.c Main buffer controller (JPEG decompressor => postprocessor). +jdcoefct.c Buffer controller for DCT coefficient buffer. +jdpostct.c Postprocessor buffer controller. +jdmarker.c JPEG marker reading. +jdhuff.c Huffman entropy decoding for sequential JPEG. +jdphuff.c Huffman entropy decoding for progressive JPEG. +jddctmgr.c IDCT manager (IDCT implementation selection & control). +jidctint.c Inverse DCT using slow-but-accurate integer method. +jidctfst.c Inverse DCT using faster, less accurate integer method. +jidctflt.c Inverse DCT using floating-point arithmetic. +jidctred.c Inverse DCTs with reduced-size outputs. +jdsample.c Upsampling. +jdcolor.c Color space conversion. +jdmerge.c Merged upsampling/color conversion (faster, lower quality). +jquant1.c One-pass color quantization using a fixed-spacing colormap. +jquant2.c Two-pass color quantization using a custom-generated colormap. + Also handles one-pass quantization to an externally given map. +jdatasrc.c Data source manager for stdio input. + +Support files for both compression and decompression: + +jerror.c Standard error handling routines (application replaceable). +jmemmgr.c System-independent (more or less) memory management code. +jutils.c Miscellaneous utility routines. + +jmemmgr.c relies on a system-dependent memory management module. The IJG +distribution includes the following implementations of the system-dependent +module: + +jmemnobs.c "No backing store": assumes adequate virtual memory exists. +jmemansi.c Makes temporary files with ANSI-standard routine tmpfile(). +jmemname.c Makes temporary files with program-generated file names. +jmemdos.c Custom implementation for MS-DOS (16-bit environment only): + can use extended and expanded memory as well as temp files. +jmemmac.c Custom implementation for Apple Macintosh. + +Exactly one of the system-dependent modules should be configured into an +installed JPEG library (see install.doc for hints about which one to use). +On unusual systems you may find it worthwhile to make a special +system-dependent memory manager. + + +Non-C source code files: + +jmemdosa.asm 80x86 assembly code support for jmemdos.c; used only in + MS-DOS-specific configurations of the JPEG library. + + +CJPEG/DJPEG/JPEGTRAN +==================== + +Include files: + +cdjpeg.h Declarations shared by cjpeg/djpeg/jpegtran modules. +cderror.h Additional error and trace message codes for cjpeg et al. +transupp.h Declarations for jpegtran support routines in transupp.c. + +C source code files: + +cjpeg.c Main program for cjpeg. +djpeg.c Main program for djpeg. +jpegtran.c Main program for jpegtran. +cdjpeg.c Utility routines used by all three programs. +rdcolmap.c Code to read a colormap file for djpeg's "-map" switch. +rdswitch.c Code to process some of cjpeg's more complex switches. + Also used by jpegtran. +transupp.c Support code for jpegtran: lossless image manipulations. + +Image file reader modules for cjpeg: + +rdbmp.c BMP file input. +rdgif.c GIF file input (now just a stub). +rdppm.c PPM/PGM file input. +rdrle.c Utah RLE file input. +rdtarga.c Targa file input. + +Image file writer modules for djpeg: + +wrbmp.c BMP file output. +wrgif.c GIF file output (a mere shadow of its former self). +wrppm.c PPM/PGM file output. +wrrle.c Utah RLE file output. +wrtarga.c Targa file output. + + +RDJPGCOM/WRJPGCOM +================= + +C source code files: + +rdjpgcom.c Stand-alone rdjpgcom application. +wrjpgcom.c Stand-alone wrjpgcom application. + +These programs do not depend on the IJG library. They do use +jconfig.h and jinclude.h, only to improve portability. + + +ADDITIONAL FILES +================ + +Documentation (see README for a guide to the documentation files): + +README Master documentation file. +*.doc Other documentation files. +*.1 Documentation in Unix man page format. +change.log Version-to-version change highlights. +example.c Sample code for calling JPEG library. + +Configuration/installation files and programs (see install.doc for more info): + +configure Unix shell script to perform automatic configuration. +ltconfig Support scripts for configure (from GNU libtool). +ltmain.sh +config.guess +config.sub +install-sh Install shell script for those Unix systems lacking one. +ckconfig.c Program to generate jconfig.h on non-Unix systems. +jconfig.doc Template for making jconfig.h by hand. +makefile.* Sample makefiles for particular systems. +jconfig.* Sample jconfig.h for particular systems. +ansi2knr.c De-ANSIfier for pre-ANSI C compilers (courtesy of + L. Peter Deutsch and Aladdin Enterprises). + +Test files (see install.doc for test procedure): + +test*.* Source and comparison files for confidence test. + These are binary image files, NOT text files. diff --git a/Utilities/FLTK/jpeg/jcapimin.c b/Utilities/FLTK/jpeg/jcapimin.c new file mode 100644 index 0000000000..54fb8c58c5 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jcapistd.c b/Utilities/FLTK/jpeg/jcapistd.c new file mode 100644 index 0000000000..c0320b1b19 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jccoefct.c b/Utilities/FLTK/jpeg/jccoefct.c new file mode 100644 index 0000000000..1963ddb61b --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jccolor.c b/Utilities/FLTK/jpeg/jccolor.c new file mode 100644 index 0000000000..0a8a4b5d13 --- /dev/null +++ b/Utilities/FLTK/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<<SCALEBITS) + 0.5)) + +/* We allocate one big table and divide it up into eight parts, instead of + * doing eight alloc_small requests. This lets us use a single table base + * address, which can be held in a register in the inner loops on many + * machines (more than can hold all eight addresses, anyway). + */ + +#define R_Y_OFF 0 /* offset to R => 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/Utilities/FLTK/jpeg/jcdctmgr.c b/Utilities/FLTK/jpeg/jcdctmgr.c new file mode 100644 index 0000000000..61fa79b9e6 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jchuff.c b/Utilities/FLTK/jpeg/jchuff.c new file mode 100644 index 0000000000..f235250548 --- /dev/null +++ b/Utilities/FLTK/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)<<size) - 1; /* mask off any extra bits in code */ + + put_bits += size; /* new number of bits in buffer */ + + put_buffer <<= 24 - put_bits; /* align incoming bits */ + + put_buffer |= state->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] -= 2; /* remove two symbols */ + bits[i-1]++; /* one goes in this length */ + bits[j+1] += 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/Utilities/FLTK/jpeg/jchuff.h b/Utilities/FLTK/jpeg/jchuff.h new file mode 100644 index 0000000000..a9599fc1e6 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jcinit.c b/Utilities/FLTK/jpeg/jcinit.c new file mode 100644 index 0000000000..5efffe3316 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jcmainct.c b/Utilities/FLTK/jpeg/jcmainct.c new file mode 100644 index 0000000000..a0d82683f4 --- /dev/null +++ b/Utilities/FLTK/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 jmain = (my_main_ptr) cinfo->main; + + /* Do nothing in raw-data mode. */ + if (cinfo->raw_data_in) + return; + + jmain->cur_iMCU_row = 0; /* initialize counters */ + jmain->rowgroup_ctr = 0; + jmain->suspended = FALSE; + jmain->pass_mode = pass_mode; /* save mode for use by process_data */ + + switch (pass_mode) { + case JBUF_PASS_THRU: +#ifdef FULL_MAIN_BUFFER_SUPPORTED + if (jmain->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + jmain->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 (jmain->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + jmain->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 jmain = (my_main_ptr) cinfo->main; + + while (jmain->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Read input data if we haven't filled the main buffer yet */ + if (jmain->rowgroup_ctr < DCTSIZE) + (*cinfo->prep->pre_process_data) (cinfo, + input_buf, in_row_ctr, in_rows_avail, + jmain->buffer, &jmain->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 (jmain->rowgroup_ctr != DCTSIZE) + return; + + /* Send the completed row to the compressor */ + if (! (*cinfo->coef->compress_data) (cinfo, jmain->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 (! jmain->suspended) { + (*in_row_ctr)--; + jmain->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 (jmain->suspended) { + (*in_row_ctr)++; + jmain->suspended = FALSE; + } + jmain->rowgroup_ctr = 0; + jmain->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 jmain = (my_main_ptr) cinfo->main; + int ci; + jpeg_component_info *compptr; + boolean writing = (jmain->pass_mode != JBUF_CRANK_DEST); + + while (jmain->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Realign the virtual buffers if at the start of an iMCU row. */ + if (jmain->rowgroup_ctr == 0) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + jmain->buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, jmain->whole_image[ci], + jmain->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; + jmain->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, + jmain->buffer, &jmain->rowgroup_ctr, + (JDIMENSION) DCTSIZE); + /* Return to application if we need more data to fill the iMCU row. */ + if (jmain->rowgroup_ctr < DCTSIZE) + return; + } + + /* Emit data, unless this is a sink-only pass. */ + if (jmain->pass_mode != JBUF_SAVE_SOURCE) { + if (! (*cinfo->coef->compress_data) (cinfo, jmain->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 (! jmain->suspended) { + (*in_row_ctr)--; + jmain->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 (jmain->suspended) { + (*in_row_ctr)++; + jmain->suspended = FALSE; + } + } + + /* If get here, we are done with this iMCU row. Mark buffer empty. */ + jmain->rowgroup_ctr = 0; + jmain->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 jmain; + int ci; + jpeg_component_info *compptr; + + jmain = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_c_main_controller *) jmain; + jmain->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++) { + jmain->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 + jmain->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++) { + jmain->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/Utilities/FLTK/jpeg/jcmarker.c b/Utilities/FLTK/jpeg/jcmarker.c new file mode 100644 index 0000000000..3d1e6c6d52 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jcmaster.c b/Utilities/FLTK/jpeg/jcmaster.c new file mode 100644 index 0000000000..aab4020b87 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jcomapi.c b/Utilities/FLTK/jpeg/jcomapi.c new file mode 100644 index 0000000000..9b1fa7568a --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jconfig.doc b/Utilities/FLTK/jpeg/jconfig.doc new file mode 100644 index 0000000000..c18d1c064b --- /dev/null +++ b/Utilities/FLTK/jpeg/jconfig.doc @@ -0,0 +1,155 @@ +/* + * jconfig.doc + * + * 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 documents the configuration options that are required to + * customize the JPEG software for a particular system. + * + * The actual configuration options for a particular installation are stored + * in jconfig.h. On many machines, jconfig.h can be generated automatically + * or copied from one of the "canned" jconfig files that we supply. But if + * you need to generate a jconfig.h file by hand, this file tells you how. + * + * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING. + * EDIT A COPY NAMED JCONFIG.H. + */ + + +/* + * These symbols indicate the properties of your machine or compiler. + * #define the symbol if yes, #undef it if no. + */ + +/* Does your compiler support function prototypes? + * (If not, you also need to use ansi2knr, see install.doc) + */ +#define HAVE_PROTOTYPES + +/* Does your compiler support the declaration "unsigned char" ? + * How about "unsigned short" ? + */ +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT + +/* Define "void" as "char" if your compiler doesn't know about type void. + * NOTE: be sure to define void such that "void *" represents the most general + * pointer type, e.g., that returned by malloc(). + */ +/* #define void char */ + +/* Define "const" as empty if your compiler doesn't know the "const" keyword. + */ +/* #define const */ + +/* Define this if an ordinary "char" type is unsigned. + * If you're not sure, leaving it undefined will work at some cost in speed. + * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal. + */ +#undef CHAR_IS_UNSIGNED + +/* Define this if your system has an ANSI-conforming <stddef.h> file. + */ +#define HAVE_STDDEF_H + +/* Define this if your system has an ANSI-conforming <stdlib.h> file. + */ +#define HAVE_STDLIB_H + +/* Define this if your system does not have an ANSI/SysV <string.h>, + * but does have a BSD-style <strings.h>. + */ +#undef NEED_BSD_STRINGS + +/* Define this if your system does not provide typedef size_t in any of the + * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in + * <sys/types.h> instead. + */ +#undef NEED_SYS_TYPES_H + +/* For 80x86 machines, you need to define NEED_FAR_POINTERS, + * unless you are using a large-data memory model or 80386 flat-memory mode. + * On less brain-damaged CPUs this symbol must not be defined. + * (Defining this symbol causes large data structures to be referenced through + * "far" pointers and to be allocated with a special version of malloc.) + */ +#undef NEED_FAR_POINTERS + +/* Define this if your linker needs global names to be unique in less + * than the first 15 characters. + */ +#undef NEED_SHORT_EXTERNAL_NAMES + +/* Although a real ANSI C compiler can deal perfectly well with pointers to + * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI + * and pseudo-ANSI compilers get confused. To keep one of these bozos happy, + * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you + * actually get "missing structure definition" warnings or errors while + * compiling the JPEG code. + */ +#undef INCOMPLETE_TYPES_BROKEN + + +/* + * The following options affect code selection within the JPEG library, + * but they don't need to be visible to applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS has been defined. + */ + +#ifdef JPEG_INTERNALS + +/* Define this if your compiler implements ">>" on signed values as a logical + * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift, + * which is the normal and rational definition. + */ +#undef RIGHT_SHIFT_IS_UNSIGNED + + +#endif /* JPEG_INTERNALS */ + + +/* + * The remaining options do not affect the JPEG library proper, + * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c). + * Other applications can ignore these. + */ + +#ifdef JPEG_CJPEG_DJPEG + +/* These defines indicate which image (non-JPEG) file formats are allowed. */ + +#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 this if you want to name both input and output files on the command + * line, rather than using stdout and optionally stdin. You MUST do this if + * your system can't cope with binary I/O to stdin/stdout. See comments at + * head of cjpeg.c or djpeg.c. + */ +#undef TWO_FILE_COMMANDLINE + +/* Define this if your system needs explicit cleanup of temporary files. + * This is crucial under MS-DOS, where the temporary "files" may be areas + * of extended memory; on most other systems it's not as important. + */ +#undef NEED_SIGNAL_CATCHER + +/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb"). + * This is necessary on systems that distinguish text files from binary files, + * and is harmless on most systems that don't. If you have one of the rare + * systems that complains about the "b" spec, define this symbol. + */ +#undef DONT_USE_B_MODE + +/* Define this if you want percent-done progress reports from cjpeg/djpeg. + */ +#undef PROGRESS_REPORT + + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/Utilities/FLTK/jpeg/jconfig.h b/Utilities/FLTK/jpeg/jconfig.h new file mode 100644 index 0000000000..a990022846 --- /dev/null +++ b/Utilities/FLTK/jpeg/jconfig.h @@ -0,0 +1,50 @@ +/* jconfig.cfg --- source file edited by configure script */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +#ifdef __CHAR_UNSIGNED__ +# define CHAR_IS_UNSIGNED +#endif /* __CHAR_UNSIGNED__ */ +/* Define this if you get warnings about undefined structures. */ +#undef INCOMPLETE_TYPES_BROKEN + +#if defined(WIN32) || defined(__EMX__) +/* Define "boolean" as unsigned char, not int, per Windows custom */ +# ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ +typedef unsigned char boolean; +# endif +# define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ +#endif /* WIN32 || __EMX__ */ + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED +#undef INLINE +/* These are for configuring the JPEG memory manager. */ +#undef DEFAULT_MAX_MEM +#undef NO_MKTEMP + +#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 */ + +#undef TWO_FILE_COMMANDLINE +#undef NEED_SIGNAL_CATCHER +#undef DONT_USE_B_MODE + +#if defined(WIN32) || defined(__EMX__) +# define USE_SETMODE +#endif /* WIN32 || __EMX__ */ + +/* Define this if you want percent-done progress reports from cjpeg/djpeg. */ +#undef PROGRESS_REPORT + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/Utilities/FLTK/jpeg/jcparam.c b/Utilities/FLTK/jpeg/jcparam.c new file mode 100644 index 0000000000..6fc48f5365 --- /dev/null +++ b/Utilities/FLTK/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 */ + scanptr = 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); + scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0); + } +} + +#endif /* C_PROGRESSIVE_SUPPORTED */ diff --git a/Utilities/FLTK/jpeg/jcphuff.c b/Utilities/FLTK/jpeg/jcphuff.c new file mode 100644 index 0000000000..07f9178b01 --- /dev/null +++ b/Utilities/FLTK/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)<<size) - 1; /* mask off any extra bits in code */ + + put_bits += size; /* new number of bits in buffer */ + + put_buffer <<= 24 - put_bits; /* align incoming bits */ + + put_buffer |= entropy->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/Utilities/FLTK/jpeg/jcprepct.c b/Utilities/FLTK/jpeg/jcprepct.c new file mode 100644 index 0000000000..fa93333db2 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jcsample.c b/Utilities/FLTK/jpeg/jcsample.c new file mode 100644 index 0000000000..212ec8757c --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jctrans.c b/Utilities/FLTK/jpeg/jctrans.c new file mode 100644 index 0000000000..0e6d70769d --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jdapimin.c b/Utilities/FLTK/jpeg/jdapimin.c new file mode 100644 index 0000000000..cadb59fce3 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jdapistd.c b/Utilities/FLTK/jpeg/jdapistd.c new file mode 100644 index 0000000000..c8e3fa0c35 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jdatadst.c b/Utilities/FLTK/jpeg/jdatadst.c new file mode 100644 index 0000000000..a8f6fb0e02 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jdatasrc.c b/Utilities/FLTK/jpeg/jdatasrc.c new file mode 100644 index 0000000000..edc752bf5d --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jdcoefct.c b/Utilities/FLTK/jpeg/jdcoefct.c new file mode 100644 index 0000000000..4938d20fcb --- /dev/null +++ b/Utilities/FLTK/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<<Al)) + pred = (1<<Al)-1; + } else { + pred = (int) (((Q01<<7) - num) / (Q01<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + pred = -pred; + } + workspace[1] = (JCOEF) pred; + } + /* AC10 */ + if ((Al=coef_bits[2]) != 0 && workspace[8] == 0) { + num = 36 * Q00 * (DC2 - DC8); + if (num >= 0) { + pred = (int) (((Q10<<7) + num) / (Q10<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + } else { + pred = (int) (((Q10<<7) - num) / (Q10<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + pred = -pred; + } + workspace[8] = (JCOEF) pred; + } + /* AC20 */ + if ((Al=coef_bits[3]) != 0 && workspace[16] == 0) { + num = 9 * Q00 * (DC2 + DC8 - 2*DC5); + if (num >= 0) { + pred = (int) (((Q20<<7) + num) / (Q20<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + } else { + pred = (int) (((Q20<<7) - num) / (Q20<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + pred = -pred; + } + workspace[16] = (JCOEF) pred; + } + /* AC11 */ + if ((Al=coef_bits[4]) != 0 && workspace[9] == 0) { + num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9); + if (num >= 0) { + pred = (int) (((Q11<<7) + num) / (Q11<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + } else { + pred = (int) (((Q11<<7) - num) / (Q11<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + pred = -pred; + } + workspace[9] = (JCOEF) pred; + } + /* AC02 */ + if ((Al=coef_bits[5]) != 0 && workspace[2] == 0) { + num = 9 * Q00 * (DC4 + DC6 - 2*DC5); + if (num >= 0) { + pred = (int) (((Q02<<7) + num) / (Q02<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + } else { + pred = (int) (((Q02<<7) - num) / (Q02<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + pred = -pred; + } + workspace[2] = (JCOEF) pred; + } + /* OK, do the IDCT */ + (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) workspace, + output_ptr, output_col); + /* Advance for next column */ + DC1 = DC2; DC2 = DC3; + DC4 = DC5; DC5 = DC6; + DC7 = DC8; DC8 = DC9; + buffer_ptr++, prev_block_row++, next_block_row++; + 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 /* 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/Utilities/FLTK/jpeg/jdcolor.c b/Utilities/FLTK/jpeg/jdcolor.c new file mode 100644 index 0000000000..6c04dfe8aa --- /dev/null +++ b/Utilities/FLTK/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<<SCALEBITS) + 0.5)) + + +/* + * Initialize tables for YCC->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/Utilities/FLTK/jpeg/jdct.h b/Utilities/FLTK/jpeg/jdct.h new file mode 100644 index 0000000000..04192a266a --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jddctmgr.c b/Utilities/FLTK/jpeg/jddctmgr.c new file mode 100644 index 0000000000..bbf8d0e92f --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jdhuff.c b/Utilities/FLTK/jpeg/jdhuff.c new file mode 100644 index 0000000000..b5ba39f736 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jdhuff.h b/Utilities/FLTK/jpeg/jdhuff.h new file mode 100644 index 0000000000..ae19b6cafd --- /dev/null +++ b/Utilities/FLTK/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<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */ + UINT8 look_sym[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */ +} d_derived_tbl; + +/* Expand a Huffman table definition into the derived format */ +EXTERN(void) jpeg_make_d_derived_tbl + JPP((j_decompress_ptr cinfo, boolean isDC, int tblno, + d_derived_tbl ** pdtbl)); + + +/* + * Fetching the next N bits from the input stream is a time-critical operation + * for the Huffman decoders. We implement it with a combination of inline + * macros and out-of-line subroutines. Note that N (the number of bits + * demanded at one time) never exceeds 15 for JPEG use. + * + * We read source bytes into get_buffer and dole out bits as needed. + * If get_buffer already contains enough bits, they are fetched in-line + * by the macros CHECK_BIT_BUFFER and GET_BITS. When there aren't enough + * bits, jpeg_fill_bit_buffer is called; it will attempt to fill get_buffer + * as full as possible (not just to the number of bits needed; this + * prefetching reduces the overhead cost of calling jpeg_fill_bit_buffer). + * Note that jpeg_fill_bit_buffer may return FALSE to indicate suspension. + * On TRUE return, jpeg_fill_bit_buffer guarantees that get_buffer contains + * at least the requested number of bits --- dummy zeroes are inserted if + * necessary. + */ + +typedef INT32 bit_buf_type; /* type of bit-extraction buffer */ +#define BIT_BUF_SIZE 32 /* size of buffer in bits */ + +/* If long is > 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/Utilities/FLTK/jpeg/jdinput.c b/Utilities/FLTK/jpeg/jdinput.c new file mode 100644 index 0000000000..0c2ac8f120 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jdmainct.c b/Utilities/FLTK/jpeg/jdmainct.c new file mode 100644 index 0000000000..da19c7e5e0 --- /dev/null +++ b/Utilities/FLTK/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 jmain = (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. + */ + jmain->xbuffer[0] = (JSAMPIMAGE) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); + jmain->xbuffer[1] = jmain->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 */ + jmain->xbuffer[0][ci] = xbuf; + xbuf += rgroup * (M + 4); + jmain->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 jmain->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 jmain = (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 = jmain->xbuffer[0][ci]; + xbuf1 = jmain->xbuffer[1][ci]; + /* First copy the workspace pointers as-is */ + buf = jmain->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 jmain = (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 = jmain->xbuffer[0][ci]; + xbuf1 = jmain->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 jmain = (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) { + jmain->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 = jmain->xbuffer[jmain->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 jmain = (my_main_ptr) cinfo->main; + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (cinfo->upsample->need_context_rows) { + jmain->pub.process_data = process_data_context_main; + make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ + jmain->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ + jmain->context_state = CTX_PREPARE_FOR_IMCU; + jmain->iMCU_row_ctr = 0; + } else { + /* Simple case with no context needed */ + jmain->pub.process_data = process_data_simple_main; + } + jmain->buffer_full = FALSE; /* Mark buffer empty */ + jmain->rowgroup_ctr = 0; + break; +#ifdef QUANT_2PASS_SUPPORTED + case JBUF_CRANK_DEST: + /* For last pass of 2-pass quantization, just crank the postprocessor */ + jmain->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 jmain = (my_main_ptr) cinfo->main; + JDIMENSION rowgroups_avail; + + /* Read input data if we haven't filled the main buffer yet */ + if (! jmain->buffer_full) { + if (! (*cinfo->coef->decompress_data) (cinfo, jmain->buffer)) + return; /* suspension forced, can do nothing more */ + jmain->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, jmain->buffer, + &jmain->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 (jmain->rowgroup_ctr >= rowgroups_avail) { + jmain->buffer_full = FALSE; + jmain->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 jmain = (my_main_ptr) cinfo->main; + + /* Read input data if we haven't filled the main buffer yet */ + if (! jmain->buffer_full) { + if (! (*cinfo->coef->decompress_data) (cinfo, + jmain->xbuffer[jmain->whichptr])) + return; /* suspension forced, can do nothing more */ + jmain->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + jmain->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 (jmain->context_state) { + case CTX_POSTPONED_ROW: + /* Call postprocessor using previously set pointers for postponed row */ + (*cinfo->post->post_process_data) (cinfo, jmain->xbuffer[jmain->whichptr], + &jmain->rowgroup_ctr, jmain->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (jmain->rowgroup_ctr < jmain->rowgroups_avail) + return; /* Need to suspend */ + jmain->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 */ + jmain->rowgroup_ctr = 0; + jmain->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 (jmain->iMCU_row_ctr == cinfo->total_iMCU_rows) + set_bottom_pointers(cinfo); + jmain->context_state = CTX_PROCESS_IMCU; + /*FALLTHROUGH*/ + case CTX_PROCESS_IMCU: + /* Call postprocessor using previously set pointers */ + (*cinfo->post->post_process_data) (cinfo, jmain->xbuffer[jmain->whichptr], + &jmain->rowgroup_ctr, jmain->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (jmain->rowgroup_ctr < jmain->rowgroups_avail) + return; /* Need to suspend */ + /* After the first iMCU, change wraparound pointers to normal state */ + if (jmain->iMCU_row_ctr == 1) + set_wraparound_pointers(cinfo); + /* Prepare to load new iMCU row using other xbuffer list */ + jmain->whichptr ^= 1; /* 0=>1 or 1=>0 */ + jmain->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 */ + jmain->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1); + jmain->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2); + jmain->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 jmain; + int ci, rgroup, ngroups; + jpeg_component_info *compptr; + + jmain = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_d_main_controller *) jmain; + jmain->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 */ + jmain->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/Utilities/FLTK/jpeg/jdmarker.c b/Utilities/FLTK/jpeg/jdmarker.c new file mode 100644 index 0000000000..f4cca8cc83 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jdmaster.c b/Utilities/FLTK/jpeg/jdmaster.c new file mode 100644 index 0000000000..2802c5b7b2 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jdmerge.c b/Utilities/FLTK/jpeg/jdmerge.c new file mode 100644 index 0000000000..37444468c2 --- /dev/null +++ b/Utilities/FLTK/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<<SCALEBITS) + 0.5)) + + +/* + * Initialize tables for YCC->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/Utilities/FLTK/jpeg/jdphuff.c b/Utilities/FLTK/jpeg/jdphuff.c new file mode 100644 index 0000000000..2267809945 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jdpostct.c b/Utilities/FLTK/jpeg/jdpostct.c new file mode 100644 index 0000000000..571563d728 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jdsample.c b/Utilities/FLTK/jpeg/jdsample.c new file mode 100644 index 0000000000..80ffefb2a1 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jdtrans.c b/Utilities/FLTK/jpeg/jdtrans.c new file mode 100644 index 0000000000..6c0ab715d3 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jerror.c b/Utilities/FLTK/jpeg/jerror.c new file mode 100644 index 0000000000..a44463cf18 --- /dev/null +++ b/Utilities/FLTK/jpeg/jerror.c @@ -0,0 +1,253 @@ +/* + * 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" +#include <stdlib.h> + +#ifdef USE_WINDOWS_MESSAGEBOX +#include <windows.h> +#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/Utilities/FLTK/jpeg/jerror.h b/Utilities/FLTK/jpeg/jerror.h new file mode 100644 index 0000000000..fc2fffeac2 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jfdctflt.c b/Utilities/FLTK/jpeg/jfdctflt.c new file mode 100644 index 0000000000..79d7a00787 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jfdctfst.c b/Utilities/FLTK/jpeg/jfdctfst.c new file mode 100644 index 0000000000..ccb378a3b4 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jfdctint.c b/Utilities/FLTK/jpeg/jfdctint.c new file mode 100644 index 0000000000..0a78b64aee --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jidctflt.c b/Utilities/FLTK/jpeg/jidctflt.c new file mode 100644 index 0000000000..0188ce3dfc --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jidctfst.c b/Utilities/FLTK/jpeg/jidctfst.c new file mode 100644 index 0000000000..dba4216fb9 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jidctint.c b/Utilities/FLTK/jpeg/jidctint.c new file mode 100644 index 0000000000..a72b3207ca --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jidctred.c b/Utilities/FLTK/jpeg/jidctred.c new file mode 100644 index 0000000000..421f3c7ca1 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jinclude.h b/Utilities/FLTK/jpeg/jinclude.h new file mode 100644 index 0000000000..0a4f15146a --- /dev/null +++ b/Utilities/FLTK/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 <stddef.h>. + * Otherwise, we get them from <stdlib.h> or <stdio.h>; we may have to + * pull in <sys/types.h> as well. + * Note that the core JPEG library does not require <stdio.h>; + * 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 <stdio.h>. + */ + +#ifdef HAVE_STDDEF_H +#include <stddef.h> +#endif + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#ifdef NEED_SYS_TYPES_H +#include <sys/types.h> +#endif + +#include <stdio.h> + +/* + * We need memory copying and zeroing functions, plus strncpy(). + * ANSI and System V implementations declare these in <string.h>. + * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). + * Some systems may declare memset and memcpy in <memory.h>. + * + * 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 <strings.h> +#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 <string.h> +#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/Utilities/FLTK/jpeg/jmemmgr.c b/Utilities/FLTK/jpeg/jmemmgr.c new file mode 100644 index 0000000000..d801b322da --- /dev/null +++ b/Utilities/FLTK/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 /* <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/Utilities/FLTK/jpeg/jmemnobs.c b/Utilities/FLTK/jpeg/jmemnobs.c new file mode 100644 index 0000000000..eb8c337725 --- /dev/null +++ b/Utilities/FLTK/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 /* <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/Utilities/FLTK/jpeg/jmemsys.h b/Utilities/FLTK/jpeg/jmemsys.h new file mode 100644 index 0000000000..6c3c6d348f --- /dev/null +++ b/Utilities/FLTK/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 <Files.h> +#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/Utilities/FLTK/jpeg/jmorecfg.h b/Utilities/FLTK/jpeg/jmorecfg.h new file mode 100644 index 0000000000..4f491fc914 --- /dev/null +++ b/Utilities/FLTK/jpeg/jmorecfg.h @@ -0,0 +1,316 @@ +/* + * 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. + */ + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#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. + */ + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +/* 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. */ + +typedef unsigned char UINT8; + +/* UINT16 must hold at least the values 0..65535. */ + +typedef unsigned short UINT16; + +/* 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 +typedef int 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. + */ + +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist + +/* 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. + */ + +#undef FAR +#define FAR + + +/* + * 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 char 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/Utilities/FLTK/jpeg/jpegint.h b/Utilities/FLTK/jpeg/jpegint.h new file mode 100644 index 0000000000..95b00d405c --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jpeglib.h b/Utilities/FLTK/jpeg/jpeglib.h new file mode 100644 index 0000000000..d1be8ddeff --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jquant1.c b/Utilities/FLTK/jpeg/jquant1.c new file mode 100644 index 0000000000..b2f96aa15d --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jquant2.c b/Utilities/FLTK/jpeg/jquant2.c new file mode 100644 index 0000000000..af601e334b --- /dev/null +++ b/Utilities/FLTK/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<<HIST_C0_BITS) +#define HIST_C1_ELEMS (1<<HIST_C1_BITS) +#define HIST_C2_ELEMS (1<<HIST_C2_BITS) + +/* These are the amounts to shift an input value to get a histogram index. */ +#define C0_SHIFT (BITS_IN_JSAMPLE-HIST_C0_BITS) +#define C1_SHIFT (BITS_IN_JSAMPLE-HIST_C1_BITS) +#define C2_SHIFT (BITS_IN_JSAMPLE-HIST_C2_BITS) + + +typedef UINT16 histcell; /* histogram cell; prefer an unsigned type */ + +typedef histcell FAR * histptr; /* for pointers to histogram cells */ + +typedef histcell hist1d[HIST_C2_ELEMS]; /* typedefs for the array */ +typedef hist1d FAR * hist2d; /* type for the 2nd-level pointers */ +typedef hist2d * hist3d; /* type for top-level pointer */ + + +/* 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 has (#columns + 2) entries; the extra entry at + * each end saves us from special-casing the first and last pixels. + * Each entry is three values long, one value for each color component. + * + * 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 */ + +typedef struct { + struct jpeg_color_quantizer pub; /* public fields */ + + /* Space for the eventually created colormap is stashed here */ + JSAMPARRAY sv_colormap; /* colormap allocated at init time */ + int desired; /* desired # of colors = size of colormap */ + + /* Variables for accumulating image statistics */ + hist3d histogram; /* pointer to the histogram */ + + boolean needs_zeroed; /* TRUE if next pass must zero histogram */ + + /* Variables for Floyd-Steinberg dithering */ + FSERRPTR fserrors; /* accumulated errors */ + boolean on_odd_row; /* flag to remember which row we are on */ + int * error_limiter; /* table for clamping the applied error */ +} my_cquantizer; + +typedef my_cquantizer * my_cquantize_ptr; + + +/* + * Prescan some rows of pixels. + * In this module the prescan simply updates the histogram, which has been + * initialized to zeroes by start_pass. + * An output_buf parameter is required by the method signature, but no data + * is actually output (in fact the buffer controller is probably passing a + * NULL pointer). + */ + +METHODDEF(void) +prescan_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->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<<C0_SHIFT)>>1)) * count; + c1total += ((c1 << C1_SHIFT) + ((1<<C1_SHIFT)>>1)) * count; + c2total += ((c2 << C2_SHIFT) + ((1<<C2_SHIFT)>>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<<BOX_C0_LOG) /* # of hist cells in update box */ +#define BOX_C1_ELEMS (1<<BOX_C1_LOG) +#define BOX_C2_ELEMS (1<<BOX_C2_LOG) + +#define BOX_C0_SHIFT (C0_SHIFT + BOX_C0_LOG) +#define BOX_C1_SHIFT (C1_SHIFT + BOX_C1_LOG) +#define BOX_C2_SHIFT (C2_SHIFT + BOX_C2_LOG) + + +/* + * The next three routines implement inverse colormap filling. They could + * all be folded into one big routine, but splitting them up this way saves + * some stack space (the mindist[] and bestdist[] arrays need not coexist) + * and may allow some compilers to produce better code by registerizing more + * inner-loop variables. + */ + +LOCAL(int) +find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, + JSAMPLE colorlist[]) +/* Locate the colormap entries close enough to an update box to be candidates + * for the nearest entry to some cell(s) in the update box. The update box + * is specified by the center coordinates of its first cell. The number of + * candidate colormap entries is returned, and their colormap indexes are + * placed in colorlist[]. + * This routine uses Heckbert's "locally sorted search" criterion to select + * the colors that need further consideration. + */ +{ + int numcolors = cinfo->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/Utilities/FLTK/jpeg/jutils.c b/Utilities/FLTK/jpeg/jutils.c new file mode 100644 index 0000000000..d18a955562 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/jversion.h b/Utilities/FLTK/jpeg/jversion.h new file mode 100644 index 0000000000..6472c58d35 --- /dev/null +++ b/Utilities/FLTK/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/Utilities/FLTK/jpeg/libjpeg.doc b/Utilities/FLTK/jpeg/libjpeg.doc new file mode 100644 index 0000000000..689b206c07 --- /dev/null +++ b/Utilities/FLTK/jpeg/libjpeg.doc @@ -0,0 +1,3006 @@ +USING THE IJG JPEG LIBRARY + +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 describes how to use the IJG JPEG library within an application +program. Read it if you want to write a program that uses the library. + +The file example.c provides heavily commented skeleton code for calling the +JPEG library. Also see jpeglib.h (the include file to be used by application +programs) for full details about data structures and function parameter lists. +The library source code, of course, is the ultimate reference. + +Note that there have been *major* changes from the application interface +presented by IJG version 4 and earlier versions. The old design had several +inherent limitations, and it had accumulated a lot of cruft as we added +features while trying to minimize application-interface changes. We have +sacrificed backward compatibility in the version 5 rewrite, but we think the +improvements justify this. + + +TABLE OF CONTENTS +----------------- + +Overview: + Functions provided by the library + Outline of typical usage +Basic library usage: + Data formats + Compression details + Decompression details + Mechanics of usage: include files, linking, etc +Advanced features: + Compression parameter selection + Decompression parameter selection + Special color spaces + Error handling + Compressed data handling (source and destination managers) + I/O suspension + Progressive JPEG support + Buffered-image mode + Abbreviated datastreams and multiple images + Special markers + Raw (downsampled) image data + Really raw data: DCT coefficients + Progress monitoring + Memory management + Memory usage + Library compile-time options + Portability considerations + Notes for MS-DOS implementors + +You should read at least the overview and basic usage sections before trying +to program with the library. The sections on advanced features can be read +if and when you need them. + + +OVERVIEW +======== + +Functions provided by the library +--------------------------------- + +The IJG JPEG library provides C code to read and write JPEG-compressed image +files. The surrounding application program receives or supplies image data a +scanline at a time, using a straightforward uncompressed image format. All +details of color conversion and other preprocessing/postprocessing can be +handled by the library. + +The library includes a substantial amount of code that is not covered by the +JPEG standard but is necessary for typical applications of JPEG. These +functions preprocess the image before JPEG compression or postprocess it after +decompression. They include colorspace conversion, downsampling/upsampling, +and color quantization. The application indirectly selects use of this code +by specifying the format in which it wishes to supply or receive image data. +For example, if colormapped output is requested, then the decompression +library automatically invokes color quantization. + +A wide range of quality vs. speed tradeoffs are possible in JPEG processing, +and even more so in decompression postprocessing. The decompression library +provides multiple implementations that cover most of the useful tradeoffs, +ranging from very-high-quality down to fast-preview operation. On the +compression side we have generally not provided low-quality choices, since +compression is normally less time-critical. It should be understood that the +low-quality modes may not meet the JPEG standard's accuracy requirements; +nonetheless, they are useful for viewers. + +A word about functions *not* provided by the library. We handle a subset of +the ISO JPEG standard; most baseline, extended-sequential, and progressive +JPEG processes are supported. (Our subset includes all features now in common +use.) Unsupported ISO options include: + * Hierarchical storage + * Lossless JPEG + * Arithmetic entropy coding (unsupported for legal reasons) + * DNL marker + * Nonintegral subsampling ratios +We support both 8- and 12-bit data precision, but this is a compile-time +choice rather than a run-time choice; hence it is difficult to use both +precisions in a single application. + +By itself, the library handles only interchange JPEG datastreams --- in +particular the widely used JFIF file format. The library can be used by +surrounding code to process interchange or abbreviated JPEG datastreams that +are embedded in more complex file formats. (For example, this library is +used by the free LIBTIFF library to support JPEG compression in TIFF.) + + +Outline of typical usage +------------------------ + +The rough outline of a JPEG compression operation is: + + Allocate and initialize a JPEG compression object + Specify the destination for the compressed data (eg, a file) + Set parameters for compression, including image size & colorspace + jpeg_start_compress(...); + while (scan lines remain to be written) + jpeg_write_scanlines(...); + jpeg_finish_compress(...); + Release the JPEG compression object + +A JPEG compression object holds parameters and working state for the JPEG +library. We make creation/destruction of the object separate from starting +or finishing compression of an image; the same object can be re-used for a +series of image compression operations. This makes it easy to re-use the +same parameter settings for a sequence of images. Re-use of a JPEG object +also has important implications for processing abbreviated JPEG datastreams, +as discussed later. + +The image data to be compressed is supplied to jpeg_write_scanlines() from +in-memory buffers. If the application is doing file-to-file compression, +reading image data from the source file is the application's responsibility. +The library emits compressed data by calling a "data destination manager", +which typically will write the data into a file; but the application can +provide its own destination manager to do something else. + +Similarly, the rough outline of a JPEG decompression operation is: + + Allocate and initialize a JPEG decompression object + Specify the source of the compressed data (eg, a file) + Call jpeg_read_header() to obtain image info + Set parameters for decompression + jpeg_start_decompress(...); + while (scan lines remain to be read) + jpeg_read_scanlines(...); + jpeg_finish_decompress(...); + Release the JPEG decompression object + +This is comparable to the compression outline except that reading the +datastream header is a separate step. This is helpful because information +about the image's size, colorspace, etc is available when the application +selects decompression parameters. For example, the application can choose an +output scaling ratio that will fit the image into the available screen size. + +The decompression library obtains compressed data by calling a data source +manager, which typically will read the data from a file; but other behaviors +can be obtained with a custom source manager. Decompressed data is delivered +into in-memory buffers passed to jpeg_read_scanlines(). + +It is possible to abort an incomplete compression or decompression operation +by calling jpeg_abort(); or, if you do not need to retain the JPEG object, +simply release it by calling jpeg_destroy(). + +JPEG compression and decompression objects are two separate struct types. +However, they share some common fields, and certain routines such as +jpeg_destroy() can work on either type of object. + +The JPEG library has no static variables: all state is in the compression +or decompression object. Therefore it is possible to process multiple +compression and decompression operations concurrently, using multiple JPEG +objects. + +Both compression and decompression can be done in an incremental memory-to- +memory fashion, if suitable source/destination managers are used. See the +section on "I/O suspension" for more details. + + +BASIC LIBRARY USAGE +=================== + +Data formats +------------ + +Before diving into procedural details, it is helpful to understand the +image data format that the JPEG library expects or returns. + +The standard input image format is a rectangular array of pixels, with each +pixel having the same number of "component" or "sample" values (color +channels). You must specify how many components there are and the colorspace +interpretation of the components. Most applications will use RGB data +(three components per pixel) or grayscale data (one component per pixel). +PLEASE NOTE THAT RGB DATA IS THREE SAMPLES PER PIXEL, GRAYSCALE ONLY ONE. +A remarkable number of people manage to miss this, only to find that their +programs don't work with grayscale JPEG files. + +There is no provision for colormapped input. JPEG files are always full-color +or full grayscale (or sometimes another colorspace such as CMYK). You can +feed in a colormapped image by expanding it to full-color format. However +JPEG often doesn't work very well with source data that has been colormapped, +because of dithering noise. This is discussed in more detail in the JPEG FAQ +and the other references mentioned in the README file. + +Pixels are stored by scanlines, with each scanline running from left to +right. The component values for each pixel are adjacent in the row; for +example, R,G,B,R,G,B,R,G,B,... for 24-bit RGB color. Each scanline is an +array of data type JSAMPLE --- which is typically "unsigned char", unless +you've changed jmorecfg.h. (You can also change the RGB pixel layout, say +to B,G,R order, by modifying jmorecfg.h. But see the restrictions listed in +that file before doing so.) + +A 2-D array of pixels is formed by making a list of pointers to the starts of +scanlines; so the scanlines need not be physically adjacent in memory. Even +if you process just one scanline at a time, you must make a one-element +pointer array to conform to this structure. Pointers to JSAMPLE rows are of +type JSAMPROW, and the pointer to the pointer array is of type JSAMPARRAY. + +The library accepts or supplies one or more complete scanlines per call. +It is not possible to process part of a row at a time. Scanlines are always +processed top-to-bottom. You can process an entire image in one call if you +have it all in memory, but usually it's simplest to process one scanline at +a time. + +For best results, source data values should have the precision specified by +BITS_IN_JSAMPLE (normally 8 bits). For instance, if you choose to compress +data that's only 6 bits/channel, you should left-justify each value in a +byte before passing it to the compressor. If you need to compress data +that has more than 8 bits/channel, compile with BITS_IN_JSAMPLE = 12. +(See "Library compile-time options", later.) + + +The data format returned by the decompressor is the same in all details, +except that colormapped output is supported. (Again, a JPEG file is never +colormapped. But you can ask the decompressor to perform on-the-fly color +quantization to deliver colormapped output.) If you request colormapped +output then the returned data array contains a single JSAMPLE per pixel; +its value is an index into a color map. The color map is represented as +a 2-D JSAMPARRAY in which each row holds the values of one color component, +that is, colormap[i][j] is the value of the i'th color component for pixel +value (map index) j. Note that since the colormap indexes are stored in +JSAMPLEs, the maximum number of colors is limited by the size of JSAMPLE +(ie, at most 256 colors for an 8-bit JPEG library). + + +Compression details +------------------- + +Here we revisit the JPEG compression outline given in the overview. + +1. Allocate and initialize a JPEG compression object. + +A JPEG compression object is a "struct jpeg_compress_struct". (It also has +a bunch of subsidiary structures which are allocated via malloc(), but the +application doesn't control those directly.) This struct can be just a local +variable in the calling routine, if a single routine is going to execute the +whole JPEG compression sequence. Otherwise it can be static or allocated +from malloc(). + +You will also need a structure representing a JPEG error handler. The part +of this that the library cares about is a "struct jpeg_error_mgr". If you +are providing your own error handler, you'll typically want to embed the +jpeg_error_mgr struct in a larger structure; this is discussed later under +"Error handling". For now we'll assume you are just using the default error +handler. The default error handler will print JPEG error/warning messages +on stderr, and it will call exit() if a fatal error occurs. + +You must initialize the error handler structure, store a pointer to it into +the JPEG object's "err" field, and then call jpeg_create_compress() to +initialize the rest of the JPEG object. + +Typical code for this step, if you are using the default error handler, is + + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + ... + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + +jpeg_create_compress allocates a small amount of memory, so it could fail +if you are out of memory. In that case it will exit via the error handler; +that's why the error handler must be initialized first. + + +2. Specify the destination for the compressed data (eg, a file). + +As previously mentioned, the JPEG library delivers compressed data to a +"data destination" module. The library includes one data destination +module which knows how to write to a stdio stream. You can use your own +destination module if you want to do something else, as discussed later. + +If you use the standard destination module, you must open the target stdio +stream beforehand. Typical code for this step looks like: + + FILE * outfile; + ... + if ((outfile = fopen(filename, "wb")) == NULL) { + fprintf(stderr, "can't open %s\n", filename); + exit(1); + } + jpeg_stdio_dest(&cinfo, outfile); + +where the last line invokes the standard destination module. + +WARNING: it is critical that the binary compressed data be delivered to the +output file unchanged. On non-Unix systems the stdio library may perform +newline translation or otherwise corrupt binary data. To suppress this +behavior, you may need to use a "b" option to fopen (as shown above), or use +setmode() or another routine to put the stdio stream in binary mode. See +cjpeg.c and djpeg.c for code that has been found to work on many systems. + +You can select the data destination after setting other parameters (step 3), +if that's more convenient. You may not change the destination between +calling jpeg_start_compress() and jpeg_finish_compress(). + + +3. Set parameters for compression, including image size & colorspace. + +You must supply information about the source image by setting the following +fields in the JPEG object (cinfo structure): + + image_width Width of image, in pixels + image_height Height of image, in pixels + input_components Number of color channels (samples per pixel) + in_color_space Color space of source image + +The image dimensions are, hopefully, obvious. JPEG supports image dimensions +of 1 to 64K pixels in either direction. The input color space is typically +RGB or grayscale, and input_components is 3 or 1 accordingly. (See "Special +color spaces", later, for more info.) The in_color_space field must be +assigned one of the J_COLOR_SPACE enum constants, typically JCS_RGB or +JCS_GRAYSCALE. + +JPEG has a large number of compression parameters that determine how the +image is encoded. Most applications don't need or want to know about all +these parameters. You can set all the parameters to reasonable defaults by +calling jpeg_set_defaults(); then, if there are particular values you want +to change, you can do so after that. The "Compression parameter selection" +section tells about all the parameters. + +You must set in_color_space correctly before calling jpeg_set_defaults(), +because the defaults depend on the source image colorspace. However the +other three source image parameters need not be valid until you call +jpeg_start_compress(). There's no harm in calling jpeg_set_defaults() more +than once, if that happens to be convenient. + +Typical code for a 24-bit RGB source image is + + cinfo.image_width = Width; /* image width and height, in pixels */ + cinfo.image_height = Height; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + + jpeg_set_defaults(&cinfo); + /* Make optional parameter settings here */ + + +4. jpeg_start_compress(...); + +After you have established the data destination and set all the necessary +source image info and other parameters, call jpeg_start_compress() to begin +a compression cycle. This will initialize internal state, allocate working +storage, and emit the first few bytes of the JPEG datastream header. + +Typical code: + + jpeg_start_compress(&cinfo, TRUE); + +The "TRUE" parameter ensures that a complete JPEG interchange datastream +will be written. This is appropriate in most cases. If you think you might +want to use an abbreviated datastream, read the section on abbreviated +datastreams, below. + +Once you have called jpeg_start_compress(), you may not alter any JPEG +parameters or other fields of the JPEG object until you have completed +the compression cycle. + + +5. while (scan lines remain to be written) + jpeg_write_scanlines(...); + +Now write all the required image data by calling jpeg_write_scanlines() +one or more times. You can pass one or more scanlines in each call, up +to the total image height. In most applications it is convenient to pass +just one or a few scanlines at a time. The expected format for the passed +data is discussed under "Data formats", above. + +Image data should be written in top-to-bottom scanline order. The JPEG spec +contains some weasel wording about how top and bottom are application-defined +terms (a curious interpretation of the English language...) but if you want +your files to be compatible with everyone else's, you WILL use top-to-bottom +order. If the source data must be read in bottom-to-top order, you can use +the JPEG library's virtual array mechanism to invert the data efficiently. +Examples of this can be found in the sample application cjpeg. + +The library maintains a count of the number of scanlines written so far +in the next_scanline field of the JPEG object. Usually you can just use +this variable as the loop counter, so that the loop test looks like +"while (cinfo.next_scanline < cinfo.image_height)". + +Code for this step depends heavily on the way that you store the source data. +example.c shows the following code for the case of a full-size 2-D source +array containing 3-byte RGB pixels: + + JSAMPROW row_pointer[1]; /* pointer to a single row */ + int row_stride; /* physical row width in buffer */ + + row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */ + + while (cinfo.next_scanline < cinfo.image_height) { + row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; + jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + +jpeg_write_scanlines() returns the number of scanlines actually written. +This will normally be equal to the number passed in, so you can usually +ignore the return value. It is different in just two cases: + * If you try to write more scanlines than the declared image height, + the additional scanlines are ignored. + * If you use a suspending data destination manager, output buffer overrun + will cause the compressor to return before accepting all the passed lines. + This feature is discussed under "I/O suspension", below. The normal + stdio destination manager will NOT cause this to happen. +In any case, the return value is the same as the change in the value of +next_scanline. + + +6. jpeg_finish_compress(...); + +After all the image data has been written, call jpeg_finish_compress() to +complete the compression cycle. This step is ESSENTIAL to ensure that the +last bufferload of data is written to the data destination. +jpeg_finish_compress() also releases working memory associated with the JPEG +object. + +Typical code: + + jpeg_finish_compress(&cinfo); + +If using the stdio destination manager, don't forget to close the output +stdio stream (if necessary) afterwards. + +If you have requested a multi-pass operating mode, such as Huffman code +optimization, jpeg_finish_compress() will perform the additional passes using +data buffered by the first pass. In this case jpeg_finish_compress() may take +quite a while to complete. With the default compression parameters, this will +not happen. + +It is an error to call jpeg_finish_compress() before writing the necessary +total number of scanlines. If you wish to abort compression, call +jpeg_abort() as discussed below. + +After completing a compression cycle, you may dispose of the JPEG object +as discussed next, or you may use it to compress another image. In that case +return to step 2, 3, or 4 as appropriate. If you do not change the +destination manager, the new datastream will be written to the same target. +If you do not change any JPEG parameters, the new datastream will be written +with the same parameters as before. Note that you can change the input image +dimensions freely between cycles, but if you change the input colorspace, you +should call jpeg_set_defaults() to adjust for the new colorspace; and then +you'll need to repeat all of step 3. + + +7. Release the JPEG compression object. + +When you are done with a JPEG compression object, destroy it by calling +jpeg_destroy_compress(). This will free all subsidiary memory (regardless of +the previous state of the object). Or you can call jpeg_destroy(), which +works for either compression or decompression objects --- this may be more +convenient if you are sharing code between compression and decompression +cases. (Actually, these routines are equivalent except for the declared type +of the passed pointer. To avoid gripes from ANSI C compilers, jpeg_destroy() +should be passed a j_common_ptr.) + +If you allocated the jpeg_compress_struct structure from malloc(), freeing +it is your responsibility --- jpeg_destroy() won't. Ditto for the error +handler structure. + +Typical code: + + jpeg_destroy_compress(&cinfo); + + +8. Aborting. + +If you decide to abort a compression cycle before finishing, you can clean up +in either of two ways: + +* If you don't need the JPEG object any more, just call + jpeg_destroy_compress() or jpeg_destroy() to release memory. This is + legitimate at any point after calling jpeg_create_compress() --- in fact, + it's safe even if jpeg_create_compress() fails. + +* If you want to re-use the JPEG object, call jpeg_abort_compress(), or call + jpeg_abort() which works on both compression and decompression objects. + This will return the object to an idle state, releasing any working memory. + jpeg_abort() is allowed at any time after successful object creation. + +Note that cleaning up the data destination, if required, is your +responsibility; neither of these routines will call term_destination(). +(See "Compressed data handling", below, for more about that.) + +jpeg_destroy() and jpeg_abort() are the only safe calls to make on a JPEG +object that has reported an error by calling error_exit (see "Error handling" +for more info). The internal state of such an object is likely to be out of +whack. Either of these two routines will return the object to a known state. + + +Decompression details +--------------------- + +Here we revisit the JPEG decompression outline given in the overview. + +1. Allocate and initialize a JPEG decompression object. + +This is just like initialization for compression, as discussed above, +except that the object is a "struct jpeg_decompress_struct" and you +call jpeg_create_decompress(). Error handling is exactly the same. + +Typical code: + + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + ... + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + +(Both here and in the IJG code, we usually use variable name "cinfo" for +both compression and decompression objects.) + + +2. Specify the source of the compressed data (eg, a file). + +As previously mentioned, the JPEG library reads compressed data from a "data +source" module. The library includes one data source module which knows how +to read from a stdio stream. You can use your own source module if you want +to do something else, as discussed later. + +If you use the standard source module, you must open the source stdio stream +beforehand. Typical code for this step looks like: + + FILE * infile; + ... + if ((infile = fopen(filename, "rb")) == NULL) { + fprintf(stderr, "can't open %s\n", filename); + exit(1); + } + jpeg_stdio_src(&cinfo, infile); + +where the last line invokes the standard source module. + +WARNING: it is critical that the binary compressed data be read unchanged. +On non-Unix systems the stdio library may perform newline translation or +otherwise corrupt binary data. To suppress this behavior, you may need to use +a "b" option to fopen (as shown above), or use setmode() or another routine to +put the stdio stream in binary mode. See cjpeg.c and djpeg.c for code that +has been found to work on many systems. + +You may not change the data source between calling jpeg_read_header() and +jpeg_finish_decompress(). If you wish to read a series of JPEG images from +a single source file, you should repeat the jpeg_read_header() to +jpeg_finish_decompress() sequence without reinitializing either the JPEG +object or the data source module; this prevents buffered input data from +being discarded. + + +3. Call jpeg_read_header() to obtain image info. + +Typical code for this step is just + + jpeg_read_header(&cinfo, TRUE); + +This will read the source datastream header markers, up to the beginning +of the compressed data proper. On return, the image dimensions and other +info have been stored in the JPEG object. The application may wish to +consult this information before selecting decompression parameters. + +More complex code is necessary if + * A suspending data source is used --- in that case jpeg_read_header() + may return before it has read all the header data. See "I/O suspension", + below. The normal stdio source manager will NOT cause this to happen. + * Abbreviated JPEG files are to be processed --- see the section on + abbreviated datastreams. Standard applications that deal only in + interchange JPEG files need not be concerned with this case either. + +It is permissible to stop at this point if you just wanted to find out the +image dimensions and other header info for a JPEG file. In that case, +call jpeg_destroy() when you are done with the JPEG object, or call +jpeg_abort() to return it to an idle state before selecting a new data +source and reading another header. + + +4. Set parameters for decompression. + +jpeg_read_header() sets appropriate default decompression parameters based on +the properties of the image (in particular, its colorspace). However, you +may well want to alter these defaults before beginning the decompression. +For example, the default is to produce full color output from a color file. +If you want colormapped output you must ask for it. Other options allow the +returned image to be scaled and allow various speed/quality tradeoffs to be +selected. "Decompression parameter selection", below, gives details. + +If the defaults are appropriate, nothing need be done at this step. + +Note that all default values are set by each call to jpeg_read_header(). +If you reuse a decompression object, you cannot expect your parameter +settings to be preserved across cycles, as you can for compression. +You must set desired parameter values each time. + + +5. jpeg_start_decompress(...); + +Once the parameter values are satisfactory, call jpeg_start_decompress() to +begin decompression. This will initialize internal state, allocate working +memory, and prepare for returning data. + +Typical code is just + + jpeg_start_decompress(&cinfo); + +If you have requested a multi-pass operating mode, such as 2-pass color +quantization, jpeg_start_decompress() will do everything needed before data +output can begin. In this case jpeg_start_decompress() may take quite a while +to complete. With a single-scan (non progressive) JPEG file and default +decompression parameters, this will not happen; jpeg_start_decompress() will +return quickly. + +After this call, the final output image dimensions, including any requested +scaling, are available in the JPEG object; so is the selected colormap, if +colormapped output has been requested. Useful fields include + + output_width image width and height, as scaled + output_height + out_color_components # of color components in out_color_space + output_components # of color components returned per pixel + colormap the selected colormap, if any + actual_number_of_colors number of entries in colormap + +output_components is 1 (a colormap index) when quantizing colors; otherwise it +equals out_color_components. It is the number of JSAMPLE values that will be +emitted per pixel in the output arrays. + +Typically you will need to allocate data buffers to hold the incoming image. +You will need output_width * output_components JSAMPLEs per scanline in your +output buffer, and a total of output_height scanlines will be returned. + +Note: if you are using the JPEG library's internal memory manager to allocate +data buffers (as djpeg does), then the manager's protocol requires that you +request large buffers *before* calling jpeg_start_decompress(). This is a +little tricky since the output_XXX fields are not normally valid then. You +can make them valid by calling jpeg_calc_output_dimensions() after setting the +relevant parameters (scaling, output color space, and quantization flag). + + +6. while (scan lines remain to be read) + jpeg_read_scanlines(...); + +Now you can read the decompressed image data by calling jpeg_read_scanlines() +one or more times. At each call, you pass in the maximum number of scanlines +to be read (ie, the height of your working buffer); jpeg_read_scanlines() +will return up to that many lines. The return value is the number of lines +actually read. The format of the returned data is discussed under "Data +formats", above. Don't forget that grayscale and color JPEGs will return +different data formats! + +Image data is returned in top-to-bottom scanline order. If you must write +out the image in bottom-to-top order, you can use the JPEG library's virtual +array mechanism to invert the data efficiently. Examples of this can be +found in the sample application djpeg. + +The library maintains a count of the number of scanlines returned so far +in the output_scanline field of the JPEG object. Usually you can just use +this variable as the loop counter, so that the loop test looks like +"while (cinfo.output_scanline < cinfo.output_height)". (Note that the test +should NOT be against image_height, unless you never use scaling. The +image_height field is the height of the original unscaled image.) +The return value always equals the change in the value of output_scanline. + +If you don't use a suspending data source, it is safe to assume that +jpeg_read_scanlines() reads at least one scanline per call, until the +bottom of the image has been reached. + +If you use a buffer larger than one scanline, it is NOT safe to assume that +jpeg_read_scanlines() fills it. (The current implementation returns only a +few scanlines per call, no matter how large a buffer you pass.) So you must +always provide a loop that calls jpeg_read_scanlines() repeatedly until the +whole image has been read. + + +7. jpeg_finish_decompress(...); + +After all the image data has been read, call jpeg_finish_decompress() to +complete the decompression cycle. This causes working memory associated +with the JPEG object to be released. + +Typical code: + + jpeg_finish_decompress(&cinfo); + +If using the stdio source manager, don't forget to close the source stdio +stream if necessary. + +It is an error to call jpeg_finish_decompress() before reading the correct +total number of scanlines. If you wish to abort decompression, call +jpeg_abort() as discussed below. + +After completing a decompression cycle, you may dispose of the JPEG object as +discussed next, or you may use it to decompress another image. In that case +return to step 2 or 3 as appropriate. If you do not change the source +manager, the next image will be read from the same source. + + +8. Release the JPEG decompression object. + +When you are done with a JPEG decompression object, destroy it by calling +jpeg_destroy_decompress() or jpeg_destroy(). The previous discussion of +destroying compression objects applies here too. + +Typical code: + + jpeg_destroy_decompress(&cinfo); + + +9. Aborting. + +You can abort a decompression cycle by calling jpeg_destroy_decompress() or +jpeg_destroy() if you don't need the JPEG object any more, or +jpeg_abort_decompress() or jpeg_abort() if you want to reuse the object. +The previous discussion of aborting compression cycles applies here too. + + +Mechanics of usage: include files, linking, etc +----------------------------------------------- + +Applications using the JPEG library should include the header file jpeglib.h +to obtain declarations of data types and routines. Before including +jpeglib.h, include system headers that define at least the typedefs FILE and +size_t. On ANSI-conforming systems, including <stdio.h> is sufficient; on +older Unix systems, you may need <sys/types.h> to define size_t. + +If the application needs to refer to individual JPEG library error codes, also +include jerror.h to define those symbols. + +jpeglib.h indirectly includes the files jconfig.h and jmorecfg.h. If you are +installing the JPEG header files in a system directory, you will want to +install all four files: jpeglib.h, jerror.h, jconfig.h, jmorecfg.h. + +The most convenient way to include the JPEG code into your executable program +is to prepare a library file ("libjpeg.a", or a corresponding name on non-Unix +machines) and reference it at your link step. If you use only half of the +library (only compression or only decompression), only that much code will be +included from the library, unless your linker is hopelessly brain-damaged. +The supplied makefiles build libjpeg.a automatically (see install.doc). + +While you can build the JPEG library as a shared library if the whim strikes +you, we don't really recommend it. The trouble with shared libraries is that +at some point you'll probably try to substitute a new version of the library +without recompiling the calling applications. That generally doesn't work +because the parameter struct declarations usually change with each new +version. In other words, the library's API is *not* guaranteed binary +compatible across versions; we only try to ensure source-code compatibility. +(In hindsight, it might have been smarter to hide the parameter structs from +applications and introduce a ton of access functions instead. Too late now, +however.) + +On some systems your application may need to set up a signal handler to ensure +that temporary files are deleted if the program is interrupted. This is most +critical if you are on MS-DOS and use the jmemdos.c memory manager back end; +it will try to grab extended memory for temp files, and that space will NOT be +freed automatically. See cjpeg.c or djpeg.c for an example signal handler. + +It may be worth pointing out that the core JPEG library does not actually +require the stdio library: only the default source/destination managers and +error handler need it. You can use the library in a stdio-less environment +if you replace those modules and use jmemnobs.c (or another memory manager of +your own devising). More info about the minimum system library requirements +may be found in jinclude.h. + + +ADVANCED FEATURES +================= + +Compression parameter selection +------------------------------- + +This section describes all the optional parameters you can set for JPEG +compression, as well as the "helper" routines provided to assist in this +task. Proper setting of some parameters requires detailed understanding +of the JPEG standard; if you don't know what a parameter is for, it's best +not to mess with it! See REFERENCES in the README file for pointers to +more info about JPEG. + +It's a good idea to call jpeg_set_defaults() first, even if you plan to set +all the parameters; that way your code is more likely to work with future JPEG +libraries that have additional parameters. For the same reason, we recommend +you use a helper routine where one is provided, in preference to twiddling +cinfo fields directly. + +The helper routines are: + +jpeg_set_defaults (j_compress_ptr cinfo) + This routine sets all JPEG parameters to reasonable defaults, using + only the input image's color space (field in_color_space, which must + already be set in cinfo). Many applications will only need to use + this routine and perhaps jpeg_set_quality(). + +jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) + Sets the JPEG file's colorspace (field jpeg_color_space) as specified, + and sets other color-space-dependent parameters appropriately. See + "Special color spaces", below, before using this. A large number of + parameters, including all per-component parameters, are set by this + routine; if you want to twiddle individual parameters you should call + jpeg_set_colorspace() before rather than after. + +jpeg_default_colorspace (j_compress_ptr cinfo) + Selects an appropriate JPEG colorspace based on cinfo->in_color_space, + and calls jpeg_set_colorspace(). This is actually a subroutine of + jpeg_set_defaults(). It's broken out in case you want to change + just the colorspace-dependent JPEG parameters. + +jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) + Constructs JPEG quantization tables appropriate for the indicated + quality setting. The quality value is expressed on the 0..100 scale + recommended by IJG (cjpeg's "-quality" switch uses this routine). + Note that the exact mapping from quality values to tables may change + in future IJG releases as more is learned about DCT quantization. + If the force_baseline parameter is TRUE, then the quantization table + entries are constrained to the range 1..255 for full JPEG baseline + compatibility. In the current implementation, this only makes a + difference for quality settings below 25, and it effectively prevents + very small/low quality files from being generated. The IJG decoder + is capable of reading the non-baseline files generated at low quality + settings when force_baseline is FALSE, but other decoders may not be. + +jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, + boolean force_baseline) + Same as jpeg_set_quality() except that the generated tables are the + sample tables given in the JPEC spec section K.1, multiplied by the + specified scale factor (which is expressed as a percentage; thus + scale_factor = 100 reproduces the spec's tables). Note that larger + scale factors give lower quality. This entry point is useful for + conforming to the Adobe PostScript DCT conventions, but we do not + recommend linear scaling as a user-visible quality scale otherwise. + force_baseline again constrains the computed table entries to 1..255. + +int jpeg_quality_scaling (int quality) + Converts a value on the IJG-recommended quality scale to a linear + scaling percentage. Note that this routine may change or go away + in future releases --- IJG may choose to adopt a scaling method that + can't be expressed as a simple scalar multiplier, in which case the + premise of this routine collapses. Caveat user. + +jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, boolean force_baseline) + Allows an arbitrary quantization table to be created. which_tbl + indicates which table slot to fill. basic_table points to an array + of 64 unsigned ints given in normal array order. These values are + multiplied by scale_factor/100 and then clamped to the range 1..65535 + (or to 1..255 if force_baseline is TRUE). + CAUTION: prior to library version 6a, jpeg_add_quant_table expected + the basic table to be given in JPEG zigzag order. If you need to + write code that works with either older or newer versions of this + routine, you must check the library version number. Something like + "#if JPEG_LIB_VERSION >= 61" is the right test. + +jpeg_simple_progression (j_compress_ptr cinfo) + Generates a default scan script for writing a progressive-JPEG file. + This is the recommended method of creating a progressive file, + unless you want to make a custom scan sequence. You must ensure that + the JPEG color space is set correctly before calling this routine. + + +Compression parameters (cinfo fields) include: + +J_DCT_METHOD dct_method + Selects the algorithm used for the DCT step. Choices are: + JDCT_ISLOW: slow but accurate integer algorithm + JDCT_IFAST: faster, less accurate integer method + JDCT_FLOAT: floating-point method + JDCT_DEFAULT: default method (normally JDCT_ISLOW) + JDCT_FASTEST: fastest method (normally JDCT_IFAST) + The FLOAT method is very slightly more accurate than the ISLOW method, + but may give different results on different machines due to varying + roundoff behavior. The integer methods should give the same results + on all machines. On machines with sufficiently fast FP hardware, the + floating-point method may also be the fastest. The IFAST method is + considerably less accurate than the other two; its use is not + recommended if high quality is a concern. JDCT_DEFAULT and + JDCT_FASTEST are macros configurable by each installation. + +J_COLOR_SPACE jpeg_color_space +int num_components + The JPEG color space and corresponding number of components; see + "Special color spaces", below, for more info. We recommend using + jpeg_set_color_space() if you want to change these. + +boolean optimize_coding + TRUE causes the compressor to compute optimal Huffman coding tables + for the image. This requires an extra pass over the data and + therefore costs a good deal of space and time. The default is + FALSE, which tells the compressor to use the supplied or default + Huffman tables. In most cases optimal tables save only a few percent + of file size compared to the default tables. Note that when this is + TRUE, you need not supply Huffman tables at all, and any you do + supply will be overwritten. + +unsigned int restart_interval +int restart_in_rows + To emit restart markers in the JPEG file, set one of these nonzero. + Set restart_interval to specify the exact interval in MCU blocks. + Set restart_in_rows to specify the interval in MCU rows. (If + restart_in_rows is not 0, then restart_interval is set after the + image width in MCUs is computed.) Defaults are zero (no restarts). + One restart marker per MCU row is often a good choice. + NOTE: the overhead of restart markers is higher in grayscale JPEG + files than in color files, and MUCH higher in progressive JPEGs. + If you use restarts, you may want to use larger intervals in those + cases. + +const jpeg_scan_info * scan_info +int num_scans + By default, scan_info is NULL; this causes the compressor to write a + single-scan sequential JPEG file. If not NULL, scan_info points to + an array of scan definition records of length num_scans. The + compressor will then write a JPEG file having one scan for each scan + definition record. This is used to generate noninterleaved or + progressive JPEG files. The library checks that the scan array + defines a valid JPEG scan sequence. (jpeg_simple_progression creates + a suitable scan definition array for progressive JPEG.) This is + discussed further under "Progressive JPEG support". + +int smoothing_factor + If non-zero, the input image is smoothed; the value should be 1 for + minimal smoothing to 100 for maximum smoothing. Consult jcsample.c + for details of the smoothing algorithm. The default is zero. + +boolean write_JFIF_header + If TRUE, a JFIF APP0 marker is emitted. jpeg_set_defaults() and + jpeg_set_colorspace() set this TRUE if a JFIF-legal JPEG color space + (ie, YCbCr or grayscale) is selected, otherwise FALSE. + +UINT8 JFIF_major_version +UINT8 JFIF_minor_version + The version number to be written into the JFIF marker. + jpeg_set_defaults() initializes the version to 1.01 (major=minor=1). + You should set it to 1.02 (major=1, minor=2) if you plan to write + any JFIF 1.02 extension markers. + +UINT8 density_unit +UINT16 X_density +UINT16 Y_density + The resolution information to be written into the JFIF marker; + not used otherwise. density_unit may be 0 for unknown, + 1 for dots/inch, or 2 for dots/cm. The default values are 0,1,1 + indicating square pixels of unknown size. + +boolean write_Adobe_marker + If TRUE, an Adobe APP14 marker is emitted. jpeg_set_defaults() and + jpeg_set_colorspace() set this TRUE if JPEG color space RGB, CMYK, + or YCCK is selected, otherwise FALSE. It is generally a bad idea + to set both write_JFIF_header and write_Adobe_marker. In fact, + you probably shouldn't change the default settings at all --- the + default behavior ensures that the JPEG file's color space can be + recognized by the decoder. + +JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS] + Pointers to coefficient quantization tables, one per table slot, + or NULL if no table is defined for a slot. Usually these should + be set via one of the above helper routines; jpeg_add_quant_table() + is general enough to define any quantization table. The other + routines will set up table slot 0 for luminance quality and table + slot 1 for chrominance. + +JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS] +JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS] + Pointers to Huffman coding tables, one per table slot, or NULL if + no table is defined for a slot. Slots 0 and 1 are filled with the + JPEG sample tables by jpeg_set_defaults(). If you need to allocate + more table structures, jpeg_alloc_huff_table() may be used. + Note that optimal Huffman tables can be computed for an image + by setting optimize_coding, as discussed above; there's seldom + any need to mess with providing your own Huffman tables. + +There are some additional cinfo fields which are not documented here +because you currently can't change them; for example, you can't set +arith_code TRUE because arithmetic coding is unsupported. + + +Per-component parameters are stored in the struct cinfo.comp_info[i] for +component number i. Note that components here refer to components of the +JPEG color space, *not* the source image color space. A suitably large +comp_info[] array is allocated by jpeg_set_defaults(); if you choose not +to use that routine, it's up to you to allocate the array. + +int component_id + The one-byte identifier code to be recorded in the JPEG file for + this component. For the standard color spaces, we recommend you + leave the default values alone. + +int h_samp_factor +int v_samp_factor + Horizontal and vertical sampling factors for the component; must + be 1..4 according to the JPEG standard. Note that larger sampling + factors indicate a higher-resolution component; many people find + this behavior quite unintuitive. The default values are 2,2 for + luminance components and 1,1 for chrominance components, except + for grayscale where 1,1 is used. + +int quant_tbl_no + Quantization table number for component. The default value is + 0 for luminance components and 1 for chrominance components. + +int dc_tbl_no +int ac_tbl_no + DC and AC entropy coding table numbers. The default values are + 0 for luminance components and 1 for chrominance components. + +int component_index + Must equal the component's index in comp_info[]. (Beginning in + release v6, the compressor library will fill this in automatically; + you don't have to.) + + +Decompression parameter selection +--------------------------------- + +Decompression parameter selection is somewhat simpler than compression +parameter selection, since all of the JPEG internal parameters are +recorded in the source file and need not be supplied by the application. +(Unless you are working with abbreviated files, in which case see +"Abbreviated datastreams", below.) Decompression parameters control +the postprocessing done on the image to deliver it in a format suitable +for the application's use. Many of the parameters control speed/quality +tradeoffs, in which faster decompression may be obtained at the price of +a poorer-quality image. The defaults select the highest quality (slowest) +processing. + +The following fields in the JPEG object are set by jpeg_read_header() and +may be useful to the application in choosing decompression parameters: + +JDIMENSION image_width Width and height of image +JDIMENSION image_height +int num_components Number of color components +J_COLOR_SPACE jpeg_color_space Colorspace of image +boolean saw_JFIF_marker TRUE if a JFIF APP0 marker was seen + UINT8 JFIF_major_version Version information from JFIF marker + UINT8 JFIF_minor_version + UINT8 density_unit Resolution data from JFIF marker + UINT16 X_density + UINT16 Y_density +boolean saw_Adobe_marker TRUE if an Adobe APP14 marker was seen + UINT8 Adobe_transform Color transform code from Adobe marker + +The JPEG color space, unfortunately, is something of a guess since the JPEG +standard proper does not provide a way to record it. In practice most files +adhere to the JFIF or Adobe conventions, and the decoder will recognize these +correctly. See "Special color spaces", below, for more info. + + +The decompression parameters that determine the basic properties of the +returned image are: + +J_COLOR_SPACE out_color_space + Output color space. jpeg_read_header() sets an appropriate default + based on jpeg_color_space; typically it will be RGB or grayscale. + The application can change this field to request output in a different + colorspace. For example, set it to JCS_GRAYSCALE to get grayscale + output from a color file. (This is useful for previewing: grayscale + output is faster than full color since the color components need not + be processed.) Note that not all possible color space transforms are + currently implemented; you may need to extend jdcolor.c if you want an + unusual conversion. + +unsigned int scale_num, scale_denom + Scale the image by the fraction scale_num/scale_denom. Default is + 1/1, or no scaling. Currently, the only supported scaling ratios + are 1/1, 1/2, 1/4, and 1/8. (The library design allows for arbitrary + scaling ratios but this is not likely to be implemented any time soon.) + Smaller scaling ratios permit significantly faster decoding since + fewer pixels need be processed and a simpler IDCT method can be used. + +boolean quantize_colors + If set TRUE, colormapped output will be delivered. Default is FALSE, + meaning that full-color output will be delivered. + +The next three parameters are relevant only if quantize_colors is TRUE. + +int desired_number_of_colors + Maximum number of colors to use in generating a library-supplied color + map (the actual number of colors is returned in a different field). + Default 256. Ignored when the application supplies its own color map. + +boolean two_pass_quantize + If TRUE, an extra pass over the image is made to select a custom color + map for the image. This usually looks a lot better than the one-size- + fits-all colormap that is used otherwise. Default is TRUE. Ignored + when the application supplies its own color map. + +J_DITHER_MODE dither_mode + Selects color dithering method. Supported values are: + JDITHER_NONE no dithering: fast, very low quality + JDITHER_ORDERED ordered dither: moderate speed and quality + JDITHER_FS Floyd-Steinberg dither: slow, high quality + Default is JDITHER_FS. (At present, ordered dither is implemented + only in the single-pass, standard-colormap case. If you ask for + ordered dither when two_pass_quantize is TRUE or when you supply + an external color map, you'll get F-S dithering.) + +When quantize_colors is TRUE, the target color map is described by the next +two fields. colormap is set to NULL by jpeg_read_header(). The application +can supply a color map by setting colormap non-NULL and setting +actual_number_of_colors to the map size. Otherwise, jpeg_start_decompress() +selects a suitable color map and sets these two fields itself. +[Implementation restriction: at present, an externally supplied colormap is +only accepted for 3-component output color spaces.] + +JSAMPARRAY colormap + The color map, represented as a 2-D pixel array of out_color_components + rows and actual_number_of_colors columns. Ignored if not quantizing. + CAUTION: if the JPEG library creates its own colormap, the storage + pointed to by this field is released by jpeg_finish_decompress(). + Copy the colormap somewhere else first, if you want to save it. + +int actual_number_of_colors + The number of colors in the color map. + +Additional decompression parameters that the application may set include: + +J_DCT_METHOD dct_method + Selects the algorithm used for the DCT step. Choices are the same + as described above for compression. + +boolean do_fancy_upsampling + If TRUE, do careful upsampling of chroma components. If FALSE, + a faster but sloppier method is used. Default is TRUE. The visual + impact of the sloppier method is often very small. + +boolean do_block_smoothing + If TRUE, interblock smoothing is applied in early stages of decoding + progressive JPEG files; if FALSE, not. Default is TRUE. Early + progression stages look "fuzzy" with smoothing, "blocky" without. + In any case, block smoothing ceases to be applied after the first few + AC coefficients are known to full accuracy, so it is relevant only + when using buffered-image mode for progressive images. + +boolean enable_1pass_quant +boolean enable_external_quant +boolean enable_2pass_quant + These are significant only in buffered-image mode, which is + described in its own section below. + + +The output image dimensions are given by the following fields. These are +computed from the source image dimensions and the decompression parameters +by jpeg_start_decompress(). You can also call jpeg_calc_output_dimensions() +to obtain the values that will result from the current parameter settings. +This can be useful if you are trying to pick a scaling ratio that will get +close to a desired target size. It's also important if you are using the +JPEG library's memory manager to allocate output buffer space, because you +are supposed to request such buffers *before* jpeg_start_decompress(). + +JDIMENSION output_width Actual dimensions of output image. +JDIMENSION output_height +int out_color_components Number of color components in out_color_space. +int output_components Number of color components returned. +int rec_outbuf_height Recommended height of scanline buffer. + +When quantizing colors, output_components is 1, indicating a single color map +index per pixel. Otherwise it equals out_color_components. The output arrays +are required to be output_width * output_components JSAMPLEs wide. + +rec_outbuf_height is the recommended minimum height (in scanlines) of the +buffer passed to jpeg_read_scanlines(). If the buffer is smaller, the +library will still work, but time will be wasted due to unnecessary data +copying. In high-quality modes, rec_outbuf_height is always 1, but some +faster, lower-quality modes set it to larger values (typically 2 to 4). +If you are going to ask for a high-speed processing mode, you may as well +go to the trouble of honoring rec_outbuf_height so as to avoid data copying. +(An output buffer larger than rec_outbuf_height lines is OK, but won't +provide any material speed improvement over that height.) + + +Special color spaces +-------------------- + +The JPEG standard itself is "color blind" and doesn't specify any particular +color space. It is customary to convert color data to a luminance/chrominance +color space before compressing, since this permits greater compression. The +existing de-facto JPEG file format standards specify YCbCr or grayscale data +(JFIF), or grayscale, RGB, YCbCr, CMYK, or YCCK (Adobe). For special +applications such as multispectral images, other color spaces can be used, +but it must be understood that such files will be unportable. + +The JPEG library can handle the most common colorspace conversions (namely +RGB <=> YCbCr and CMYK <=> YCCK). It can also deal with data of an unknown +color space, passing it through without conversion. If you deal extensively +with an unusual color space, you can easily extend the library to understand +additional color spaces and perform appropriate conversions. + +For compression, the source data's color space is specified by field +in_color_space. This is transformed to the JPEG file's color space given +by jpeg_color_space. jpeg_set_defaults() chooses a reasonable JPEG color +space depending on in_color_space, but you can override this by calling +jpeg_set_colorspace(). Of course you must select a supported transformation. +jccolor.c currently supports the following transformations: + RGB => YCbCr + RGB => GRAYSCALE + YCbCr => GRAYSCALE + CMYK => YCCK +plus the null transforms: GRAYSCALE => GRAYSCALE, RGB => RGB, +YCbCr => YCbCr, CMYK => CMYK, YCCK => YCCK, and UNKNOWN => UNKNOWN. + +The de-facto file format standards (JFIF and Adobe) specify APPn markers that +indicate the color space of the JPEG file. It is important to ensure that +these are written correctly, or omitted if the JPEG file's color space is not +one of the ones supported by the de-facto standards. jpeg_set_colorspace() +will set the compression parameters to include or omit the APPn markers +properly, so long as it is told the truth about the JPEG color space. +For example, if you are writing some random 3-component color space without +conversion, don't try to fake out the library by setting in_color_space and +jpeg_color_space to JCS_YCbCr; use JCS_UNKNOWN. You may want to write an +APPn marker of your own devising to identify the colorspace --- see "Special +markers", below. + +When told that the color space is UNKNOWN, the library will default to using +luminance-quality compression parameters for all color components. You may +well want to change these parameters. See the source code for +jpeg_set_colorspace(), in jcparam.c, for details. + +For decompression, the JPEG file's color space is given in jpeg_color_space, +and this is transformed to the output color space out_color_space. +jpeg_read_header's setting of jpeg_color_space can be relied on if the file +conforms to JFIF or Adobe conventions, but otherwise it is no better than a +guess. If you know the JPEG file's color space for certain, you can override +jpeg_read_header's guess by setting jpeg_color_space. jpeg_read_header also +selects a default output color space based on (its guess of) jpeg_color_space; +set out_color_space to override this. Again, you must select a supported +transformation. jdcolor.c currently supports + YCbCr => GRAYSCALE + YCbCr => RGB + GRAYSCALE => RGB + YCCK => CMYK +as well as the null transforms. (Since GRAYSCALE=>RGB is provided, an +application can force grayscale JPEGs to look like color JPEGs if it only +wants to handle one case.) + +The two-pass color quantizer, jquant2.c, is specialized to handle RGB data +(it weights distances appropriately for RGB colors). You'll need to modify +the code if you want to use it for non-RGB output color spaces. Note that +jquant2.c is used to map to an application-supplied colormap as well as for +the normal two-pass colormap selection process. + +CAUTION: it appears that Adobe Photoshop writes inverted data in CMYK JPEG +files: 0 represents 100% ink coverage, rather than 0% ink as you'd expect. +This is arguably a bug in Photoshop, but if you need to work with Photoshop +CMYK files, you will have to deal with it in your application. We cannot +"fix" this in the library by inverting the data during the CMYK<=>YCCK +transform, because that would break other applications, notably Ghostscript. +Photoshop versions prior to 3.0 write EPS files containing JPEG-encoded CMYK +data in the same inverted-YCCK representation used in bare JPEG files, but +the surrounding PostScript code performs an inversion using the PS image +operator. I am told that Photoshop 3.0 will write uninverted YCCK in +EPS/JPEG files, and will omit the PS-level inversion. (But the data +polarity used in bare JPEG files will not change in 3.0.) In either case, +the JPEG library must not invert the data itself, or else Ghostscript would +read these EPS files incorrectly. + + +Error handling +-------------- + +When the default error handler is used, any error detected inside the JPEG +routines will cause a message to be printed on stderr, followed by exit(). +You can supply your own error handling routines to override this behavior +and to control the treatment of nonfatal warnings and trace/debug messages. +The file example.c illustrates the most common case, which is to have the +application regain control after an error rather than exiting. + +The JPEG library never writes any message directly; it always goes through +the error handling routines. Three classes of messages are recognized: + * Fatal errors: the library cannot continue. + * Warnings: the library can continue, but the data is corrupt, and a + damaged output image is likely to result. + * Trace/informational messages. These come with a trace level indicating + the importance of the message; you can control the verbosity of the + program by adjusting the maximum trace level that will be displayed. + +You may, if you wish, simply replace the entire JPEG error handling module +(jerror.c) with your own code. However, you can avoid code duplication by +only replacing some of the routines depending on the behavior you need. +This is accomplished by calling jpeg_std_error() as usual, but then overriding +some of the method pointers in the jpeg_error_mgr struct, as illustrated by +example.c. + +All of the error handling routines will receive a pointer to the JPEG object +(a j_common_ptr which points to either a jpeg_compress_struct or a +jpeg_decompress_struct; if you need to tell which, test the is_decompressor +field). This struct includes a pointer to the error manager struct in its +"err" field. Frequently, custom error handler routines will need to access +additional data which is not known to the JPEG library or the standard error +handler. The most convenient way to do this is to embed either the JPEG +object or the jpeg_error_mgr struct in a larger structure that contains +additional fields; then casting the passed pointer provides access to the +additional fields. Again, see example.c for one way to do it. (Beginning +with IJG version 6b, there is also a void pointer "client_data" in each +JPEG object, which the application can also use to find related data. +The library does not touch client_data at all.) + +The individual methods that you might wish to override are: + +error_exit (j_common_ptr cinfo) + Receives control for a fatal error. Information sufficient to + generate the error message has been stored in cinfo->err; call + output_message to display it. Control must NOT return to the caller; + generally this routine will exit() or longjmp() somewhere. + Typically you would override this routine to get rid of the exit() + default behavior. Note that if you continue processing, you should + clean up the JPEG object with jpeg_abort() or jpeg_destroy(). + +output_message (j_common_ptr cinfo) + Actual output of any JPEG message. Override this to send messages + somewhere other than stderr. Note that this method does not know + how to generate a message, only where to send it. + +format_message (j_common_ptr cinfo, char * buffer) + Constructs a readable error message string based on the error info + stored in cinfo->err. This method is called by output_message. Few + applications should need to override this method. One possible + reason for doing so is to implement dynamic switching of error message + language. + +emit_message (j_common_ptr cinfo, int msg_level) + Decide whether or not to emit a warning or trace message; if so, + calls output_message. The main reason for overriding this method + would be to abort on warnings. msg_level is -1 for warnings, + 0 and up for trace messages. + +Only error_exit() and emit_message() are called from the rest of the JPEG +library; the other two are internal to the error handler. + +The actual message texts are stored in an array of strings which is pointed to +by the field err->jpeg_message_table. The messages are numbered from 0 to +err->last_jpeg_message, and it is these code numbers that are used in the +JPEG library code. You could replace the message texts (for instance, with +messages in French or German) by changing the message table pointer. See +jerror.h for the default texts. CAUTION: this table will almost certainly +change or grow from one library version to the next. + +It may be useful for an application to add its own message texts that are +handled by the same mechanism. The error handler supports a second "add-on" +message table for this purpose. To define an addon table, set the pointer +err->addon_message_table and the message numbers err->first_addon_message and +err->last_addon_message. If you number the addon messages beginning at 1000 +or so, you won't have to worry about conflicts with the library's built-in +messages. See the sample applications cjpeg/djpeg for an example of using +addon messages (the addon messages are defined in cderror.h). + +Actual invocation of the error handler is done via macros defined in jerror.h: + ERREXITn(...) for fatal errors + WARNMSn(...) for corrupt-data warnings + TRACEMSn(...) for trace and informational messages. +These macros store the message code and any additional parameters into the +error handler struct, then invoke the error_exit() or emit_message() method. +The variants of each macro are for varying numbers of additional parameters. +The additional parameters are inserted into the generated message using +standard printf() format codes. + +See jerror.h and jerror.c for further details. + + +Compressed data handling (source and destination managers) +---------------------------------------------------------- + +The JPEG compression library sends its compressed data to a "destination +manager" module. The default destination manager just writes the data to a +stdio stream, but you can provide your own manager to do something else. +Similarly, the decompression library calls a "source manager" to obtain the +compressed data; you can provide your own source manager if you want the data +to come from somewhere other than a stdio stream. + +In both cases, compressed data is processed a bufferload at a time: the +destination or source manager provides a work buffer, and the library invokes +the manager only when the buffer is filled or emptied. (You could define a +one-character buffer to force the manager to be invoked for each byte, but +that would be rather inefficient.) The buffer's size and location are +controlled by the manager, not by the library. For example, if you desired to +decompress a JPEG datastream that was all in memory, you could just make the +buffer pointer and length point to the original data in memory. Then the +buffer-reload procedure would be invoked only if the decompressor ran off the +end of the datastream, which would indicate an erroneous datastream. + +The work buffer is defined as an array of datatype JOCTET, which is generally +"char" or "unsigned char". On a machine where char is not exactly 8 bits +wide, you must define JOCTET as a wider data type and then modify the data +source and destination modules to transcribe the work arrays into 8-bit units +on external storage. + +A data destination manager struct contains a pointer and count defining the +next byte to write in the work buffer and the remaining free space: + + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + +The library increments the pointer and decrements the count until the buffer +is filled. The manager's empty_output_buffer method must reset the pointer +and count. The manager is expected to remember the buffer's starting address +and total size in private fields not visible to the library. + +A data destination manager provides three methods: + +init_destination (j_compress_ptr cinfo) + Initialize destination. This is called by jpeg_start_compress() + before any data is actually written. It must initialize + next_output_byte and free_in_buffer. free_in_buffer must be + initialized to a positive value. + +empty_output_buffer (j_compress_ptr cinfo) + This is called whenever the buffer has filled (free_in_buffer + reaches zero). In typical applications, it should write out the + *entire* buffer (use the saved start address and buffer length; + ignore the current state of next_output_byte and free_in_buffer). + Then reset the pointer & count to the start of the buffer, and + return TRUE indicating that the buffer has been dumped. + free_in_buffer must be set to a positive value when TRUE is + returned. A FALSE return should only be used when I/O suspension is + desired (this operating mode is discussed in the next section). + +term_destination (j_compress_ptr cinfo) + Terminate destination --- called by jpeg_finish_compress() after all + data has been written. In most applications, this must flush any + data remaining in the buffer. Use either next_output_byte or + free_in_buffer to determine how much data is in the buffer. + +term_destination() is NOT called by jpeg_abort() or jpeg_destroy(). If you +want the destination manager to be cleaned up during an abort, you must do it +yourself. + +You will also need code to create a jpeg_destination_mgr struct, fill in its +method pointers, and insert a pointer to the struct into the "dest" field of +the JPEG compression object. This can be done in-line in your setup code if +you like, but it's probably cleaner to provide a separate routine similar to +the jpeg_stdio_dest() routine of the supplied destination manager. + +Decompression source managers follow a parallel design, but with some +additional frammishes. The source manager struct contains a pointer and count +defining the next byte to read from the work buffer and the number of bytes +remaining: + + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + +The library increments the pointer and decrements the count until the buffer +is emptied. The manager's fill_input_buffer method must reset the pointer and +count. In most applications, the manager must remember the buffer's starting +address and total size in private fields not visible to the library. + +A data source manager provides five methods: + +init_source (j_decompress_ptr cinfo) + Initialize source. This is called by jpeg_read_header() before any + data is actually read. Unlike init_destination(), it may leave + bytes_in_buffer set to 0 (in which case a fill_input_buffer() call + will occur immediately). + +fill_input_buffer (j_decompress_ptr cinfo) + This is called whenever bytes_in_buffer has reached zero and more + data is wanted. In typical applications, it should read fresh data + into the buffer (ignoring the current state of next_input_byte and + 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. bytes_in_buffer MUST be set to a positive value + if TRUE is returned. A FALSE return should only be used when I/O + suspension is desired (this mode is discussed in the next section). + +skip_input_data (j_decompress_ptr cinfo, long num_bytes) + Skip num_bytes worth of data. The buffer pointer and count should + be advanced over num_bytes input bytes, refilling the buffer as + needed. This is used to skip over a potentially large amount of + uninteresting data (such as an APPn marker). In some applications + it may be possible to optimize away the reading of the skipped data, + but it's not clear that being smart is worth much trouble; large + skips are uncommon. bytes_in_buffer may be zero on return. + A zero or negative skip count should be treated as a no-op. + +resync_to_restart (j_decompress_ptr cinfo, int desired) + This routine is called only when the decompressor has failed to find + a restart (RSTn) marker where one is expected. Its mission is to + find a suitable point for resuming decompression. For most + applications, we recommend that you just use the default resync + procedure, jpeg_resync_to_restart(). However, if you are able to back + up in the input data stream, or if you have a-priori knowledge about + the likely location of restart markers, you may be able to do better. + Read the read_restart_marker() and jpeg_resync_to_restart() routines + in jdmarker.c if you think you'd like to implement your own resync + procedure. + +term_source (j_decompress_ptr cinfo) + Terminate source --- called by jpeg_finish_decompress() after all + data has been read. Often a no-op. + +For both fill_input_buffer() and skip_input_data(), there is no such thing +as an EOF return. If the end of the file has been reached, the routine has +a choice of exiting via 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. In pathological cases, the decompressor +may swallow the EOI and again demand data ... just keep feeding it fake EOIs. +jdatasrc.c illustrates the recommended error recovery behavior. + +term_source() is NOT called by jpeg_abort() or jpeg_destroy(). If you want +the source manager to be cleaned up during an abort, you must do it yourself. + +You will also need code to create a jpeg_source_mgr struct, fill in its method +pointers, and insert a pointer to the struct into the "src" field of the JPEG +decompression object. This can be done in-line in your setup code if you +like, but it's probably cleaner to provide a separate routine similar to the +jpeg_stdio_src() routine of the supplied source manager. + +For more information, consult the stdio source and destination managers +in jdatasrc.c and jdatadst.c. + + +I/O suspension +-------------- + +Some applications need to use the JPEG library as an incremental memory-to- +memory filter: when the compressed data buffer is filled or emptied, they want +control to return to the outer loop, rather than expecting that the buffer can +be emptied or reloaded within the data source/destination manager subroutine. +The library supports this need by providing an "I/O suspension" mode, which we +describe in this section. + +The I/O suspension mode is not a panacea: nothing is guaranteed about the +maximum amount of time spent in any one call to the library, so it will not +eliminate response-time problems in single-threaded applications. If you +need guaranteed response time, we suggest you "bite the bullet" and implement +a real multi-tasking capability. + +To use I/O suspension, cooperation is needed between the calling application +and the data source or destination manager; you will always need a custom +source/destination manager. (Please read the previous section if you haven't +already.) The basic idea is that the empty_output_buffer() or +fill_input_buffer() routine is a no-op, merely returning FALSE to indicate +that it has done nothing. Upon seeing this, the JPEG library suspends +operation and returns to its caller. The surrounding application is +responsible for emptying or refilling the work buffer before calling the +JPEG library again. + +Compression suspension: + +For compression suspension, use an empty_output_buffer() routine that returns +FALSE; typically it will not do anything else. This will cause the +compressor to return to the caller of jpeg_write_scanlines(), with the return +value indicating that not all the supplied scanlines have been accepted. +The application must make more room in the output buffer, adjust the output +buffer pointer/count appropriately, and then call jpeg_write_scanlines() +again, pointing to the first unconsumed scanline. + +When forced to suspend, the compressor will backtrack to a convenient stopping +point (usually the start of the current MCU); it will regenerate some output +data when restarted. Therefore, although empty_output_buffer() is only +called when the buffer is filled, you should NOT write out the entire buffer +after a suspension. Write only the data up to the current position of +next_output_byte/free_in_buffer. The data beyond that point will be +regenerated after resumption. + +Because of the backtracking behavior, a good-size output buffer is essential +for efficiency; you don't want the compressor to suspend often. (In fact, an +overly small buffer could lead to infinite looping, if a single MCU required +more data than would fit in the buffer.) We recommend a buffer of at least +several Kbytes. You may want to insert explicit code to ensure that you don't +call jpeg_write_scanlines() unless there is a reasonable amount of space in +the output buffer; in other words, flush the buffer before trying to compress +more data. + +The compressor does not allow suspension while it is trying to write JPEG +markers at the beginning and end of the file. This means that: + * At the beginning of a compression operation, there must be enough free + space in the output buffer to hold the header markers (typically 600 or + so bytes). The recommended buffer size is bigger than this anyway, so + this is not a problem as long as you start with an empty buffer. However, + this restriction might catch you if you insert large special markers, such + as a JFIF thumbnail image, without flushing the buffer afterwards. + * When you call jpeg_finish_compress(), there must be enough space in the + output buffer to emit any buffered data and the final EOI marker. In the + current implementation, half a dozen bytes should suffice for this, but + for safety's sake we recommend ensuring that at least 100 bytes are free + before calling jpeg_finish_compress(). + +A more significant restriction is that jpeg_finish_compress() cannot suspend. +This means you cannot use suspension with multi-pass operating modes, namely +Huffman code optimization and multiple-scan output. Those modes write the +whole file during jpeg_finish_compress(), which will certainly result in +buffer overrun. (Note that this restriction applies only to compression, +not decompression. The decompressor supports input suspension in all of its +operating modes.) + +Decompression suspension: + +For decompression suspension, use a fill_input_buffer() routine that simply +returns FALSE (except perhaps during error recovery, as discussed below). +This will cause the decompressor to return to its caller with an indication +that suspension has occurred. This can happen at four places: + * jpeg_read_header(): will return JPEG_SUSPENDED. + * jpeg_start_decompress(): will return FALSE, rather than its usual TRUE. + * jpeg_read_scanlines(): will return the number of scanlines already + completed (possibly 0). + * jpeg_finish_decompress(): will return FALSE, rather than its usual TRUE. +The surrounding application must recognize these cases, load more data into +the input buffer, and repeat the call. In the case of jpeg_read_scanlines(), +increment the passed pointers past any scanlines successfully read. + +Just as with compression, the decompressor will typically backtrack to a +convenient restart point before suspending. When fill_input_buffer() is +called, next_input_byte/bytes_in_buffer point to the current restart point, +which is where the decompressor will backtrack to if FALSE is returned. +The data beyond that position must NOT be discarded if you suspend; it needs +to be re-read upon resumption. In most implementations, you'll need to shift +this data down to the start of your work buffer and then load more data after +it. Again, this behavior means that a several-Kbyte work buffer is essential +for decent performance; furthermore, you should load a reasonable amount of +new data before resuming decompression. (If you loaded, say, only one new +byte each time around, you could waste a LOT of cycles.) + +The skip_input_data() source manager routine requires special care in a +suspension scenario. This routine is NOT granted the ability to suspend the +decompressor; it can decrement bytes_in_buffer to zero, but no more. If the +requested skip distance exceeds the amount of data currently in the input +buffer, then skip_input_data() must set bytes_in_buffer to zero and record the +additional skip distance somewhere else. The decompressor will immediately +call fill_input_buffer(), which should return FALSE, which will cause a +suspension return. The surrounding application must then arrange to discard +the recorded number of bytes before it resumes loading the input buffer. +(Yes, this design is rather baroque, but it avoids complexity in the far more +common case where a non-suspending source manager is used.) + +If the input data has been exhausted, we recommend that you emit a warning +and insert dummy EOI markers just as a non-suspending data source manager +would do. This can be handled either in the surrounding application logic or +within fill_input_buffer(); the latter is probably more efficient. If +fill_input_buffer() knows that no more data is available, it can set the +pointer/count to point to a dummy EOI marker and then return TRUE just as +though it had read more data in a non-suspending situation. + +The decompressor does not attempt to suspend within standard JPEG markers; +instead it will backtrack to the start of the marker and reprocess the whole +marker next time. Hence the input buffer must be large enough to hold the +longest standard marker in the file. Standard JPEG markers should normally +not exceed a few hundred bytes each (DHT tables are typically the longest). +We recommend at least a 2K buffer for performance reasons, which is much +larger than any correct marker is likely to be. For robustness against +damaged marker length counts, you may wish to insert a test in your +application for the case that the input buffer is completely full and yet +the decoder has suspended without consuming any data --- otherwise, if this +situation did occur, it would lead to an endless loop. (The library can't +provide this test since it has no idea whether "the buffer is full", or +even whether there is a fixed-size input buffer.) + +The input buffer would need to be 64K to allow for arbitrary COM or APPn +markers, but these are handled specially: they are either saved into allocated +memory, or skipped over by calling skip_input_data(). In the former case, +suspension is handled correctly, and in the latter case, the problem of +buffer overrun is placed on skip_input_data's shoulders, as explained above. +Note that if you provide your own marker handling routine for large markers, +you should consider how to deal with buffer overflow. + +Multiple-buffer management: + +In some applications it is desirable to store the compressed data in a linked +list of buffer areas, so as to avoid data copying. This can be handled by +having empty_output_buffer() or fill_input_buffer() set the pointer and count +to reference the next available buffer; FALSE is returned only if no more +buffers are available. Although seemingly straightforward, there is a +pitfall in this approach: the backtrack that occurs when FALSE is returned +could back up into an earlier buffer. For example, when fill_input_buffer() +is called, the current pointer & count indicate the backtrack restart point. +Since fill_input_buffer() will set the pointer and count to refer to a new +buffer, the restart position must be saved somewhere else. Suppose a second +call to fill_input_buffer() occurs in the same library call, and no +additional input data is available, so fill_input_buffer must return FALSE. +If the JPEG library has not moved the pointer/count forward in the current +buffer, then *the correct restart point is the saved position in the prior +buffer*. Prior buffers may be discarded only after the library establishes +a restart point within a later buffer. Similar remarks apply for output into +a chain of buffers. + +The library will never attempt to backtrack over a skip_input_data() call, +so any skipped data can be permanently discarded. You still have to deal +with the case of skipping not-yet-received data, however. + +It's much simpler to use only a single buffer; when fill_input_buffer() is +called, move any unconsumed data (beyond the current pointer/count) down to +the beginning of this buffer and then load new data into the remaining buffer +space. This approach requires a little more data copying but is far easier +to get right. + + +Progressive JPEG support +------------------------ + +Progressive JPEG rearranges the stored data into a series of scans of +increasing quality. In situations where a JPEG file is transmitted across a +slow communications link, a decoder can generate a low-quality image very +quickly from the first scan, then gradually improve the displayed quality as +more scans are received. The final image after all scans are complete is +identical to that of a regular (sequential) JPEG file of the same quality +setting. Progressive JPEG files are often slightly smaller than equivalent +sequential JPEG files, but the possibility of incremental display is the main +reason for using progressive JPEG. + +The IJG encoder library generates progressive JPEG files when given a +suitable "scan script" defining how to divide the data into scans. +Creation of progressive JPEG files is otherwise transparent to the encoder. +Progressive JPEG files can also be read transparently by the decoder library. +If the decoding application simply uses the library as defined above, it +will receive a final decoded image without any indication that the file was +progressive. Of course, this approach does not allow incremental display. +To perform incremental display, an application needs to use the decoder +library's "buffered-image" mode, in which it receives a decoded image +multiple times. + +Each displayed scan requires about as much work to decode as a full JPEG +image of the same size, so the decoder must be fairly fast in relation to the +data transmission rate in order to make incremental display useful. However, +it is possible to skip displaying the image and simply add the incoming bits +to the decoder's coefficient buffer. This is fast because only Huffman +decoding need be done, not IDCT, upsampling, colorspace conversion, etc. +The IJG decoder library allows the application to switch dynamically between +displaying the image and simply absorbing the incoming bits. A properly +coded application can automatically adapt the number of display passes to +suit the time available as the image is received. Also, a final +higher-quality display cycle can be performed from the buffered data after +the end of the file is reached. + +Progressive compression: + +To create a progressive JPEG file (or a multiple-scan sequential JPEG file), +set the scan_info cinfo field to point to an array of scan descriptors, and +perform compression as usual. Instead of constructing your own scan list, +you can call the jpeg_simple_progression() helper routine to create a +recommended progression sequence; this method should be used by all +applications that don't want to get involved in the nitty-gritty of +progressive scan sequence design. (If you want to provide user control of +scan sequences, you may wish to borrow the scan script reading code found +in rdswitch.c, so that you can read scan script files just like cjpeg's.) +When scan_info is not NULL, the compression library will store DCT'd data +into a buffer array as jpeg_write_scanlines() is called, and will emit all +the requested scans during jpeg_finish_compress(). This implies that +multiple-scan output cannot be created with a suspending data destination +manager, since jpeg_finish_compress() does not support suspension. We +should also note that the compressor currently forces Huffman optimization +mode when creating a progressive JPEG file, because the default Huffman +tables are unsuitable for progressive files. + +Progressive decompression: + +When buffered-image mode is not used, the decoder library will read all of +a multi-scan file during jpeg_start_decompress(), so that it can provide a +final decoded image. (Here "multi-scan" means either progressive or +multi-scan sequential.) This makes multi-scan files transparent to the +decoding application. However, existing applications that used suspending +input with version 5 of the IJG library will need to be modified to check +for a suspension return from jpeg_start_decompress(). + +To perform incremental display, an application must use the library's +buffered-image mode. This is described in the next section. + + +Buffered-image mode +------------------- + +In buffered-image mode, the library stores the partially decoded image in a +coefficient buffer, from which it can be read out as many times as desired. +This mode is typically used for incremental display of progressive JPEG files, +but it can be used with any JPEG file. Each scan of a progressive JPEG file +adds more data (more detail) to the buffered image. The application can +display in lockstep with the source file (one display pass per input scan), +or it can allow input processing to outrun display processing. By making +input and display processing run independently, it is possible for the +application to adapt progressive display to a wide range of data transmission +rates. + +The basic control flow for buffered-image decoding is + + jpeg_create_decompress() + set data source + jpeg_read_header() + set overall decompression parameters + cinfo.buffered_image = TRUE; /* select buffered-image mode */ + jpeg_start_decompress() + for (each output pass) { + adjust output decompression parameters if required + jpeg_start_output() /* start a new output pass */ + for (all scanlines in image) { + jpeg_read_scanlines() + display scanlines + } + jpeg_finish_output() /* terminate output pass */ + } + jpeg_finish_decompress() + jpeg_destroy_decompress() + +This differs from ordinary unbuffered decoding in that there is an additional +level of looping. The application can choose how many output passes to make +and how to display each pass. + +The simplest approach to displaying progressive images is to do one display +pass for each scan appearing in the input file. In this case the outer loop +condition is typically + while (! jpeg_input_complete(&cinfo)) +and the start-output call should read + jpeg_start_output(&cinfo, cinfo.input_scan_number); +The second parameter to jpeg_start_output() indicates which scan of the input +file is to be displayed; the scans are numbered starting at 1 for this +purpose. (You can use a loop counter starting at 1 if you like, but using +the library's input scan counter is easier.) The library automatically reads +data as necessary to complete each requested scan, and jpeg_finish_output() +advances to the next scan or end-of-image marker (hence input_scan_number +will be incremented by the time control arrives back at jpeg_start_output()). +With this technique, data is read from the input file only as needed, and +input and output processing run in lockstep. + +After reading the final scan and reaching the end of the input file, the +buffered image remains available; it can be read additional times by +repeating the jpeg_start_output()/jpeg_read_scanlines()/jpeg_finish_output() +sequence. For example, a useful technique is to use fast one-pass color +quantization for display passes made while the image is arriving, followed by +a final display pass using two-pass quantization for highest quality. This +is done by changing the library parameters before the final output pass. +Changing parameters between passes is discussed in detail below. + +In general the last scan of a progressive file cannot be recognized as such +until after it is read, so a post-input display pass is the best approach if +you want special processing in the final pass. + +When done with the image, be sure to call jpeg_finish_decompress() to release +the buffered image (or just use jpeg_destroy_decompress()). + +If input data arrives faster than it can be displayed, the application can +cause the library to decode input data in advance of what's needed to produce +output. This is done by calling the routine jpeg_consume_input(). +The return value is one of the following: + JPEG_REACHED_SOS: reached an SOS marker (the start of a new scan) + JPEG_REACHED_EOI: reached the EOI marker (end of image) + JPEG_ROW_COMPLETED: completed reading one MCU row of compressed data + JPEG_SCAN_COMPLETED: completed reading last MCU row of current scan + JPEG_SUSPENDED: suspended before completing any of the above +(JPEG_SUSPENDED can occur only if a suspending data source is used.) This +routine can be called at any time after initializing the JPEG object. It +reads some additional data and returns when one of the indicated significant +events occurs. (If called after the EOI marker is reached, it will +immediately return JPEG_REACHED_EOI without attempting to read more data.) + +The library's output processing will automatically call jpeg_consume_input() +whenever the output processing overtakes the input; thus, simple lockstep +display requires no direct calls to jpeg_consume_input(). But by adding +calls to jpeg_consume_input(), you can absorb data in advance of what is +being displayed. This has two benefits: + * You can limit buildup of unprocessed data in your input buffer. + * You can eliminate extra display passes by paying attention to the + state of the library's input processing. + +The first of these benefits only requires interspersing calls to +jpeg_consume_input() with your display operations and any other processing +you may be doing. To avoid wasting cycles due to backtracking, it's best to +call jpeg_consume_input() only after a hundred or so new bytes have arrived. +This is discussed further under "I/O suspension", above. (Note: the JPEG +library currently is not thread-safe. You must not call jpeg_consume_input() +from one thread of control if a different library routine is working on the +same JPEG object in another thread.) + +When input arrives fast enough that more than one new scan is available +before you start a new output pass, you may as well skip the output pass +corresponding to the completed scan. This occurs for free if you pass +cinfo.input_scan_number as the target scan number to jpeg_start_output(). +The input_scan_number field is simply the index of the scan currently being +consumed by the input processor. You can ensure that this is up-to-date by +emptying the input buffer just before calling jpeg_start_output(): call +jpeg_consume_input() repeatedly until it returns JPEG_SUSPENDED or +JPEG_REACHED_EOI. + +The target scan number passed to jpeg_start_output() is saved in the +cinfo.output_scan_number field. The library's output processing calls +jpeg_consume_input() whenever the current input scan number and row within +that scan is less than or equal to the current output scan number and row. +Thus, input processing can "get ahead" of the output processing but is not +allowed to "fall behind". You can achieve several different effects by +manipulating this interlock rule. For example, if you pass a target scan +number greater than the current input scan number, the output processor will +wait until that scan starts to arrive before producing any output. (To avoid +an infinite loop, the target scan number is automatically reset to the last +scan number when the end of image is reached. Thus, if you specify a large +target scan number, the library will just absorb the entire input file and +then perform an output pass. This is effectively the same as what +jpeg_start_decompress() does when you don't select buffered-image mode.) +When you pass a target scan number equal to the current input scan number, +the image is displayed no faster than the current input scan arrives. The +final possibility is to pass a target scan number less than the current input +scan number; this disables the input/output interlock and causes the output +processor to simply display whatever it finds in the image buffer, without +waiting for input. (However, the library will not accept a target scan +number less than one, so you can't avoid waiting for the first scan.) + +When data is arriving faster than the output display processing can advance +through the image, jpeg_consume_input() will store data into the buffered +image beyond the point at which the output processing is reading data out +again. If the input arrives fast enough, it may "wrap around" the buffer to +the point where the input is more than one whole scan ahead of the output. +If the output processing simply proceeds through its display pass without +paying attention to the input, the effect seen on-screen is that the lower +part of the image is one or more scans better in quality than the upper part. +Then, when the next output scan is started, you have a choice of what target +scan number to use. The recommended choice is to use the current input scan +number at that time, which implies that you've skipped the output scans +corresponding to the input scans that were completed while you processed the +previous output scan. In this way, the decoder automatically adapts its +speed to the arriving data, by skipping output scans as necessary to keep up +with the arriving data. + +When using this strategy, you'll want to be sure that you perform a final +output pass after receiving all the data; otherwise your last display may not +be full quality across the whole screen. So the right outer loop logic is +something like this: + do { + absorb any waiting input by calling jpeg_consume_input() + final_pass = jpeg_input_complete(&cinfo); + adjust output decompression parameters if required + jpeg_start_output(&cinfo, cinfo.input_scan_number); + ... + jpeg_finish_output() + } while (! final_pass); +rather than quitting as soon as jpeg_input_complete() returns TRUE. This +arrangement makes it simple to use higher-quality decoding parameters +for the final pass. But if you don't want to use special parameters for +the final pass, the right loop logic is like this: + for (;;) { + absorb any waiting input by calling jpeg_consume_input() + jpeg_start_output(&cinfo, cinfo.input_scan_number); + ... + jpeg_finish_output() + if (jpeg_input_complete(&cinfo) && + cinfo.input_scan_number == cinfo.output_scan_number) + break; + } +In this case you don't need to know in advance whether an output pass is to +be the last one, so it's not necessary to have reached EOF before starting +the final output pass; rather, what you want to test is whether the output +pass was performed in sync with the final input scan. This form of the loop +will avoid an extra output pass whenever the decoder is able (or nearly able) +to keep up with the incoming data. + +When the data transmission speed is high, you might begin a display pass, +then find that much or all of the file has arrived before you can complete +the pass. (You can detect this by noting the JPEG_REACHED_EOI return code +from jpeg_consume_input(), or equivalently by testing jpeg_input_complete().) +In this situation you may wish to abort the current display pass and start a +new one using the newly arrived information. To do so, just call +jpeg_finish_output() and then start a new pass with jpeg_start_output(). + +A variant strategy is to abort and restart display if more than one complete +scan arrives during an output pass; this can be detected by noting +JPEG_REACHED_SOS returns and/or examining cinfo.input_scan_number. This +idea should be employed with caution, however, since the display process +might never get to the bottom of the image before being aborted, resulting +in the lower part of the screen being several passes worse than the upper. +In most cases it's probably best to abort an output pass only if the whole +file has arrived and you want to begin the final output pass immediately. + +When receiving data across a communication link, we recommend always using +the current input scan number for the output target scan number; if a +higher-quality final pass is to be done, it should be started (aborting any +incomplete output pass) as soon as the end of file is received. However, +many other strategies are possible. For example, the application can examine +the parameters of the current input scan and decide whether to display it or +not. If the scan contains only chroma data, one might choose not to use it +as the target scan, expecting that the scan will be small and will arrive +quickly. To skip to the next scan, call jpeg_consume_input() until it +returns JPEG_REACHED_SOS or JPEG_REACHED_EOI. Or just use the next higher +number as the target scan for jpeg_start_output(); but that method doesn't +let you inspect the next scan's parameters before deciding to display it. + + +In buffered-image mode, jpeg_start_decompress() never performs input and +thus never suspends. An application that uses input suspension with +buffered-image mode must be prepared for suspension returns from these +routines: +* jpeg_start_output() performs input only if you request 2-pass quantization + and the target scan isn't fully read yet. (This is discussed below.) +* jpeg_read_scanlines(), as always, returns the number of scanlines that it + was able to produce before suspending. +* jpeg_finish_output() will read any markers following the target scan, + up to the end of the file or the SOS marker that begins another scan. + (But it reads no input if jpeg_consume_input() has already reached the + end of the file or a SOS marker beyond the target output scan.) +* jpeg_finish_decompress() will read until the end of file, and thus can + suspend if the end hasn't already been reached (as can be tested by + calling jpeg_input_complete()). +jpeg_start_output(), jpeg_finish_output(), and jpeg_finish_decompress() +all return TRUE if they completed their tasks, FALSE if they had to suspend. +In the event of a FALSE return, the application must load more input data +and repeat the call. Applications that use non-suspending data sources need +not check the return values of these three routines. + + +It is possible to change decoding parameters between output passes in the +buffered-image mode. The decoder library currently supports only very +limited changes of parameters. ONLY THE FOLLOWING parameter changes are +allowed after jpeg_start_decompress() is called: +* dct_method can be changed before each call to jpeg_start_output(). + For example, one could use a fast DCT method for early scans, changing + to a higher quality method for the final scan. +* dither_mode can be changed before each call to jpeg_start_output(); + of course this has no impact if not using color quantization. Typically + one would use ordered dither for initial passes, then switch to + Floyd-Steinberg dither for the final pass. Caution: changing dither mode + can cause more memory to be allocated by the library. Although the amount + of memory involved is not large (a scanline or so), it may cause the + initial max_memory_to_use specification to be exceeded, which in the worst + case would result in an out-of-memory failure. +* do_block_smoothing can be changed before each call to jpeg_start_output(). + This setting is relevant only when decoding a progressive JPEG image. + During the first DC-only scan, block smoothing provides a very "fuzzy" look + instead of the very "blocky" look seen without it; which is better seems a + matter of personal taste. But block smoothing is nearly always a win + during later stages, especially when decoding a successive-approximation + image: smoothing helps to hide the slight blockiness that otherwise shows + up on smooth gradients until the lowest coefficient bits are sent. +* Color quantization mode can be changed under the rules described below. + You *cannot* change between full-color and quantized output (because that + would alter the required I/O buffer sizes), but you can change which + quantization method is used. + +When generating color-quantized output, changing quantization method is a +very useful way of switching between high-speed and high-quality display. +The library allows you to change among its three quantization methods: +1. Single-pass quantization to a fixed color cube. + Selected by cinfo.two_pass_quantize = FALSE and cinfo.colormap = NULL. +2. Single-pass quantization to an application-supplied colormap. + Selected by setting cinfo.colormap to point to the colormap (the value of + two_pass_quantize is ignored); also set cinfo.actual_number_of_colors. +3. Two-pass quantization to a colormap chosen specifically for the image. + Selected by cinfo.two_pass_quantize = TRUE and cinfo.colormap = NULL. + (This is the default setting selected by jpeg_read_header, but it is + probably NOT what you want for the first pass of progressive display!) +These methods offer successively better quality and lesser speed. However, +only the first method is available for quantizing in non-RGB color spaces. + +IMPORTANT: because the different quantizer methods have very different +working-storage requirements, the library requires you to indicate which +one(s) you intend to use before you call jpeg_start_decompress(). (If we did +not require this, the max_memory_to_use setting would be a complete fiction.) +You do this by setting one or more of these three cinfo fields to TRUE: + enable_1pass_quant Fixed color cube colormap + enable_external_quant Externally-supplied colormap + enable_2pass_quant Two-pass custom colormap +All three are initialized FALSE by jpeg_read_header(). But +jpeg_start_decompress() automatically sets TRUE the one selected by the +current two_pass_quantize and colormap settings, so you only need to set the +enable flags for any other quantization methods you plan to change to later. + +After setting the enable flags correctly at jpeg_start_decompress() time, you +can change to any enabled quantization method by setting two_pass_quantize +and colormap properly just before calling jpeg_start_output(). The following +special rules apply: +1. You must explicitly set cinfo.colormap to NULL when switching to 1-pass + or 2-pass mode from a different mode, or when you want the 2-pass + quantizer to be re-run to generate a new colormap. +2. To switch to an external colormap, or to change to a different external + colormap than was used on the prior pass, you must call + jpeg_new_colormap() after setting cinfo.colormap. +NOTE: if you want to use the same colormap as was used in the prior pass, +you should not do either of these things. This will save some nontrivial +switchover costs. +(These requirements exist because cinfo.colormap will always be non-NULL +after completing a prior output pass, since both the 1-pass and 2-pass +quantizers set it to point to their output colormaps. Thus you have to +do one of these two things to notify the library that something has changed. +Yup, it's a bit klugy, but it's necessary to do it this way for backwards +compatibility.) + +Note that in buffered-image mode, the library generates any requested colormap +during jpeg_start_output(), not during jpeg_start_decompress(). + +When using two-pass quantization, jpeg_start_output() makes a pass over the +buffered image to determine the optimum color map; it therefore may take a +significant amount of time, whereas ordinarily it does little work. The +progress monitor hook is called during this pass, if defined. It is also +important to realize that if the specified target scan number is greater than +or equal to the current input scan number, jpeg_start_output() will attempt +to consume input as it makes this pass. If you use a suspending data source, +you need to check for a FALSE return from jpeg_start_output() under these +conditions. The combination of 2-pass quantization and a not-yet-fully-read +target scan is the only case in which jpeg_start_output() will consume input. + + +Application authors who support buffered-image mode may be tempted to use it +for all JPEG images, even single-scan ones. This will work, but it is +inefficient: there is no need to create an image-sized coefficient buffer for +single-scan images. Requesting buffered-image mode for such an image wastes +memory. Worse, it can cost time on large images, since the buffered data has +to be swapped out or written to a temporary file. If you are concerned about +maximum performance on baseline JPEG files, you should use buffered-image +mode only when the incoming file actually has multiple scans. This can be +tested by calling jpeg_has_multiple_scans(), which will return a correct +result at any time after jpeg_read_header() completes. + +It is also worth noting that when you use jpeg_consume_input() to let input +processing get ahead of output processing, the resulting pattern of access to +the coefficient buffer is quite nonsequential. It's best to use the memory +manager jmemnobs.c if you can (ie, if you have enough real or virtual main +memory). If not, at least make sure that max_memory_to_use is set as high as +possible. If the JPEG memory manager has to use a temporary file, you will +probably see a lot of disk traffic and poor performance. (This could be +improved with additional work on the memory manager, but we haven't gotten +around to it yet.) + +In some applications it may be convenient to use jpeg_consume_input() for all +input processing, including reading the initial markers; that is, you may +wish to call jpeg_consume_input() instead of jpeg_read_header() during +startup. This works, but note that you must check for JPEG_REACHED_SOS and +JPEG_REACHED_EOI return codes as the equivalent of jpeg_read_header's codes. +Once the first SOS marker has been reached, you must call +jpeg_start_decompress() before jpeg_consume_input() will consume more input; +it'll just keep returning JPEG_REACHED_SOS until you do. If you read a +tables-only file this way, jpeg_consume_input() will return JPEG_REACHED_EOI +without ever returning JPEG_REACHED_SOS; be sure to check for this case. +If this happens, the decompressor will not read any more input until you call +jpeg_abort() to reset it. It is OK to call jpeg_consume_input() even when not +using buffered-image mode, but in that case it's basically a no-op after the +initial markers have been read: it will just return JPEG_SUSPENDED. + + +Abbreviated datastreams and multiple images +------------------------------------------- + +A JPEG compression or decompression object can be reused to process multiple +images. This saves a small amount of time per image by eliminating the +"create" and "destroy" operations, but that isn't the real purpose of the +feature. Rather, reuse of an object provides support for abbreviated JPEG +datastreams. Object reuse can also simplify processing a series of images in +a single input or output file. This section explains these features. + +A JPEG file normally contains several hundred bytes worth of quantization +and Huffman tables. In a situation where many images will be stored or +transmitted with identical tables, this may represent an annoying overhead. +The JPEG standard therefore permits tables to be omitted. The standard +defines three classes of JPEG datastreams: + * "Interchange" datastreams contain an image and all tables needed to decode + the image. These are the usual kind of JPEG file. + * "Abbreviated image" datastreams contain an image, but are missing some or + all of the tables needed to decode that image. + * "Abbreviated table specification" (henceforth "tables-only") datastreams + contain only table specifications. +To decode an abbreviated image, it is necessary to load the missing table(s) +into the decoder beforehand. This can be accomplished by reading a separate +tables-only file. A variant scheme uses a series of images in which the first +image is an interchange (complete) datastream, while subsequent ones are +abbreviated and rely on the tables loaded by the first image. It is assumed +that once the decoder has read a table, it will remember that table until a +new definition for the same table number is encountered. + +It is the application designer's responsibility to figure out how to associate +the correct tables with an abbreviated image. While abbreviated datastreams +can be useful in a closed environment, their use is strongly discouraged in +any situation where data exchange with other applications might be needed. +Caveat designer. + +The JPEG library provides support for reading and writing any combination of +tables-only datastreams and abbreviated images. In both compression and +decompression objects, a quantization or Huffman table will be retained for +the lifetime of the object, unless it is overwritten by a new table definition. + + +To create abbreviated image datastreams, it is only necessary to tell the +compressor not to emit some or all of the tables it is using. Each +quantization and Huffman table struct contains a boolean field "sent_table", +which normally is initialized to FALSE. For each table used by the image, the +header-writing process emits the table and sets sent_table = TRUE unless it is +already TRUE. (In normal usage, this prevents outputting the same table +definition multiple times, as would otherwise occur because the chroma +components typically share tables.) Thus, setting this field to TRUE before +calling jpeg_start_compress() will prevent the table from being written at +all. + +If you want to create a "pure" abbreviated image file containing no tables, +just call "jpeg_suppress_tables(&cinfo, TRUE)" after constructing all the +tables. If you want to emit some but not all tables, you'll need to set the +individual sent_table fields directly. + +To create an abbreviated image, you must also call jpeg_start_compress() +with a second parameter of FALSE, not TRUE. Otherwise jpeg_start_compress() +will force all the sent_table fields to FALSE. (This is a safety feature to +prevent abbreviated images from being created accidentally.) + +To create a tables-only file, perform the same parameter setup that you +normally would, but instead of calling jpeg_start_compress() and so on, call +jpeg_write_tables(&cinfo). This will write an abbreviated datastream +containing only SOI, DQT and/or DHT markers, and EOI. All the quantization +and Huffman tables that are currently defined in the compression object will +be emitted unless their sent_tables flag is already TRUE, and then all the +sent_tables flags will be set TRUE. + +A sure-fire way to create matching tables-only and abbreviated image files +is to proceed as follows: + + create JPEG compression object + set JPEG parameters + set destination to tables-only file + jpeg_write_tables(&cinfo); + set destination to image file + jpeg_start_compress(&cinfo, FALSE); + write data... + jpeg_finish_compress(&cinfo); + +Since the JPEG parameters are not altered between writing the table file and +the abbreviated image file, the same tables are sure to be used. Of course, +you can repeat the jpeg_start_compress() ... jpeg_finish_compress() sequence +many times to produce many abbreviated image files matching the table file. + +You cannot suppress output of the computed Huffman tables when Huffman +optimization is selected. (If you could, there'd be no way to decode the +image...) Generally, you don't want to set optimize_coding = TRUE when +you are trying to produce abbreviated files. + +In some cases you might want to compress an image using tables which are +not stored in the application, but are defined in an interchange or +tables-only file readable by the application. This can be done by setting up +a JPEG decompression object to read the specification file, then copying the +tables into your compression object. See jpeg_copy_critical_parameters() +for an example of copying quantization tables. + + +To read abbreviated image files, you simply need to load the proper tables +into the decompression object before trying to read the abbreviated image. +If the proper tables are stored in the application program, you can just +allocate the table structs and fill in their contents directly. For example, +to load a fixed quantization table into table slot "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]; /* quant_ptr is JQUANT_TBL* */ + for (i = 0; i < 64; i++) { + /* Qtable[] is desired quantization table, in natural array order */ + quant_ptr->quantval[i] = Qtable[i]; + } + +Code to load a fixed Huffman table is typically (for AC table "n"): + + if (cinfo.ac_huff_tbl_ptrs[n] == NULL) + cinfo.ac_huff_tbl_ptrs[n] = jpeg_alloc_huff_table((j_common_ptr) &cinfo); + huff_ptr = cinfo.ac_huff_tbl_ptrs[n]; /* huff_ptr is JHUFF_TBL* */ + for (i = 1; i <= 16; i++) { + /* counts[i] is number of Huffman codes of length i bits, i=1..16 */ + huff_ptr->bits[i] = counts[i]; + } + for (i = 0; i < 256; i++) { + /* symbols[] is the list of Huffman symbols, in code-length order */ + huff_ptr->huffval[i] = symbols[i]; + } + +(Note that trying to set cinfo.quant_tbl_ptrs[n] to point directly at a +constant JQUANT_TBL object is not safe. If the incoming file happened to +contain a quantization table definition, your master table would get +overwritten! Instead allocate a working table copy and copy the master table +into it, as illustrated above. Ditto for Huffman tables, of course.) + +You might want to read the tables from a tables-only file, rather than +hard-wiring them into your application. The jpeg_read_header() call is +sufficient to read a tables-only file. You must pass a second parameter of +FALSE to indicate that you do not require an image to be present. Thus, the +typical scenario is + + create JPEG decompression object + set source to tables-only file + jpeg_read_header(&cinfo, FALSE); + set source to abbreviated image file + jpeg_read_header(&cinfo, TRUE); + set decompression parameters + jpeg_start_decompress(&cinfo); + read data... + jpeg_finish_decompress(&cinfo); + +In some cases, you may want to read a file without knowing whether it contains +an image or just tables. In that case, pass FALSE and check the return value +from jpeg_read_header(): it will be JPEG_HEADER_OK if an image was found, +JPEG_HEADER_TABLES_ONLY if only tables were found. (A third return value, +JPEG_SUSPENDED, is possible when using a suspending data source manager.) +Note that jpeg_read_header() will not complain if you read an abbreviated +image for which you haven't loaded the missing tables; the missing-table check +occurs later, in jpeg_start_decompress(). + + +It is possible to read a series of images from a single source file by +repeating the jpeg_read_header() ... jpeg_finish_decompress() sequence, +without releasing/recreating the JPEG object or the data source module. +(If you did reinitialize, any partial bufferload left in the data source +buffer at the end of one image would be discarded, causing you to lose the +start of the next image.) When you use this method, stored tables are +automatically carried forward, so some of the images can be abbreviated images +that depend on tables from earlier images. + +If you intend to write a series of images into a single destination file, +you might want to make a specialized data destination module that doesn't +flush the output buffer at term_destination() time. This would speed things +up by some trifling amount. Of course, you'd need to remember to flush the +buffer after the last image. You can make the later images be abbreviated +ones by passing FALSE to jpeg_start_compress(). + + +Special markers +--------------- + +Some applications may need to insert or extract special data in the JPEG +datastream. The JPEG standard provides marker types "COM" (comment) and +"APP0" through "APP15" (application) to hold application-specific data. +Unfortunately, the use of these markers is not specified by the standard. +COM markers are fairly widely used to hold user-supplied text. The JFIF file +format spec uses APP0 markers with specified initial strings to hold certain +data. Adobe applications use APP14 markers beginning with the string "Adobe" +for miscellaneous data. Other APPn markers are rarely seen, but might +contain almost anything. + +If you wish to store user-supplied text, we recommend you use COM markers +and place readable 7-bit ASCII text in them. Newline conventions are not +standardized --- expect to find LF (Unix style), CR/LF (DOS style), or CR +(Mac style). A robust COM reader should be able to cope with random binary +garbage, including nulls, since some applications generate COM markers +containing non-ASCII junk. (But yours should not be one of them.) + +For program-supplied data, use an APPn marker, and be sure to begin it with an +identifying string so that you can tell whether the marker is actually yours. +It's probably best to avoid using APP0 or APP14 for any private markers. +(NOTE: the upcoming SPIFF standard will use APP8 markers; we recommend you +not use APP8 markers for any private purposes, either.) + +Keep in mind that at most 65533 bytes can be put into one marker, but you +can have as many markers as you like. + +By default, the IJG compression library will write a JFIF APP0 marker if the +selected JPEG colorspace is grayscale or YCbCr, or an Adobe APP14 marker if +the selected colorspace is RGB, CMYK, or YCCK. You can disable this, but +we don't recommend it. The decompression library will recognize JFIF and +Adobe markers and will set the JPEG colorspace properly when one is found. + + +You can write special markers immediately following the datastream header by +calling jpeg_write_marker() after jpeg_start_compress() and before the first +call to jpeg_write_scanlines(). When you do this, the markers appear after +the SOI and the JFIF APP0 and Adobe APP14 markers (if written), but before +all else. Specify the marker type parameter as "JPEG_COM" for COM or +"JPEG_APP0 + n" for APPn. (Actually, jpeg_write_marker will let you write +any marker type, but we don't recommend writing any other kinds of marker.) +For example, to write a user comment string pointed to by comment_text: + jpeg_write_marker(cinfo, JPEG_COM, comment_text, strlen(comment_text)); + +If it's not convenient to store all the marker data in memory at once, +you can instead call jpeg_write_m_header() followed by multiple calls to +jpeg_write_m_byte(). If you do it this way, it's your responsibility to +call jpeg_write_m_byte() exactly the number of times given in the length +parameter to jpeg_write_m_header(). (This method lets you empty the +output buffer partway through a marker, which might be important when +using a suspending data destination module. In any case, if you are using +a suspending destination, you should flush its buffer after inserting +any special markers. See "I/O suspension".) + +Or, if you prefer to synthesize the marker byte sequence yourself, +you can just cram it straight into the data destination module. + +If you are writing JFIF 1.02 extension markers (thumbnail images), don't +forget to set cinfo.JFIF_minor_version = 2 so that the encoder will write the +correct JFIF version number in the JFIF header marker. The library's default +is to write version 1.01, but that's wrong if you insert any 1.02 extension +markers. (We could probably get away with just defaulting to 1.02, but there +used to be broken decoders that would complain about unknown minor version +numbers. To reduce compatibility risks it's safest not to write 1.02 unless +you are actually using 1.02 extensions.) + + +When reading, two methods of handling special markers are available: +1. You can ask the library to save the contents of COM and/or APPn markers +into memory, and then examine them at your leisure afterwards. +2. You can supply your own routine to process COM and/or APPn markers +on-the-fly as they are read. +The first method is simpler to use, especially if you are using a suspending +data source; writing a marker processor that copes with input suspension is +not easy (consider what happens if the marker is longer than your available +input buffer). However, the second method conserves memory since the marker +data need not be kept around after it's been processed. + +For either method, you'd normally set up marker handling after creating a +decompression object and before calling jpeg_read_header(), because the +markers of interest will typically be near the head of the file and so will +be scanned by jpeg_read_header. Once you've established a marker handling +method, it will be used for the life of that decompression object +(potentially many datastreams), unless you change it. Marker handling is +determined separately for COM markers and for each APPn marker code. + + +To save the contents of special markers in memory, call + jpeg_save_markers(cinfo, marker_code, length_limit) +where marker_code is the marker type to save, JPEG_COM or JPEG_APP0+n. +(To arrange to save all the special marker types, you need to call this +routine 17 times, for COM and APP0-APP15.) If the incoming marker is longer +than length_limit data bytes, only length_limit bytes will be saved; this +parameter allows you to avoid chewing up memory when you only need to see the +first few bytes of a potentially large marker. If you want to save all the +data, set length_limit to 0xFFFF; that is enough since marker lengths are only +16 bits. As a special case, setting length_limit to 0 prevents that marker +type from being saved at all. (That is the default behavior, in fact.) + +After jpeg_read_header() completes, you can examine the special markers by +following the cinfo->marker_list pointer chain. All the special markers in +the file appear in this list, in order of their occurrence in the file (but +omitting any markers of types you didn't ask for). Both the original data +length and the saved data length are recorded for each list entry; the latter +will not exceed length_limit for the particular marker type. Note that these +lengths exclude the marker length word, whereas the stored representation +within the JPEG file includes it. (Hence the maximum data length is really +only 65533.) + +It is possible that additional special markers appear in the file beyond the +SOS marker at which jpeg_read_header stops; if so, the marker list will be +extended during reading of the rest of the file. This is not expected to be +common, however. If you are short on memory you may want to reset the length +limit to zero for all marker types after finishing jpeg_read_header, to +ensure that the max_memory_to_use setting cannot be exceeded due to addition +of later markers. + +The marker list remains stored until you call jpeg_finish_decompress or +jpeg_abort, at which point the memory is freed and the list is set to empty. +(jpeg_destroy also releases the storage, of course.) + +Note that the library is internally interested in APP0 and APP14 markers; +if you try to set a small nonzero length limit on these types, the library +will silently force the length up to the minimum it wants. (But you can set +a zero length limit to prevent them from being saved at all.) Also, in a +16-bit environment, the maximum length limit may be constrained to less than +65533 by malloc() limitations. It is therefore best not to assume that the +effective length limit is exactly what you set it to be. + + +If you want to supply your own marker-reading routine, you do it by calling +jpeg_set_marker_processor(). A marker processor routine must have the +signature + boolean jpeg_marker_parser_method (j_decompress_ptr cinfo) +Although the marker code is not explicitly passed, the routine can find it +in cinfo->unread_marker. At the time of call, the marker proper has been +read from the data source module. The processor routine is responsible for +reading the marker length word and the remaining parameter bytes, if any. +Return TRUE to indicate success. (FALSE should be returned only if you are +using a suspending data source and it tells you to suspend. See the standard +marker processors in jdmarker.c for appropriate coding methods if you need to +use a suspending data source.) + +If you override the default APP0 or APP14 processors, it is up to you to +recognize JFIF and Adobe markers if you want colorspace recognition to occur +properly. We recommend copying and extending the default processors if you +want to do that. (A better idea is to save these marker types for later +examination by calling jpeg_save_markers(); that method doesn't interfere +with the library's own processing of these markers.) + +jpeg_set_marker_processor() and jpeg_save_markers() are mutually exclusive +--- if you call one it overrides any previous call to the other, for the +particular marker type specified. + +A simple example of an external COM processor can be found in djpeg.c. +Also, see jpegtran.c for an example of using jpeg_save_markers. + + +Raw (downsampled) image data +---------------------------- + +Some applications need to supply already-downsampled image data to the JPEG +compressor, or to receive raw downsampled data from the decompressor. The +library supports this requirement by allowing the application to write or +read raw data, bypassing the normal preprocessing or postprocessing steps. +The interface is different from the standard one and is somewhat harder to +use. If your interest is merely in bypassing color conversion, we recommend +that you use the standard interface and simply set jpeg_color_space = +in_color_space (or jpeg_color_space = out_color_space for decompression). +The mechanism described in this section is necessary only to supply or +receive downsampled image data, in which not all components have the same +dimensions. + + +To compress raw data, you must supply the data in the colorspace to be used +in the JPEG file (please read the earlier section on Special color spaces) +and downsampled to the sampling factors specified in the JPEG parameters. +You must supply the data in the format used internally by the JPEG library, +namely a JSAMPIMAGE array. This is an array of pointers to two-dimensional +arrays, each of type JSAMPARRAY. Each 2-D array holds the values for one +color component. This structure is necessary since the components are of +different sizes. If the image dimensions are not a multiple of the MCU size, +you must also pad the data correctly (usually, this is done by replicating +the last column and/or row). The data must be padded to a multiple of a DCT +block in each component: that is, each downsampled row must contain a +multiple of 8 valid samples, and there must be a multiple of 8 sample rows +for each component. (For applications such as conversion of digital TV +images, the standard image size is usually a multiple of the DCT block size, +so that no padding need actually be done.) + +The procedure for compression of raw data is basically the same as normal +compression, except that you call jpeg_write_raw_data() in place of +jpeg_write_scanlines(). Before calling jpeg_start_compress(), you must do +the following: + * Set cinfo->raw_data_in to TRUE. (It is set FALSE by jpeg_set_defaults().) + This notifies the library that you will be supplying raw data. + * Ensure jpeg_color_space is correct --- an explicit jpeg_set_colorspace() + call is a good idea. Note that since color conversion is bypassed, + in_color_space is ignored, except that jpeg_set_defaults() uses it to + choose the default jpeg_color_space setting. + * Ensure the sampling factors, cinfo->comp_info[i].h_samp_factor and + cinfo->comp_info[i].v_samp_factor, are correct. Since these indicate the + dimensions of the data you are supplying, it's wise to set them + explicitly, rather than assuming the library's defaults are what you want. + +To pass raw data to the library, call jpeg_write_raw_data() in place of +jpeg_write_scanlines(). The two routines work similarly except that +jpeg_write_raw_data takes a JSAMPIMAGE data array rather than JSAMPARRAY. +The scanlines count passed to and returned from jpeg_write_raw_data is +measured in terms of the component with the largest v_samp_factor. + +jpeg_write_raw_data() processes one MCU row per call, which is to say +v_samp_factor*DCTSIZE sample rows of each component. The passed num_lines +value must be at least max_v_samp_factor*DCTSIZE, and the return value will +be exactly that amount (or possibly some multiple of that amount, in future +library versions). This is true even on the last call at the bottom of the +image; don't forget to pad your data as necessary. + +The required dimensions of the supplied data can be computed for each +component as + cinfo->comp_info[i].width_in_blocks*DCTSIZE samples per row + cinfo->comp_info[i].height_in_blocks*DCTSIZE rows in image +after jpeg_start_compress() has initialized those fields. If the valid data +is smaller than this, it must be padded appropriately. For some sampling +factors and image sizes, additional dummy DCT blocks are inserted to make +the image a multiple of the MCU dimensions. The library creates such dummy +blocks itself; it does not read them from your supplied data. Therefore you +need never pad by more than DCTSIZE samples. An example may help here. +Assume 2h2v downsampling of YCbCr data, that is + cinfo->comp_info[0].h_samp_factor = 2 for Y + cinfo->comp_info[0].v_samp_factor = 2 + cinfo->comp_info[1].h_samp_factor = 1 for Cb + cinfo->comp_info[1].v_samp_factor = 1 + cinfo->comp_info[2].h_samp_factor = 1 for Cr + cinfo->comp_info[2].v_samp_factor = 1 +and suppose that the nominal image dimensions (cinfo->image_width and +cinfo->image_height) are 101x101 pixels. Then jpeg_start_compress() will +compute downsampled_width = 101 and width_in_blocks = 13 for Y, +downsampled_width = 51 and width_in_blocks = 7 for Cb and Cr (and the same +for the height fields). You must pad the Y data to at least 13*8 = 104 +columns and rows, the Cb/Cr data to at least 7*8 = 56 columns and rows. The +MCU height is max_v_samp_factor = 2 DCT rows so you must pass at least 16 +scanlines on each call to jpeg_write_raw_data(), which is to say 16 actual +sample rows of Y and 8 each of Cb and Cr. A total of 7 MCU rows are needed, +so you must pass a total of 7*16 = 112 "scanlines". The last DCT block row +of Y data is dummy, so it doesn't matter what you pass for it in the data +arrays, but the scanlines count must total up to 112 so that all of the Cb +and Cr data gets passed. + +Output suspension is supported with raw-data compression: if the data +destination module suspends, jpeg_write_raw_data() will return 0. +In this case the same data rows must be passed again on the next call. + + +Decompression with raw data output implies bypassing all postprocessing: +you cannot ask for rescaling or color quantization, for instance. More +seriously, you must deal with the color space and sampling factors present in +the incoming file. If your application only handles, say, 2h1v YCbCr data, +you must check for and fail on other color spaces or other sampling factors. +The library will not convert to a different color space for you. + +To obtain raw data output, set cinfo->raw_data_out = TRUE before +jpeg_start_decompress() (it is set FALSE by jpeg_read_header()). Be sure to +verify that the color space and sampling factors are ones you can handle. +Then call jpeg_read_raw_data() in place of jpeg_read_scanlines(). The +decompression process is otherwise the same as usual. + +jpeg_read_raw_data() returns one MCU row per call, and thus you must pass a +buffer of at least max_v_samp_factor*DCTSIZE scanlines (scanline counting is +the same as for raw-data compression). The buffer you pass must be large +enough to hold the actual data plus padding to DCT-block boundaries. As with +compression, any entirely dummy DCT blocks are not processed so you need not +allocate space for them, but the total scanline count includes them. The +above example of computing buffer dimensions for raw-data compression is +equally valid for decompression. + +Input suspension is supported with raw-data decompression: if the data source +module suspends, jpeg_read_raw_data() will return 0. You can also use +buffered-image mode to read raw data in multiple passes. + + +Really raw data: DCT coefficients +--------------------------------- + +It is possible to read or write the contents of a JPEG file as raw DCT +coefficients. This facility is mainly intended for use in lossless +transcoding between different JPEG file formats. Other possible applications +include lossless cropping of a JPEG image, lossless reassembly of a +multi-strip or multi-tile TIFF/JPEG file into a single JPEG datastream, etc. + +To read the contents of a JPEG file as DCT coefficients, open the file and do +jpeg_read_header() as usual. But instead of calling jpeg_start_decompress() +and jpeg_read_scanlines(), call jpeg_read_coefficients(). This will read the +entire image into a set of virtual coefficient-block arrays, one array per +component. The return value is a pointer to an array of virtual-array +descriptors. Each virtual array can be accessed directly using the JPEG +memory manager's access_virt_barray method (see Memory management, below, +and also read structure.doc's discussion of virtual array handling). Or, +for simple transcoding to a different JPEG file format, the array list can +just be handed directly to jpeg_write_coefficients(). + +Each block in the block arrays contains quantized coefficient values in +normal array order (not JPEG zigzag order). The block arrays contain only +DCT blocks containing real data; any entirely-dummy blocks added to fill out +interleaved MCUs at the right or bottom edges of the image are discarded +during reading and are not stored in the block arrays. (The size of each +block array can be determined from the width_in_blocks and height_in_blocks +fields of the component's comp_info entry.) This is also the data format +expected by jpeg_write_coefficients(). + +When you are done using the virtual arrays, call jpeg_finish_decompress() +to release the array storage and return the decompression object to an idle +state; or just call jpeg_destroy() if you don't need to reuse the object. + +If you use a suspending data source, jpeg_read_coefficients() will return +NULL if it is forced to suspend; a non-NULL return value indicates successful +completion. You need not test for a NULL return value when using a +non-suspending data source. + +It is also possible to call jpeg_read_coefficients() to obtain access to the +decoder's coefficient arrays during a normal decode cycle in buffered-image +mode. This frammish might be useful for progressively displaying an incoming +image and then re-encoding it without loss. To do this, decode in buffered- +image mode as discussed previously, then call jpeg_read_coefficients() after +the last jpeg_finish_output() call. The arrays will be available for your use +until you call jpeg_finish_decompress(). + + +To write the contents of a JPEG file as DCT coefficients, you must provide +the DCT coefficients stored in virtual block arrays. You can either pass +block arrays read from an input JPEG file by jpeg_read_coefficients(), or +allocate virtual arrays from the JPEG compression object and fill them +yourself. In either case, jpeg_write_coefficients() is substituted for +jpeg_start_compress() and jpeg_write_scanlines(). Thus the sequence is + * Create compression object + * Set all compression parameters as necessary + * Request virtual arrays if needed + * jpeg_write_coefficients() + * jpeg_finish_compress() + * Destroy or re-use compression object +jpeg_write_coefficients() is passed a pointer to an array of virtual block +array descriptors; the number of arrays is equal to cinfo.num_components. + +The virtual arrays need only have been requested, not realized, before +jpeg_write_coefficients() is called. A side-effect of +jpeg_write_coefficients() is to realize any virtual arrays that have been +requested from the compression object's memory manager. Thus, when obtaining +the virtual arrays from the compression object, you should fill the arrays +after calling jpeg_write_coefficients(). The data is actually written out +when you call jpeg_finish_compress(); jpeg_write_coefficients() only writes +the file header. + +When writing raw DCT coefficients, it is crucial that the JPEG quantization +tables and sampling factors match the way the data was encoded, or the +resulting file will be invalid. For transcoding from an existing JPEG file, +we recommend using jpeg_copy_critical_parameters(). This routine initializes +all the compression parameters to default values (like jpeg_set_defaults()), +then copies the critical information from a source decompression object. +The decompression object should have just been used to read the entire +JPEG input file --- that is, it should be awaiting jpeg_finish_decompress(). + +jpeg_write_coefficients() marks all tables stored in the compression object +as needing to be written to the output file (thus, it acts like +jpeg_start_compress(cinfo, TRUE)). This is for safety's sake, to avoid +emitting abbreviated JPEG files by accident. If you really want to emit an +abbreviated JPEG file, call jpeg_suppress_tables(), or set the tables' +individual sent_table flags, between calling jpeg_write_coefficients() and +jpeg_finish_compress(). + + +Progress monitoring +------------------- + +Some applications may need to regain control from the JPEG library every so +often. The typical use of this feature is to produce a percent-done bar or +other progress display. (For a simple example, see cjpeg.c or djpeg.c.) +Although you do get control back frequently during the data-transferring pass +(the jpeg_read_scanlines or jpeg_write_scanlines loop), any additional passes +will occur inside jpeg_finish_compress or jpeg_start_decompress; those +routines may take a long time to execute, and you don't get control back +until they are done. + +You can define a progress-monitor routine which will be called periodically +by the library. No guarantees are made about how often this call will occur, +so we don't recommend you use it for mouse tracking or anything like that. +At present, a call will occur once per MCU row, scanline, or sample row +group, whichever unit is convenient for the current processing mode; so the +wider the image, the longer the time between calls. During the data +transferring pass, only one call occurs per call of jpeg_read_scanlines or +jpeg_write_scanlines, so don't pass a large number of scanlines at once if +you want fine resolution in the progress count. (If you really need to use +the callback mechanism for time-critical tasks like mouse tracking, you could +insert additional calls inside some of the library's inner loops.) + +To establish a progress-monitor callback, create a struct jpeg_progress_mgr, +fill in its progress_monitor field with a pointer to your callback routine, +and set cinfo->progress to point to the struct. The callback will be called +whenever cinfo->progress is non-NULL. (This pointer is set to NULL by +jpeg_create_compress or jpeg_create_decompress; the library will not change +it thereafter. So if you allocate dynamic storage for the progress struct, +make sure it will live as long as the JPEG object does. Allocating from the +JPEG memory manager with lifetime JPOOL_PERMANENT will work nicely.) You +can use the same callback routine for both compression and decompression. + +The jpeg_progress_mgr struct contains four fields which are set by the library: + 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 */ +During any one pass, pass_counter increases from 0 up to (not including) +pass_limit; the step size is usually but not necessarily 1. The pass_limit +value may change from one pass to another. The expected total number of +passes is in total_passes, and the number of passes already completed is in +completed_passes. Thus the fraction of work completed may be estimated as + completed_passes + (pass_counter/pass_limit) + -------------------------------------------- + total_passes +ignoring the fact that the passes may not be equal amounts of work. + +When decompressing, pass_limit can even change within a pass, because it +depends on the number of scans in the JPEG file, which isn't always known in +advance. The computed fraction-of-work-done may jump suddenly (if the library +discovers it has overestimated the number of scans) or even decrease (in the +opposite case). It is not wise to put great faith in the work estimate. + +When using the decompressor's buffered-image mode, the progress monitor work +estimate is likely to be completely unhelpful, because the library has no way +to know how many output passes will be demanded of it. Currently, the library +sets total_passes based on the assumption that there will be one more output +pass if the input file end hasn't yet been read (jpeg_input_complete() isn't +TRUE), but no more output passes if the file end has been reached when the +output pass is started. This means that total_passes will rise as additional +output passes are requested. If you have a way of determining the input file +size, estimating progress based on the fraction of the file that's been read +will probably be more useful than using the library's value. + + +Memory management +----------------- + +This section covers some key facts about the JPEG library's built-in memory +manager. For more info, please read structure.doc's section about the memory +manager, and consult the source code if necessary. + +All memory and temporary file allocation within the library is done via the +memory manager. If necessary, you can replace the "back end" of the memory +manager to control allocation yourself (for example, if you don't want the +library to use malloc() and free() for some reason). + +Some data is allocated "permanently" and will not be freed until the JPEG +object is destroyed. Most data is allocated "per image" and is freed by +jpeg_finish_compress, jpeg_finish_decompress, or jpeg_abort. You can call the +memory manager yourself to allocate structures that will automatically be +freed at these times. Typical code for this is + ptr = (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, size); +Use JPOOL_PERMANENT to get storage that lasts as long as the JPEG object. +Use alloc_large instead of alloc_small for anything bigger than a few Kbytes. +There are also alloc_sarray and alloc_barray routines that automatically +build 2-D sample or block arrays. + +The library's minimum space requirements to process an image depend on the +image's width, but not on its height, because the library ordinarily works +with "strip" buffers that are as wide as the image but just a few rows high. +Some operating modes (eg, two-pass color quantization) require full-image +buffers. Such buffers are treated as "virtual arrays": only the current strip +need be in memory, and the rest can be swapped out to a temporary file. + +If you use the simplest memory manager back end (jmemnobs.c), then no +temporary files are used; virtual arrays are simply malloc()'d. Images bigger +than memory can be processed only if your system supports virtual memory. +The other memory manager back ends support temporary files of various flavors +and thus work in machines without virtual memory. They may also be useful on +Unix machines if you need to process images that exceed available swap space. + +When using temporary files, the library will make the in-memory buffers for +its virtual arrays just big enough to stay within a "maximum memory" setting. +Your application can set this limit by setting cinfo->mem->max_memory_to_use +after creating the JPEG object. (Of course, there is still a minimum size for +the buffers, so the max-memory setting is effective only if it is bigger than +the minimum space needed.) If you allocate any large structures yourself, you +must allocate them before jpeg_start_compress() or jpeg_start_decompress() in +order to have them counted against the max memory limit. Also keep in mind +that space allocated with alloc_small() is ignored, on the assumption that +it's too small to be worth worrying about; so a reasonable safety margin +should be left when setting max_memory_to_use. + +If you use the jmemname.c or jmemdos.c memory manager back end, it is +important to clean up the JPEG object properly to ensure that the temporary +files get deleted. (This is especially crucial with jmemdos.c, where the +"temporary files" may be extended-memory segments; if they are not freed, +DOS will require a reboot to recover the memory.) Thus, with these memory +managers, it's a good idea to provide a signal handler that will trap any +early exit from your program. The handler should call either jpeg_abort() +or jpeg_destroy() for any active JPEG objects. A handler is not needed with +jmemnobs.c, and shouldn't be necessary with jmemansi.c or jmemmac.c either, +since the C library is supposed to take care of deleting files made with +tmpfile(). + + +Memory usage +------------ + +Working memory requirements while performing compression or decompression +depend on image dimensions, image characteristics (such as colorspace and +JPEG process), and operating mode (application-selected options). + +As of v6b, the decompressor requires: + 1. About 24K in more-or-less-fixed-size data. This varies a bit depending + on operating mode and image characteristics (particularly color vs. + grayscale), but it doesn't depend on image dimensions. + 2. Strip buffers (of size proportional to the image width) for IDCT and + upsampling results. The worst case for commonly used sampling factors + is about 34 bytes * width in pixels for a color image. A grayscale image + only needs about 8 bytes per pixel column. + 3. A full-image DCT coefficient buffer is needed to decode a multi-scan JPEG + file (including progressive JPEGs), or whenever you select buffered-image + mode. This takes 2 bytes/coefficient. At typical 2x2 sampling, that's + 3 bytes per pixel for a color image. Worst case (1x1 sampling) requires + 6 bytes/pixel. For grayscale, figure 2 bytes/pixel. + 4. To perform 2-pass color quantization, the decompressor also needs a + 128K color lookup table and a full-image pixel buffer (3 bytes/pixel). +This does not count any memory allocated by the application, such as a +buffer to hold the final output image. + +The above figures are valid for 8-bit JPEG data precision and a machine with +32-bit ints. For 12-bit JPEG data, double the size of the strip buffers and +quantization pixel buffer. The "fixed-size" data will be somewhat smaller +with 16-bit ints, larger with 64-bit ints. Also, CMYK or other unusual +color spaces will require different amounts of space. + +The full-image coefficient and pixel buffers, if needed at all, do not +have to be fully RAM resident; you can have the library use temporary +files instead when the total memory usage would exceed a limit you set. +(But if your OS supports virtual memory, it's probably better to just use +jmemnobs and let the OS do the swapping.) + +The compressor's memory requirements are similar, except that it has no need +for color quantization. Also, it needs a full-image DCT coefficient buffer +if Huffman-table optimization is asked for, even if progressive mode is not +requested. + +If you need more detailed information about memory usage in a particular +situation, you can enable the MEM_STATS code in jmemmgr.c. + + +Library compile-time options +---------------------------- + +A number of compile-time options are available by modifying jmorecfg.h. + +The JPEG standard provides for both the baseline 8-bit DCT process and +a 12-bit DCT process. The IJG code supports 12-bit lossy JPEG if you define +BITS_IN_JSAMPLE as 12 rather than 8. Note that this causes JSAMPLE to be +larger than a char, so it affects the surrounding application's image data. +The sample applications cjpeg and djpeg can support 12-bit mode only for PPM +and GIF file formats; you must disable the other file formats to compile a +12-bit cjpeg or djpeg. (install.doc has more information about that.) +At present, a 12-bit library can handle *only* 12-bit images, not both +precisions. (If you need to include both 8- and 12-bit libraries in a single +application, you could probably do it by defining NEED_SHORT_EXTERNAL_NAMES +for just one of the copies. You'd have to access the 8-bit and 12-bit copies +from separate application source files. This is untested ... if you try it, +we'd like to hear whether it works!) + +Note that a 12-bit library always compresses in Huffman optimization mode, +in order to generate valid Huffman tables. This is necessary because our +default Huffman tables only cover 8-bit data. If you need to output 12-bit +files in one pass, you'll have to supply suitable default Huffman tables. +You may also want to supply your own DCT quantization tables; the existing +quality-scaling code has been developed for 8-bit use, and probably doesn't +generate especially good tables for 12-bit. + +The maximum number of components (color channels) in the image is determined +by MAX_COMPONENTS. The JPEG standard allows up to 255 components, but we +expect that few applications will need more than four or so. + +On machines with unusual data type sizes, you may be able to improve +performance or reduce memory space by tweaking the various typedefs in +jmorecfg.h. In particular, on some RISC CPUs, access to arrays of "short"s +is quite slow; consider trading memory for speed by making JCOEF, INT16, and +UINT16 be "int" or "unsigned int". UINT8 is also a candidate to become int. +You probably don't want to make JSAMPLE be int unless you have lots of memory +to burn. + +You can reduce the size of the library by compiling out various optional +functions. To do this, undefine xxx_SUPPORTED symbols as necessary. + +You can also save a few K by not having text error messages in the library; +the standard error message table occupies about 5Kb. This is particularly +reasonable for embedded applications where there's no good way to display +a message anyway. To do this, remove the creation of the message table +(jpeg_std_message_table[]) from jerror.c, and alter format_message to do +something reasonable without it. You could output the numeric value of the +message code number, for example. If you do this, you can also save a couple +more K by modifying the TRACEMSn() macros in jerror.h to expand to nothing; +you don't need trace capability anyway, right? + + +Portability considerations +-------------------------- + +The JPEG library has been written to be extremely portable; the sample +applications cjpeg and djpeg are slightly less so. This section summarizes +the design goals in this area. (If you encounter any bugs that cause the +library to be less portable than is claimed here, we'd appreciate hearing +about them.) + +The code works fine on ANSI C, C++, and pre-ANSI C compilers, using any of +the popular system include file setups, and some not-so-popular ones too. +See install.doc for configuration procedures. + +The code is not dependent on the exact sizes of the C data types. As +distributed, we make the assumptions that + char is at least 8 bits wide + short is at least 16 bits wide + int is at least 16 bits wide + long is at least 32 bits wide +(These are the minimum requirements of the ANSI C standard.) Wider types will +work fine, although memory may be used inefficiently if char is much larger +than 8 bits or short is much bigger than 16 bits. The code should work +equally well with 16- or 32-bit ints. + +In a system where these assumptions are not met, you may be able to make the +code work by modifying the typedefs in jmorecfg.h. However, you will probably +have difficulty if int is less than 16 bits wide, since references to plain +int abound in the code. + +char can be either signed or unsigned, although the code runs faster if an +unsigned char type is available. If char is wider than 8 bits, you will need +to redefine JOCTET and/or provide custom data source/destination managers so +that JOCTET represents exactly 8 bits of data on external storage. + +The JPEG library proper does not assume ASCII representation of characters. +But some of the image file I/O modules in cjpeg/djpeg do have ASCII +dependencies in file-header manipulation; so does cjpeg's select_file_type() +routine. + +The JPEG library does not rely heavily on the C library. In particular, C +stdio is used only by the data source/destination modules and the error +handler, all of which are application-replaceable. (cjpeg/djpeg are more +heavily dependent on stdio.) malloc and free are called only from the memory +manager "back end" module, so you can use a different memory allocator by +replacing that one file. + +The code generally assumes that C names must be unique in the first 15 +characters. However, global function names can be made unique in the +first 6 characters by defining NEED_SHORT_EXTERNAL_NAMES. + +More info about porting the code may be gleaned by reading jconfig.doc, +jmorecfg.h, and jinclude.h. + + +Notes for MS-DOS implementors +----------------------------- + +The IJG code is designed to work efficiently in 80x86 "small" or "medium" +memory models (i.e., data pointers are 16 bits unless explicitly declared +"far"; code pointers can be either size). You may be able to use small +model to compile cjpeg or djpeg by itself, but you will probably have to use +medium model for any larger application. This won't make much difference in +performance. You *will* take a noticeable performance hit if you use a +large-data memory model (perhaps 10%-25%), and you should avoid "huge" model +if at all possible. + +The JPEG library typically needs 2Kb-3Kb of stack space. It will also +malloc about 20K-30K of near heap space while executing (and lots of far +heap, but that doesn't count in this calculation). This figure will vary +depending on selected operating mode, and to a lesser extent on image size. +There is also about 5Kb-6Kb of constant data which will be allocated in the +near data segment (about 4Kb of this is the error message table). +Thus you have perhaps 20K available for other modules' static data and near +heap space before you need to go to a larger memory model. The C library's +static data will account for several K of this, but that still leaves a good +deal for your needs. (If you are tight on space, you could reduce the sizes +of the I/O buffers allocated by jdatasrc.c and jdatadst.c, say from 4K to +1K. Another possibility is to move the error message table to far memory; +this should be doable with only localized hacking on jerror.c.) + +About 2K of the near heap space is "permanent" memory that will not be +released until you destroy the JPEG object. This is only an issue if you +save a JPEG object between compression or decompression operations. + +Far data space may also be a tight resource when you are dealing with large +images. The most memory-intensive case is decompression with two-pass color +quantization, or single-pass quantization to an externally supplied color +map. This requires a 128Kb color lookup table plus strip buffers amounting +to about 40 bytes per column for typical sampling ratios (eg, about 25600 +bytes for a 640-pixel-wide image). You may not be able to process wide +images if you have large data structures of your own. + +Of course, all of these concerns vanish if you use a 32-bit flat-memory-model +compiler, such as DJGPP or Watcom C. We highly recommend flat model if you +can use it; the JPEG library is significantly faster in flat model. diff --git a/Utilities/FLTK/jpeg/makedepend b/Utilities/FLTK/jpeg/makedepend new file mode 100644 index 0000000000..ecf2b024c8 --- /dev/null +++ b/Utilities/FLTK/jpeg/makedepend @@ -0,0 +1,94 @@ +# DO NOT DELETE + +jmemnobs.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jmemnobs.o: jerror.h jmemsys.h +jcapimin.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jcapimin.o: jerror.h +jcapistd.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jcapistd.o: jerror.h +jccoefct.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jccoefct.o: jerror.h +jccolor.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jccolor.o: jerror.h +jcdctmgr.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jcdctmgr.o: jerror.h jdct.h +jchuff.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jchuff.o: jerror.h jchuff.h +jcinit.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jcinit.o: jerror.h +jcmainct.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jcmainct.o: jerror.h +jcmarker.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jcmarker.o: jerror.h +jcmaster.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jcmaster.o: jerror.h +jcomapi.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jcomapi.o: jerror.h +jcparam.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jcparam.o: jerror.h +jcphuff.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jcphuff.o: jerror.h jchuff.h +jcprepct.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jcprepct.o: jerror.h +jcsample.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jcsample.o: jerror.h +jctrans.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jctrans.o: jerror.h +jdapimin.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jdapimin.o: jerror.h +jdapistd.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jdapistd.o: jerror.h +jdatadst.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jdatadst.o: jerror.h +jdatasrc.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jdatasrc.o: jerror.h +jdcoefct.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jdcoefct.o: jerror.h +jdcolor.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jdcolor.o: jerror.h +jddctmgr.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jddctmgr.o: jerror.h jdct.h +jdhuff.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jdhuff.o: jerror.h jdhuff.h +jdinput.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jdinput.o: jerror.h +jdmainct.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jdmainct.o: jerror.h +jdmarker.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jdmarker.o: jerror.h +jdmaster.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jdmaster.o: jerror.h +jdmerge.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jdmerge.o: jerror.h +jdphuff.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jdphuff.o: jerror.h jdhuff.h +jdpostct.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jdpostct.o: jerror.h +jdsample.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jdsample.o: jerror.h +jdtrans.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jdtrans.o: jerror.h +jerror.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jerror.o: jerror.h jversion.h +jfdctflt.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jfdctflt.o: jerror.h jdct.h +jfdctfst.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jfdctfst.o: jerror.h jdct.h +jfdctint.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jfdctint.o: jerror.h jdct.h +jidctflt.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jidctflt.o: jerror.h jdct.h +jidctfst.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jidctfst.o: jerror.h jdct.h +jidctint.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jidctint.o: jerror.h jdct.h +jidctred.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jidctred.o: jerror.h jdct.h +jquant1.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jquant1.o: jerror.h +jquant2.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jquant2.o: jerror.h +jutils.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jutils.o: jerror.h +jmemmgr.o: jinclude.h jconfig.h ../config.h jpeglib.h jmorecfg.h jpegint.h +jmemmgr.o: jerror.h jmemsys.h diff --git a/Utilities/FLTK/jpeg/makefile.wat b/Utilities/FLTK/jpeg/makefile.wat new file mode 100644 index 0000000000..0f8b9f43ea --- /dev/null +++ b/Utilities/FLTK/jpeg/makefile.wat @@ -0,0 +1,67 @@ +# +# "$Id: makefile.wat 4359 2005-05-19 16:07:13Z mike $" +# +# JPEG library makefile for the Fast Light Toolkit (FLTK). +# +# Copyright 1997-2004 by Easy Software Products. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. +# +# Please report all bugs and problems to "fltk-bugs@fltk.org". +# + +LIBNAMEROOT=ftlk_jpeg + +!include ../watcom.mif + + +# +# Object files... +# + +LIBOBJS = jmemnobs.obj & + jcapimin.obj jcapistd.obj jccoefct.obj jccolor.obj jcdctmgr.obj & + jchuff.obj jcinit.obj jcmainct.obj jcmarker.obj jcmaster.obj jcomapi.obj & + jcparam.obj jcphuff.obj jcprepct.obj jcsample.obj jctrans.obj & + jdapimin.obj jdapistd.obj jdatadst.obj jdatasrc.obj jdcoefct.obj & + jdcolor.obj jddctmgr.obj jdhuff.obj jdinput.obj jdmainct.obj jdmarker.obj & + jdmaster.obj jdmerge.obj jdphuff.obj jdpostct.obj jdsample.obj & + jdtrans.obj jerror.obj jfdctflt.obj jfdctfst.obj jfdctint.obj & + jidctflt.obj jidctfst.obj jidctint.obj jidctred.obj jquant1.obj & + jquant2.obj jutils.obj jmemmgr.obj + +# +# Make all targets... +# + +all: $(LIBNAME) + +$(LIBNAME): $(LIBOBJS) + $(LIB) $(LIBOPTS) $@ $< + +# +# Clean all directories +# +clean : .SYMBOLIC + @echo Cleaning up. +CLEANEXTS = obj + @for %a in ($(CLEANEXTS)) do -rm -f $(ODIR)\*.%a + -rm -f *.err + -rm -f $(LIBNAME) + +# +# End of "$Id: makefile.wat 4359 2005-05-19 16:07:13Z mike $". +# diff --git a/Utilities/FLTK/jpeg/structure.doc b/Utilities/FLTK/jpeg/structure.doc new file mode 100644 index 0000000000..51c9def7e5 --- /dev/null +++ b/Utilities/FLTK/jpeg/structure.doc @@ -0,0 +1,948 @@ +IJG JPEG LIBRARY: SYSTEM ARCHITECTURE + +Copyright (C) 1991-1995, 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 an overview of the architecture of the IJG JPEG software; +that is, the functions of the various modules in the system and the interfaces +between modules. For more precise details about any data structure or calling +convention, see the include files and comments in the source code. + +We assume that the reader is already somewhat familiar with the JPEG standard. +The README file includes references for learning about JPEG. The file +libjpeg.doc describes the library from the viewpoint of an application +programmer using the library; it's best to read that file before this one. +Also, the file coderules.doc describes the coding style conventions we use. + +In this document, JPEG-specific terminology follows the JPEG standard: + A "component" means a color channel, e.g., Red or Luminance. + A "sample" is a single component value (i.e., one number in the image data). + A "coefficient" is a frequency coefficient (a DCT transform output number). + A "block" is an 8x8 group of samples or coefficients. + An "MCU" (minimum coded unit) is an interleaved set of blocks of size + determined by the sampling factors, or a single block in a + noninterleaved scan. +We do not use the terms "pixel" and "sample" interchangeably. When we say +pixel, we mean an element of the full-size image, while a sample is an element +of the downsampled image. Thus the number of samples may vary across +components while the number of pixels does not. (This terminology is not used +rigorously throughout the code, but it is used in places where confusion would +otherwise result.) + + +*** System features *** + +The IJG distribution contains two parts: + * A subroutine library for JPEG compression and decompression. + * cjpeg/djpeg, two sample applications that use the library to transform + JFIF JPEG files to and from several other image formats. +cjpeg/djpeg are of no great intellectual complexity: they merely add a simple +command-line user interface and I/O routines for several uncompressed image +formats. This document concentrates on the library itself. + +We desire the library to be capable of supporting all JPEG baseline, extended +sequential, and progressive DCT processes. Hierarchical processes are not +supported. + +The library does not support the lossless (spatial) JPEG process. Lossless +JPEG shares little or no code with lossy JPEG, and would normally be used +without the extensive pre- and post-processing provided by this library. +We feel that lossless JPEG is better handled by a separate library. + +Within these limits, any set of compression parameters allowed by the JPEG +spec should be readable for decompression. (We can be more restrictive about +what formats we can generate.) Although the system design allows for all +parameter values, some uncommon settings are not yet implemented and may +never be; nonintegral sampling ratios are the prime example. Furthermore, +we treat 8-bit vs. 12-bit data precision as a compile-time switch, not a +run-time option, because most machines can store 8-bit pixels much more +compactly than 12-bit. + +For legal reasons, JPEG arithmetic coding is not currently supported, but +extending the library to include it would be straightforward. + +By itself, the library handles only interchange JPEG datastreams --- in +particular the widely used JFIF file format. The library can be used by +surrounding code to process interchange or abbreviated JPEG datastreams that +are embedded in more complex file formats. (For example, libtiff uses this +library to implement JPEG compression within the TIFF file format.) + +The library includes a substantial amount of code that is not covered by the +JPEG standard but is necessary for typical applications of JPEG. These +functions preprocess the image before JPEG compression or postprocess it after +decompression. They include colorspace conversion, downsampling/upsampling, +and color quantization. This code can be omitted if not needed. + +A wide range of quality vs. speed tradeoffs are possible in JPEG processing, +and even more so in decompression postprocessing. The decompression library +provides multiple implementations that cover most of the useful tradeoffs, +ranging from very-high-quality down to fast-preview operation. On the +compression side we have generally not provided low-quality choices, since +compression is normally less time-critical. It should be understood that the +low-quality modes may not meet the JPEG standard's accuracy requirements; +nonetheless, they are useful for viewers. + + +*** Portability issues *** + +Portability is an essential requirement for the library. The key portability +issues that show up at the level of system architecture are: + +1. Memory usage. We want the code to be able to run on PC-class machines +with limited memory. Images should therefore be processed sequentially (in +strips), to avoid holding the whole image in memory at once. Where a +full-image buffer is necessary, we should be able to use either virtual memory +or temporary files. + +2. Near/far pointer distinction. To run efficiently on 80x86 machines, the +code should distinguish "small" objects (kept in near data space) from +"large" ones (kept in far data space). This is an annoying restriction, but +fortunately it does not impact code quality for less brain-damaged machines, +and the source code clutter turns out to be minimal with sufficient use of +pointer typedefs. + +3. Data precision. We assume that "char" is at least 8 bits, "short" and +"int" at least 16, "long" at least 32. The code will work fine with larger +data sizes, although memory may be used inefficiently in some cases. However, +the JPEG compressed datastream must ultimately appear on external storage as a +sequence of 8-bit bytes if it is to conform to the standard. This may pose a +problem on machines where char is wider than 8 bits. The library represents +compressed data as an array of values of typedef JOCTET. If no data type +exactly 8 bits wide is available, custom data source and data destination +modules must be written to unpack and pack the chosen JOCTET datatype into +8-bit external representation. + + +*** System overview *** + +The compressor and decompressor are each divided into two main sections: +the JPEG compressor or decompressor proper, and the preprocessing or +postprocessing functions. The interface between these two sections is the +image data that the official JPEG spec regards as its input or output: this +data is in the colorspace to be used for compression, and it is downsampled +to the sampling factors to be used. The preprocessing and postprocessing +steps are responsible for converting a normal image representation to or from +this form. (Those few applications that want to deal with YCbCr downsampled +data can skip the preprocessing or postprocessing step.) + +Looking more closely, the compressor library contains the following main +elements: + + Preprocessing: + * Color space conversion (e.g., RGB to YCbCr). + * Edge expansion and downsampling. Optionally, this step can do simple + smoothing --- this is often helpful for low-quality source data. + JPEG proper: + * MCU assembly, DCT, quantization. + * Entropy coding (sequential or progressive, Huffman or arithmetic). + +In addition to these modules we need overall control, marker generation, +and support code (memory management & error handling). There is also a +module responsible for physically writing the output data --- typically +this is just an interface to fwrite(), but some applications may need to +do something else with the data. + +The decompressor library contains the following main elements: + + JPEG proper: + * Entropy decoding (sequential or progressive, Huffman or arithmetic). + * Dequantization, inverse DCT, MCU disassembly. + Postprocessing: + * Upsampling. Optionally, this step may be able to do more general + rescaling of the image. + * Color space conversion (e.g., YCbCr to RGB). This step may also + provide gamma adjustment [ currently it does not ]. + * Optional color quantization (e.g., reduction to 256 colors). + * Optional color precision reduction (e.g., 24-bit to 15-bit color). + [This feature is not currently implemented.] + +We also need overall control, marker parsing, and a data source module. +The support code (memory management & error handling) can be shared with +the compression half of the library. + +There may be several implementations of each of these elements, particularly +in the decompressor, where a wide range of speed/quality tradeoffs is very +useful. It must be understood that some of the best speedups involve +merging adjacent steps in the pipeline. For example, upsampling, color space +conversion, and color quantization might all be done at once when using a +low-quality ordered-dither technique. The system architecture is designed to +allow such merging where appropriate. + + +Note: it is convenient to regard edge expansion (padding to block boundaries) +as a preprocessing/postprocessing function, even though the JPEG spec includes +it in compression/decompression. We do this because downsampling/upsampling +can be simplified a little if they work on padded data: it's not necessary to +have special cases at the right and bottom edges. Therefore the interface +buffer is always an integral number of blocks wide and high, and we expect +compression preprocessing to pad the source data properly. Padding will occur +only to the next block (8-sample) boundary. In an interleaved-scan situation, +additional dummy blocks may be used to fill out MCUs, but the MCU assembly and +disassembly logic will create or discard these blocks internally. (This is +advantageous for speed reasons, since we avoid DCTing the dummy blocks. +It also permits a small reduction in file size, because the compressor can +choose dummy block contents so as to minimize their size in compressed form. +Finally, it makes the interface buffer specification independent of whether +the file is actually interleaved or not.) Applications that wish to deal +directly with the downsampled data must provide similar buffering and padding +for odd-sized images. + + +*** Poor man's object-oriented programming *** + +It should be clear by now that we have a lot of quasi-independent processing +steps, many of which have several possible behaviors. To avoid cluttering the +code with lots of switch statements, we use a simple form of object-style +programming to separate out the different possibilities. + +For example, two different color quantization algorithms could be implemented +as two separate modules that present the same external interface; at runtime, +the calling code will access the proper module indirectly through an "object". + +We can get the limited features we need while staying within portable C. +The basic tool is a function pointer. An "object" is just a struct +containing one or more function pointer fields, each of which corresponds to +a method name in real object-oriented languages. During initialization we +fill in the function pointers with references to whichever module we have +determined we need to use in this run. Then invocation of the module is done +by indirecting through a function pointer; on most machines this is no more +expensive than a switch statement, which would be the only other way of +making the required run-time choice. The really significant benefit, of +course, is keeping the source code clean and well structured. + +We can also arrange to have private storage that varies between different +implementations of the same kind of object. We do this by making all the +module-specific object structs be separately allocated entities, which will +be accessed via pointers in the master compression or decompression struct. +The "public" fields or methods for a given kind of object are specified by +a commonly known struct. But a module's initialization code can allocate +a larger struct that contains the common struct as its first member, plus +additional private fields. With appropriate pointer casting, the module's +internal functions can access these private fields. (For a simple example, +see jdatadst.c, which implements the external interface specified by struct +jpeg_destination_mgr, but adds extra fields.) + +(Of course this would all be a lot easier if we were using C++, but we are +not yet prepared to assume that everyone has a C++ compiler.) + +An important benefit of this scheme is that it is easy to provide multiple +versions of any method, each tuned to a particular case. While a lot of +precalculation might be done to select an optimal implementation of a method, +the cost per invocation is constant. For example, the upsampling step might +have a "generic" method, plus one or more "hardwired" methods for the most +popular sampling factors; the hardwired methods would be faster because they'd +use straight-line code instead of for-loops. The cost to determine which +method to use is paid only once, at startup, and the selection criteria are +hidden from the callers of the method. + +This plan differs a little bit from usual object-oriented structures, in that +only one instance of each object class will exist during execution. The +reason for having the class structure is that on different runs we may create +different instances (choose to execute different modules). You can think of +the term "method" as denoting the common interface presented by a particular +set of interchangeable functions, and "object" as denoting a group of related +methods, or the total shared interface behavior of a group of modules. + + +*** Overall control structure *** + +We previously mentioned the need for overall control logic in the compression +and decompression libraries. In IJG implementations prior to v5, overall +control was mostly provided by "pipeline control" modules, which proved to be +large, unwieldy, and hard to understand. To improve the situation, the +control logic has been subdivided into multiple modules. The control modules +consist of: + +1. Master control for module selection and initialization. This has two +responsibilities: + + 1A. Startup initialization at the beginning of image processing. + The individual processing modules to be used in this run are selected + and given initialization calls. + + 1B. Per-pass control. This determines how many passes will be performed + and calls each active processing module to configure itself + appropriately at the beginning of each pass. End-of-pass processing, + where necessary, is also invoked from the master control module. + + Method selection is partially distributed, in that a particular processing + module may contain several possible implementations of a particular method, + which it will select among when given its initialization call. The master + control code need only be concerned with decisions that affect more than + one module. + +2. Data buffering control. A separate control module exists for each + inter-processing-step data buffer. This module is responsible for + invoking the processing steps that write or read that data buffer. + +Each buffer controller sees the world as follows: + +input data => processing step A => buffer => processing step B => output data + | | | + ------------------ controller ------------------ + +The controller knows the dataflow requirements of steps A and B: how much data +they want to accept in one chunk and how much they output in one chunk. Its +function is to manage its buffer and call A and B at the proper times. + +A data buffer control module may itself be viewed as a processing step by a +higher-level control module; thus the control modules form a binary tree with +elementary processing steps at the leaves of the tree. + +The control modules are objects. A considerable amount of flexibility can +be had by replacing implementations of a control module. For example: +* Merging of adjacent steps in the pipeline is done by replacing a control + module and its pair of processing-step modules with a single processing- + step module. (Hence the possible merges are determined by the tree of + control modules.) +* In some processing modes, a given interstep buffer need only be a "strip" + buffer large enough to accommodate the desired data chunk sizes. In other + modes, a full-image buffer is needed and several passes are required. + The control module determines which kind of buffer is used and manipulates + virtual array buffers as needed. One or both processing steps may be + unaware of the multi-pass behavior. + +In theory, we might be able to make all of the data buffer controllers +interchangeable and provide just one set of implementations for all. In +practice, each one contains considerable special-case processing for its +particular job. The buffer controller concept should be regarded as an +overall system structuring principle, not as a complete description of the +task performed by any one controller. + + +*** Compression object structure *** + +Here is a sketch of the logical structure of the JPEG compression library: + + |-- Colorspace conversion + |-- Preprocessing controller --| + | |-- Downsampling +Main controller --| + | |-- Forward DCT, quantize + |-- Coefficient controller --| + |-- Entropy encoding + +This sketch also describes the flow of control (subroutine calls) during +typical image data processing. Each of the components shown in the diagram is +an "object" which may have several different implementations available. One +or more source code files contain the actual implementation(s) of each object. + +The objects shown above are: + +* Main controller: buffer controller for the subsampled-data buffer, which + holds the preprocessed input data. This controller invokes preprocessing to + fill the subsampled-data buffer, and JPEG compression to empty it. There is + usually no need for a full-image buffer here; a strip buffer is adequate. + +* Preprocessing controller: buffer controller for the downsampling input data + buffer, which lies between colorspace conversion and downsampling. Note + that a unified conversion/downsampling module would probably replace this + controller entirely. + +* Colorspace conversion: converts application image data into the desired + JPEG color space; also changes the data from pixel-interleaved layout to + separate component planes. Processes one pixel row at a time. + +* Downsampling: performs reduction of chroma components as required. + Optionally may perform pixel-level smoothing as well. Processes a "row + group" at a time, where a row group is defined as Vmax pixel rows of each + component before downsampling, and Vk sample rows afterwards (remember Vk + differs across components). Some downsampling or smoothing algorithms may + require context rows above and below the current row group; the + preprocessing controller is responsible for supplying these rows via proper + buffering. The downsampler is responsible for edge expansion at the right + edge (i.e., extending each sample row to a multiple of 8 samples); but the + preprocessing controller is responsible for vertical edge expansion (i.e., + duplicating the bottom sample row as needed to make a multiple of 8 rows). + +* Coefficient controller: buffer controller for the DCT-coefficient data. + This controller handles MCU assembly, including insertion of dummy DCT + blocks when needed at the right or bottom edge. When performing + Huffman-code optimization or emitting a multiscan JPEG file, this + controller is responsible for buffering the full image. The equivalent of + one fully interleaved MCU row of subsampled data is processed per call, + even when the JPEG file is noninterleaved. + +* Forward DCT and quantization: Perform DCT, quantize, and emit coefficients. + Works on one or more DCT blocks at a time. (Note: the coefficients are now + emitted in normal array order, which the entropy encoder is expected to + convert to zigzag order as necessary. Prior versions of the IJG code did + the conversion to zigzag order within the quantization step.) + +* Entropy encoding: Perform Huffman or arithmetic entropy coding and emit the + coded data to the data destination module. Works on one MCU per call. + For progressive JPEG, the same DCT blocks are fed to the entropy coder + during each pass, and the coder must emit the appropriate subset of + coefficients. + +In addition to the above objects, the compression library includes these +objects: + +* Master control: determines the number of passes required, controls overall + and per-pass initialization of the other modules. + +* Marker writing: generates JPEG markers (except for RSTn, which is emitted + by the entropy encoder when needed). + +* Data destination manager: writes the output JPEG datastream to its final + destination (e.g., a file). The destination manager supplied with the + library knows how to write to a stdio stream; for other behaviors, the + surrounding application may provide its own destination manager. + +* Memory manager: allocates and releases memory, controls virtual arrays + (with backing store management, where required). + +* Error handler: performs formatting and output of error and trace messages; + determines handling of nonfatal errors. The surrounding application may + override some or all of this object's methods to change error handling. + +* Progress monitor: supports output of "percent-done" progress reports. + This object represents an optional callback to the surrounding application: + if wanted, it must be supplied by the application. + +The error handler, destination manager, and progress monitor objects are +defined as separate objects in order to simplify application-specific +customization of the JPEG library. A surrounding application may override +individual methods or supply its own all-new implementation of one of these +objects. The object interfaces for these objects are therefore treated as +part of the application interface of the library, whereas the other objects +are internal to the library. + +The error handler and memory manager are shared by JPEG compression and +decompression; the progress monitor, if used, may be shared as well. + + +*** Decompression object structure *** + +Here is a sketch of the logical structure of the JPEG decompression library: + + |-- Entropy decoding + |-- Coefficient controller --| + | |-- Dequantize, Inverse DCT +Main controller --| + | |-- Upsampling + |-- Postprocessing controller --| |-- Colorspace conversion + |-- Color quantization + |-- Color precision reduction + +As before, this diagram also represents typical control flow. The objects +shown are: + +* Main controller: buffer controller for the subsampled-data buffer, which + holds the output of JPEG decompression proper. This controller's primary + task is to feed the postprocessing procedure. Some upsampling algorithms + may require context rows above and below the current row group; when this + is true, the main controller is responsible for managing its buffer so as + to make context rows available. In the current design, the main buffer is + always a strip buffer; a full-image buffer is never required. + +* Coefficient controller: buffer controller for the DCT-coefficient data. + This controller handles MCU disassembly, including deletion of any dummy + DCT blocks at the right or bottom edge. When reading a multiscan JPEG + file, this controller is responsible for buffering the full image. + (Buffering DCT coefficients, rather than samples, is necessary to support + progressive JPEG.) The equivalent of one fully interleaved MCU row of + subsampled data is processed per call, even when the source JPEG file is + noninterleaved. + +* Entropy decoding: Read coded data from the data source module and perform + Huffman or arithmetic entropy decoding. Works on one MCU per call. + For progressive JPEG decoding, the coefficient controller supplies the prior + coefficients of each MCU (initially all zeroes), which the entropy decoder + modifies in each scan. + +* Dequantization and inverse DCT: like it says. Note that the coefficients + buffered by the coefficient controller have NOT been dequantized; we + merge dequantization and inverse DCT into a single step for speed reasons. + When scaled-down output is asked for, simplified DCT algorithms may be used + that emit only 1x1, 2x2, or 4x4 samples per DCT block, not the full 8x8. + Works on one DCT block at a time. + +* Postprocessing controller: buffer controller for the color quantization + input buffer, when quantization is in use. (Without quantization, this + controller just calls the upsampler.) For two-pass quantization, this + controller is responsible for buffering the full-image data. + +* Upsampling: restores chroma components to full size. (May support more + general output rescaling, too. Note that if undersized DCT outputs have + been emitted by the DCT module, this module must adjust so that properly + sized outputs are created.) Works on one row group at a time. This module + also calls the color conversion module, so its top level is effectively a + buffer controller for the upsampling->color conversion buffer. However, in + all but the highest-quality operating modes, upsampling and color + conversion are likely to be merged into a single step. + +* Colorspace conversion: convert from JPEG color space to output color space, + and change data layout from separate component planes to pixel-interleaved. + Works on one pixel row at a time. + +* Color quantization: reduce the data to colormapped form, using either an + externally specified colormap or an internally generated one. This module + is not used for full-color output. Works on one pixel row at a time; may + require two passes to generate a color map. Note that the output will + always be a single component representing colormap indexes. In the current + design, the output values are JSAMPLEs, so an 8-bit compilation cannot + quantize to more than 256 colors. This is unlikely to be a problem in + practice. + +* Color reduction: this module handles color precision reduction, e.g., + generating 15-bit color (5 bits/primary) from JPEG's 24-bit output. + Not quite clear yet how this should be handled... should we merge it with + colorspace conversion??? + +Note that some high-speed operating modes might condense the entire +postprocessing sequence to a single module (upsample, color convert, and +quantize in one step). + +In addition to the above objects, the decompression library includes these +objects: + +* Master control: determines the number of passes required, controls overall + and per-pass initialization of the other modules. This is subdivided into + input and output control: jdinput.c controls only input-side processing, + while jdmaster.c handles overall initialization and output-side control. + +* Marker reading: decodes JPEG markers (except for RSTn). + +* Data source manager: supplies the input JPEG datastream. The source + manager supplied with the library knows how to read from a stdio stream; + for other behaviors, the surrounding application may provide its own source + manager. + +* Memory manager: same as for compression library. + +* Error handler: same as for compression library. + +* Progress monitor: same as for compression library. + +As with compression, the data source manager, error handler, and progress +monitor are candidates for replacement by a surrounding application. + + +*** Decompression input and output separation *** + +To support efficient incremental display of progressive JPEG files, the +decompressor is divided into two sections that can run independently: + +1. Data input includes marker parsing, entropy decoding, and input into the + coefficient controller's DCT coefficient buffer. Note that this + processing is relatively cheap and fast. + +2. Data output reads from the DCT coefficient buffer and performs the IDCT + and all postprocessing steps. + +For a progressive JPEG file, the data input processing is allowed to get +arbitrarily far ahead of the data output processing. (This occurs only +if the application calls jpeg_consume_input(); otherwise input and output +run in lockstep, since the input section is called only when the output +section needs more data.) In this way the application can avoid making +extra display passes when data is arriving faster than the display pass +can run. Furthermore, it is possible to abort an output pass without +losing anything, since the coefficient buffer is read-only as far as the +output section is concerned. See libjpeg.doc for more detail. + +A full-image coefficient array is only created if the JPEG file has multiple +scans (or if the application specifies buffered-image mode anyway). When +reading a single-scan file, the coefficient controller normally creates only +a one-MCU buffer, so input and output processing must run in lockstep in this +case. jpeg_consume_input() is effectively a no-op in this situation. + +The main impact of dividing the decompressor in this fashion is that we must +be very careful with shared variables in the cinfo data structure. Each +variable that can change during the course of decompression must be +classified as belonging to data input or data output, and each section must +look only at its own variables. For example, the data output section may not +depend on any of the variables that describe the current scan in the JPEG +file, because these may change as the data input section advances into a new +scan. + +The progress monitor is (somewhat arbitrarily) defined to treat input of the +file as one pass when buffered-image mode is not used, and to ignore data +input work completely when buffered-image mode is used. Note that the +library has no reliable way to predict the number of passes when dealing +with a progressive JPEG file, nor can it predict the number of output passes +in buffered-image mode. So the work estimate is inherently bogus anyway. + +No comparable division is currently made in the compression library, because +there isn't any real need for it. + + +*** Data formats *** + +Arrays of pixel sample values use the following data structure: + + typedef something JSAMPLE; a pixel component value, 0..MAXJSAMPLE + typedef JSAMPLE *JSAMPROW; ptr to a row of samples + typedef JSAMPROW *JSAMPARRAY; ptr to a list of rows + typedef JSAMPARRAY *JSAMPIMAGE; ptr to a list of color-component arrays + +The basic element type JSAMPLE will typically be one of unsigned char, +(signed) char, or short. Short will be used if samples wider than 8 bits are +to be supported (this is a compile-time option). Otherwise, unsigned char is +used if possible. If the compiler only supports signed chars, then it is +necessary to mask off the value when reading. Thus, all reads of JSAMPLE +values must be coded as "GETJSAMPLE(value)", where the macro will be defined +as "((value) & 0xFF)" on signed-char machines and "((int) (value))" elsewhere. + +With these conventions, JSAMPLE values can be assumed to be >= 0. This helps +simplify correct rounding during downsampling, etc. The JPEG standard's +specification that sample values run from -128..127 is accommodated by +subtracting 128 just as the sample value is copied into the source array for +the DCT step (this will be an array of signed ints). Similarly, during +decompression the output of the IDCT step will be immediately shifted back to +0..255. (NB: different values are required when 12-bit samples are in use. +The code is written in terms of MAXJSAMPLE and CENTERJSAMPLE, which will be +defined as 255 and 128 respectively in an 8-bit implementation, and as 4095 +and 2048 in a 12-bit implementation.) + +We use a pointer per row, rather than a two-dimensional JSAMPLE array. This +choice costs only a small amount of memory and has several benefits: +* Code using the data structure doesn't need to know the allocated width of + the rows. This simplifies edge expansion/compression, since we can work + in an array that's wider than the logical picture width. +* Indexing doesn't require multiplication; this is a performance win on many + machines. +* Arrays with more than 64K total elements can be supported even on machines + where malloc() cannot allocate chunks larger than 64K. +* The rows forming a component array may be allocated at different times + without extra copying. This trick allows some speedups in smoothing steps + that need access to the previous and next rows. + +Note that each color component is stored in a separate array; we don't use the +traditional layout in which the components of a pixel are stored together. +This simplifies coding of modules that work on each component independently, +because they don't need to know how many components there are. Furthermore, +we can read or write each component to a temporary file independently, which +is helpful when dealing with noninterleaved JPEG files. + +In general, a specific sample value is accessed by code such as + GETJSAMPLE(image[colorcomponent][row][col]) +where col is measured from the image left edge, but row is measured from the +first sample row currently in memory. Either of the first two indexings can +be precomputed by copying the relevant pointer. + + +Since most image-processing applications prefer to work on images in which +the components of a pixel are stored together, the data passed to or from the +surrounding application uses the traditional convention: a single pixel is +represented by N consecutive JSAMPLE values, and an image row is an array of +(# of color components)*(image width) JSAMPLEs. One or more rows of data can +be represented by a pointer of type JSAMPARRAY in this scheme. This scheme is +converted to component-wise storage inside the JPEG library. (Applications +that want to skip JPEG preprocessing or postprocessing will have to contend +with component-wise storage.) + + +Arrays of DCT-coefficient values use the following data structure: + + typedef short JCOEF; a 16-bit signed integer + typedef JCOEF JBLOCK[DCTSIZE2]; an 8x8 block of coefficients + typedef JBLOCK *JBLOCKROW; ptr to one horizontal row of 8x8 blocks + typedef JBLOCKROW *JBLOCKARRAY; ptr to a list of such rows + typedef JBLOCKARRAY *JBLOCKIMAGE; ptr to a list of color component arrays + +The underlying type is at least a 16-bit signed integer; while "short" is big +enough on all machines of interest, on some machines it is preferable to use +"int" for speed reasons, despite the storage cost. Coefficients are grouped +into 8x8 blocks (but we always use #defines DCTSIZE and DCTSIZE2 rather than +"8" and "64"). + +The contents of a coefficient block may be in either "natural" or zigzagged +order, and may be true values or divided by the quantization coefficients, +depending on where the block is in the processing pipeline. In the current +library, coefficient blocks are kept in natural order everywhere; the entropy +codecs zigzag or dezigzag the data as it is written or read. The blocks +contain quantized coefficients everywhere outside the DCT/IDCT subsystems. +(This latter decision may need to be revisited to support variable +quantization a la JPEG Part 3.) + +Notice that the allocation unit is now a row of 8x8 blocks, corresponding to +eight rows of samples. Otherwise the structure is much the same as for +samples, and for the same reasons. + +On machines where malloc() can't handle a request bigger than 64Kb, this data +structure limits us to rows of less than 512 JBLOCKs, or a picture width of +4000+ pixels. This seems an acceptable restriction. + + +On 80x86 machines, the bottom-level pointer types (JSAMPROW and JBLOCKROW) +must be declared as "far" pointers, but the upper levels can be "near" +(implying that the pointer lists are allocated in the DS segment). +We use a #define symbol FAR, which expands to the "far" keyword when +compiling on 80x86 machines and to nothing elsewhere. + + +*** Suspendable processing *** + +In some applications it is desirable to use the JPEG library as an +incremental, memory-to-memory filter. In this situation the data source or +destination may be a limited-size buffer, and we can't rely on being able to +empty or refill the buffer at arbitrary times. Instead the application would +like to have control return from the library at buffer overflow/underrun, and +then resume compression or decompression at a later time. + +This scenario is supported for simple cases. (For anything more complex, we +recommend that the application "bite the bullet" and develop real multitasking +capability.) The libjpeg.doc file goes into more detail about the usage and +limitations of this capability; here we address the implications for library +structure. + +The essence of the problem is that the entropy codec (coder or decoder) must +be prepared to stop at arbitrary times. In turn, the controllers that call +the entropy codec must be able to stop before having produced or consumed all +the data that they normally would handle in one call. That part is reasonably +straightforward: we make the controller call interfaces include "progress +counters" which indicate the number of data chunks successfully processed, and +we require callers to test the counter rather than just assume all of the data +was processed. + +Rather than trying to restart at an arbitrary point, the current Huffman +codecs are designed to restart at the beginning of the current MCU after a +suspension due to buffer overflow/underrun. At the start of each call, the +codec's internal state is loaded from permanent storage (in the JPEG object +structures) into local variables. On successful completion of the MCU, the +permanent state is updated. (This copying is not very expensive, and may even +lead to *improved* performance if the local variables can be registerized.) +If a suspension occurs, the codec simply returns without updating the state, +thus effectively reverting to the start of the MCU. Note that this implies +leaving some data unprocessed in the source/destination buffer (ie, the +compressed partial MCU). The data source/destination module interfaces are +specified so as to make this possible. This also implies that the data buffer +must be large enough to hold a worst-case compressed MCU; a couple thousand +bytes should be enough. + +In a successive-approximation AC refinement scan, the progressive Huffman +decoder has to be able to undo assignments of newly nonzero coefficients if it +suspends before the MCU is complete, since decoding requires distinguishing +previously-zero and previously-nonzero coefficients. This is a bit tedious +but probably won't have much effect on performance. Other variants of Huffman +decoding need not worry about this, since they will just store the same values +again if forced to repeat the MCU. + +This approach would probably not work for an arithmetic codec, since its +modifiable state is quite large and couldn't be copied cheaply. Instead it +would have to suspend and resume exactly at the point of the buffer end. + +The JPEG marker reader is designed to cope with suspension at an arbitrary +point. It does so by backing up to the start of the marker parameter segment, +so the data buffer must be big enough to hold the largest marker of interest. +Again, a couple KB should be adequate. (A special "skip" convention is used +to bypass COM and APPn markers, so these can be larger than the buffer size +without causing problems; otherwise a 64K buffer would be needed in the worst +case.) + +The JPEG marker writer currently does *not* cope with suspension. I feel that +this is not necessary; it is much easier simply to require the application to +ensure there is enough buffer space before starting. (An empty 2K buffer is +more than sufficient for the header markers; and ensuring there are a dozen or +two bytes available before calling jpeg_finish_compress() will suffice for the +trailer.) This would not work for writing multi-scan JPEG files, but +we simply do not intend to support that capability with suspension. + + +*** Memory manager services *** + +The JPEG library's memory manager controls allocation and deallocation of +memory, and it manages large "virtual" data arrays on machines where the +operating system does not provide virtual memory. Note that the same +memory manager serves both compression and decompression operations. + +In all cases, allocated objects are tied to a particular compression or +decompression master record, and they will be released when that master +record is destroyed. + +The memory manager does not provide explicit deallocation of objects. +Instead, objects are created in "pools" of free storage, and a whole pool +can be freed at once. This approach helps prevent storage-leak bugs, and +it speeds up operations whenever malloc/free are slow (as they often are). +The pools can be regarded as lifetime identifiers for objects. Two +pools/lifetimes are defined: + * JPOOL_PERMANENT lasts until master record is destroyed + * JPOOL_IMAGE lasts until done with image (JPEG datastream) +Permanent lifetime is used for parameters and tables that should be carried +across from one datastream to another; this includes all application-visible +parameters. Image lifetime is used for everything else. (A third lifetime, +JPOOL_PASS = one processing pass, was originally planned. However it was +dropped as not being worthwhile. The actual usage patterns are such that the +peak memory usage would be about the same anyway; and having per-pass storage +substantially complicates the virtual memory allocation rules --- see below.) + +The memory manager deals with three kinds of object: +1. "Small" objects. Typically these require no more than 10K-20K total. +2. "Large" objects. These may require tens to hundreds of K depending on + image size. Semantically they behave the same as small objects, but we + distinguish them for two reasons: + * On MS-DOS machines, large objects are referenced by FAR pointers, + small objects by NEAR pointers. + * Pool allocation heuristics may differ for large and small objects. + Note that individual "large" objects cannot exceed the size allowed by + type size_t, which may be 64K or less on some machines. +3. "Virtual" objects. These are large 2-D arrays of JSAMPLEs or JBLOCKs + (typically large enough for the entire image being processed). The + memory manager provides stripwise access to these arrays. On machines + without virtual memory, the rest of the array may be swapped out to a + temporary file. + +(Note: JSAMPARRAY and JBLOCKARRAY data structures are a combination of large +objects for the data proper and small objects for the row pointers. For +convenience and speed, the memory manager provides single routines to create +these structures. Similarly, virtual arrays include a small control block +and a JSAMPARRAY or JBLOCKARRAY working buffer, all created with one call.) + +In the present implementation, virtual arrays are only permitted to have image +lifespan. (Permanent lifespan would not be reasonable, and pass lifespan is +not very useful since a virtual array's raison d'etre is to store data for +multiple passes through the image.) We also expect that only "small" objects +will be given permanent lifespan, though this restriction is not required by +the memory manager. + +In a non-virtual-memory machine, some performance benefit can be gained by +making the in-memory buffers for virtual arrays be as large as possible. +(For small images, the buffers might fit entirely in memory, so blind +swapping would be very wasteful.) The memory manager will adjust the height +of the buffers to fit within a prespecified maximum memory usage. In order +to do this in a reasonably optimal fashion, the manager needs to allocate all +of the virtual arrays at once. Therefore, there isn't a one-step allocation +routine for virtual arrays; instead, there is a "request" routine that simply +allocates the control block, and a "realize" routine (called just once) that +determines space allocation and creates all of the actual buffers. The +realize routine must allow for space occupied by non-virtual large objects. +(We don't bother to factor in the space needed for small objects, on the +grounds that it isn't worth the trouble.) + +To support all this, we establish the following protocol for doing business +with the memory manager: + 1. Modules must request virtual arrays (which may have only image lifespan) + during the initial setup phase, i.e., in their jinit_xxx routines. + 2. All "large" objects (including JSAMPARRAYs and JBLOCKARRAYs) must also be + allocated during initial setup. + 3. realize_virt_arrays will be called at the completion of initial setup. + The above conventions ensure that sufficient information is available + for it to choose a good size for virtual array buffers. +Small objects of any lifespan may be allocated at any time. We expect that +the total space used for small objects will be small enough to be negligible +in the realize_virt_arrays computation. + +In a virtual-memory machine, we simply pretend that the available space is +infinite, thus causing realize_virt_arrays to decide that it can allocate all +the virtual arrays as full-size in-memory buffers. The overhead of the +virtual-array access protocol is very small when no swapping occurs. + +A virtual array can be specified to be "pre-zeroed"; when this flag is set, +never-yet-written sections of the array are set to zero before being made +available to the caller. If this flag is not set, never-written sections +of the array contain garbage. (This feature exists primarily because the +equivalent logic would otherwise be needed in jdcoefct.c for progressive +JPEG mode; we may as well make it available for possible other uses.) + +The first write pass on a virtual array is required to occur in top-to-bottom +order; read passes, as well as any write passes after the first one, may +access the array in any order. This restriction exists partly to simplify +the virtual array control logic, and partly because some file systems may not +support seeking beyond the current end-of-file in a temporary file. The main +implication of this restriction is that rearrangement of rows (such as +converting top-to-bottom data order to bottom-to-top) must be handled while +reading data out of the virtual array, not while putting it in. + + +*** Memory manager internal structure *** + +To isolate system dependencies as much as possible, we have broken the +memory manager into two parts. There is a reasonably system-independent +"front end" (jmemmgr.c) and a "back end" that contains only the code +likely to change across systems. All of the memory management methods +outlined above are implemented by the front end. The back end provides +the following routines for use by the front end (none of these routines +are known to the rest of the JPEG code): + +jpeg_mem_init, jpeg_mem_term system-dependent initialization/shutdown + +jpeg_get_small, jpeg_free_small interface to malloc and free library routines + (or their equivalents) + +jpeg_get_large, jpeg_free_large interface to FAR malloc/free in MSDOS machines; + else usually the same as + jpeg_get_small/jpeg_free_small + +jpeg_mem_available estimate available memory + +jpeg_open_backing_store create a backing-store object + +read_backing_store, manipulate a backing-store object +write_backing_store, +close_backing_store + +On some systems there will be more than one type of backing-store object +(specifically, in MS-DOS a backing store file might be an area of extended +memory as well as a disk file). jpeg_open_backing_store is responsible for +choosing how to implement a given object. The read/write/close routines +are method pointers in the structure that describes a given object; this +lets them be different for different object types. + +It may be necessary to ensure that backing store objects are explicitly +released upon abnormal program termination. For example, MS-DOS won't free +extended memory by itself. To support this, we will expect the main program +or surrounding application to arrange to call self_destruct (typically via +jpeg_destroy) upon abnormal termination. This may require a SIGINT signal +handler or equivalent. We don't want to have the back end module install its +own signal handler, because that would pre-empt the surrounding application's +ability to control signal handling. + +The IJG distribution includes several memory manager back end implementations. +Usually the same back end should be suitable for all applications on a given +system, but it is possible for an application to supply its own back end at +need. + + +*** Implications of DNL marker *** + +Some JPEG files may use a DNL marker to postpone definition of the image +height (this would be useful for a fax-like scanner's output, for instance). +In these files the SOF marker claims the image height is 0, and you only +find out the true image height at the end of the first scan. + +We could read these files as follows: +1. Upon seeing zero image height, replace it by 65535 (the maximum allowed). +2. When the DNL is found, update the image height in the global image + descriptor. +This implies that control modules must avoid making copies of the image +height, and must re-test for termination after each MCU row. This would +be easy enough to do. + +In cases where image-size data structures are allocated, this approach will +result in very inefficient use of virtual memory or much-larger-than-necessary +temporary files. This seems acceptable for something that probably won't be a +mainstream usage. People might have to forgo use of memory-hogging options +(such as two-pass color quantization or noninterleaved JPEG files) if they +want efficient conversion of such files. (One could improve efficiency by +demanding a user-supplied upper bound for the height, less than 65536; in most +cases it could be much less.) + +The standard also permits the SOF marker to overestimate the image height, +with a DNL to give the true, smaller height at the end of the first scan. +This would solve the space problems if the overestimate wasn't too great. +However, it implies that you don't even know whether DNL will be used. + +This leads to a couple of very serious objections: +1. Testing for a DNL marker must occur in the inner loop of the decompressor's + Huffman decoder; this implies a speed penalty whether the feature is used + or not. +2. There is no way to hide the last-minute change in image height from an + application using the decoder. Thus *every* application using the IJG + library would suffer a complexity penalty whether it cared about DNL or + not. +We currently do not support DNL because of these problems. + +A different approach is to insist that DNL-using files be preprocessed by a +separate program that reads ahead to the DNL, then goes back and fixes the SOF +marker. This is a much simpler solution and is probably far more efficient. +Even if one wants piped input, buffering the first scan of the JPEG file needs +a lot smaller temp file than is implied by the maximum-height method. For +this approach we'd simply treat DNL as a no-op in the decompressor (at most, +check that it matches the SOF image height). + +We will not worry about making the compressor capable of outputting DNL. +Something similar to the first scheme above could be applied if anyone ever +wants to make that work. diff --git a/Utilities/FLTK/jpeg/usage.doc b/Utilities/FLTK/jpeg/usage.doc new file mode 100644 index 0000000000..8c4970af05 --- /dev/null +++ b/Utilities/FLTK/jpeg/usage.doc @@ -0,0 +1,562 @@ +USAGE instructions for the Independent JPEG Group's JPEG software +================================================================= + +This file describes usage of the JPEG conversion programs cjpeg and djpeg, +as well as the utility programs jpegtran, rdjpgcom and wrjpgcom. (See +the other documentation files if you wish to use the JPEG library within +your own programs.) + +If you are on a Unix machine you may prefer to read the Unix-style manual +pages in files cjpeg.1, djpeg.1, jpegtran.1, rdjpgcom.1, wrjpgcom.1. + + +INTRODUCTION + +These programs implement JPEG image compression and decompression. JPEG +(pronounced "jay-peg") is a standardized compression method for full-color +and gray-scale images. JPEG is designed to handle "real-world" scenes, +for example scanned photographs. Cartoons, line drawings, and other +non-realistic images are not JPEG's strong suit; on that sort of material +you may get poor image quality and/or little compression. + +JPEG is lossy, meaning that the output image is not necessarily identical to +the input image. Hence you should not use JPEG if you have to have identical +output bits. However, on typical real-world images, very good compression +levels can be obtained with no visible change, and amazingly high compression +is possible if you can tolerate a low-quality image. You can trade off image +quality against file size by adjusting the compressor's "quality" setting. + + +GENERAL USAGE + +We provide two programs, cjpeg to compress an image file into JPEG format, +and djpeg to decompress a JPEG file back into a conventional image format. + +On Unix-like systems, you say: + cjpeg [switches] [imagefile] >jpegfile +or + djpeg [switches] [jpegfile] >imagefile +The programs read the specified input file, or standard input if none is +named. They always write to standard output (with trace/error messages to +standard error). These conventions are handy for piping images between +programs. + +On most non-Unix systems, you say: + cjpeg [switches] imagefile jpegfile +or + djpeg [switches] jpegfile imagefile +i.e., both the input and output files are named on the command line. This +style is a little more foolproof, and it loses no functionality if you don't +have pipes. (You can get this style on Unix too, if you prefer, by defining +TWO_FILE_COMMANDLINE when you compile the programs; see install.doc.) + +You can also say: + cjpeg [switches] -outfile jpegfile imagefile +or + djpeg [switches] -outfile imagefile jpegfile +This syntax works on all systems, so it is useful for scripts. + +The currently supported image file formats are: PPM (PBMPLUS color format), +PGM (PBMPLUS gray-scale format), BMP, Targa, and RLE (Utah Raster Toolkit +format). (RLE is supported only if the URT library is available.) +cjpeg recognizes the input image format automatically, with the exception +of some Targa-format files. You have to tell djpeg which format to generate. + +JPEG files are in the defacto standard JFIF file format. There are other, +less widely used JPEG-based file formats, but we don't support them. + +All switch names may be abbreviated; for example, -grayscale may be written +-gray or -gr. Most of the "basic" switches can be abbreviated to as little as +one letter. Upper and lower case are equivalent (-BMP is the same as -bmp). +British spellings are also accepted (e.g., -greyscale), though for brevity +these are not mentioned below. + + +CJPEG DETAILS + +The basic command line switches for cjpeg are: + + -quality N Scale quantization tables to adjust image quality. + Quality is 0 (worst) to 100 (best); default is 75. + (See below for more info.) + + -grayscale Create monochrome JPEG file from color input. + Be sure to use this switch when compressing a grayscale + BMP file, because cjpeg isn't bright enough to notice + whether a BMP file uses only shades of gray. By + saying -grayscale, you'll get a smaller JPEG file that + takes less time to process. + + -optimize Perform optimization of entropy encoding parameters. + Without this, default encoding parameters are used. + -optimize usually makes the JPEG file a little smaller, + but cjpeg runs somewhat slower and needs much more + memory. Image quality and speed of decompression are + unaffected by -optimize. + + -progressive Create progressive JPEG file (see below). + + -targa Input file is Targa format. Targa files that contain + an "identification" field will not be automatically + recognized by cjpeg; for such files you must specify + -targa to make cjpeg treat the input as Targa format. + For most Targa files, you won't need this switch. + +The -quality switch lets you trade off compressed file size against quality of +the reconstructed image: the higher the quality setting, the larger the JPEG +file, and the closer the output image will be to the original input. Normally +you want to use the lowest quality setting (smallest file) that decompresses +into something visually indistinguishable from the original image. For this +purpose the quality setting should be between 50 and 95; the default of 75 is +often about right. If you see defects at -quality 75, then go up 5 or 10 +counts at a time until you are happy with the output image. (The optimal +setting will vary from one image to another.) + +-quality 100 will generate a quantization table of all 1's, minimizing loss +in the quantization step (but there is still information loss in subsampling, +as well as roundoff error). This setting is mainly of interest for +experimental purposes. Quality values above about 95 are NOT recommended for +normal use; the compressed file size goes up dramatically for hardly any gain +in output image quality. + +In the other direction, quality values below 50 will produce very small files +of low image quality. Settings around 5 to 10 might be useful in preparing an +index of a large image library, for example. Try -quality 2 (or so) for some +amusing Cubist effects. (Note: quality values below about 25 generate 2-byte +quantization tables, which are considered optional in the JPEG standard. +cjpeg emits a warning message when you give such a quality value, because some +other JPEG programs may be unable to decode the resulting file. Use -baseline +if you need to ensure compatibility at low quality values.) + +The -progressive switch creates a "progressive JPEG" file. In this type of +JPEG file, the data is stored in multiple scans of increasing quality. If the +file is being transmitted over a slow communications link, the decoder can use +the first scan to display a low-quality image very quickly, and can then +improve the display with each subsequent scan. The final image is exactly +equivalent to a standard JPEG file of the same quality setting, and the total +file size is about the same --- often a little smaller. CAUTION: progressive +JPEG is not yet widely implemented, so many decoders will be unable to view a +progressive JPEG file at all. + +Switches for advanced users: + + -dct int Use integer DCT method (default). + -dct fast Use fast integer DCT (less accurate). + -dct float Use floating-point DCT method. + The float method is very slightly more accurate than + the int method, but is much slower unless your machine + has very fast floating-point hardware. Also note that + results of the floating-point method may vary slightly + across machines, while the integer methods should give + the same results everywhere. The fast integer method + is much less accurate than the other two. + + -restart N Emit a JPEG restart marker every N MCU rows, or every + N MCU blocks if "B" is attached to the number. + -restart 0 (the default) means no restart markers. + + -smooth N Smooth the input image to eliminate dithering noise. + N, ranging from 1 to 100, indicates the strength of + smoothing. 0 (the default) means no smoothing. + + -maxmemory N Set limit for amount of memory to use in processing + large images. Value is in thousands of bytes, or + millions of bytes if "M" is attached to the number. + For example, -max 4m selects 4000000 bytes. If more + space is needed, temporary files will be used. + + -verbose Enable debug printout. More -v's give more printout. + or -debug Also, version information is printed at startup. + +The -restart option inserts extra markers that allow a JPEG decoder to +resynchronize after a transmission error. Without restart markers, any damage +to a compressed file will usually ruin the image from the point of the error +to the end of the image; with restart markers, the damage is usually confined +to the portion of the image up to the next restart marker. Of course, the +restart markers occupy extra space. We recommend -restart 1 for images that +will be transmitted across unreliable networks such as Usenet. + +The -smooth option filters the input to eliminate fine-scale noise. This is +often useful when converting dithered images to JPEG: a moderate smoothing +factor of 10 to 50 gets rid of dithering patterns in the input file, resulting +in a smaller JPEG file and a better-looking image. Too large a smoothing +factor will visibly blur the image, however. + +Switches for wizards: + + -baseline Force baseline-compatible quantization tables to be + generated. This clamps quantization values to 8 bits + even at low quality settings. (This switch is poorly + named, since it does not ensure that the output is + actually baseline JPEG. For example, you can use + -baseline and -progressive together.) + + -qtables file Use the quantization tables given in the specified + text file. + + -qslots N[,...] Select which quantization table to use for each color + component. + + -sample HxV[,...] Set JPEG sampling factors for each color component. + + -scans file Use the scan script given in the specified text file. + +The "wizard" switches are intended for experimentation with JPEG. If you +don't know what you are doing, DON'T USE THEM. These switches are documented +further in the file wizard.doc. + + +DJPEG DETAILS + +The basic command line switches for djpeg are: + + -colors N Reduce image to at most N colors. This reduces the + or -quantize N number of colors used in the output image, so that it + can be displayed on a colormapped display or stored in + a colormapped file format. For example, if you have + an 8-bit display, you'd need to reduce to 256 or fewer + colors. (-colors is the recommended name, -quantize + is provided only for backwards compatibility.) + + -fast Select recommended processing options for fast, low + quality output. (The default options are chosen for + highest quality output.) Currently, this is equivalent + to "-dct fast -nosmooth -onepass -dither ordered". + + -grayscale Force gray-scale output even if JPEG file is color. + Useful for viewing on monochrome displays; also, + djpeg runs noticeably faster in this mode. + + -scale M/N Scale the output image by a factor M/N. Currently + the scale factor must be 1/1, 1/2, 1/4, or 1/8. + Scaling is handy if the image is larger than your + screen; also, djpeg runs much faster when scaling + down the output. + + -bmp Select BMP output format (Windows flavor). 8-bit + colormapped format is emitted if -colors or -grayscale + is specified, or if the JPEG file is gray-scale; + otherwise, 24-bit full-color format is emitted. + + -gif Select GIF output format. Since GIF does not support + more than 256 colors, -colors 256 is assumed (unless + you specify a smaller number of colors). If you + specify -fast, the default number of colors is 216. + + -os2 Select BMP output format (OS/2 1.x flavor). 8-bit + colormapped format is emitted if -colors or -grayscale + is specified, or if the JPEG file is gray-scale; + otherwise, 24-bit full-color format is emitted. + + -pnm Select PBMPLUS (PPM/PGM) output format (this is the + default format). PGM is emitted if the JPEG file is + gray-scale or if -grayscale is specified; otherwise + PPM is emitted. + + -rle Select RLE output format. (Requires URT library.) + + -targa Select Targa output format. Gray-scale format is + emitted if the JPEG file is gray-scale or if + -grayscale is specified; otherwise, colormapped format + is emitted if -colors is specified; otherwise, 24-bit + full-color format is emitted. + +Switches for advanced users: + + -dct int Use integer DCT method (default). + -dct fast Use fast integer DCT (less accurate). + -dct float Use floating-point DCT method. + The float method is very slightly more accurate than + the int method, but is much slower unless your machine + has very fast floating-point hardware. Also note that + results of the floating-point method may vary slightly + across machines, while the integer methods should give + the same results everywhere. The fast integer method + is much less accurate than the other two. + + -dither fs Use Floyd-Steinberg dithering in color quantization. + -dither ordered Use ordered dithering in color quantization. + -dither none Do not use dithering in color quantization. + By default, Floyd-Steinberg dithering is applied when + quantizing colors; this is slow but usually produces + the best results. Ordered dither is a compromise + between speed and quality; no dithering is fast but + usually looks awful. Note that these switches have + no effect unless color quantization is being done. + Ordered dither is only available in -onepass mode. + + -map FILE Quantize to the colors used in the specified image + file. This is useful for producing multiple files + with identical color maps, or for forcing a predefined + set of colors to be used. The FILE must be a GIF + or PPM file. This option overrides -colors and + -onepass. + + -nosmooth Use a faster, lower-quality upsampling routine. + + -onepass Use one-pass instead of two-pass color quantization. + The one-pass method is faster and needs less memory, + but it produces a lower-quality image. -onepass is + ignored unless you also say -colors N. Also, + the one-pass method is always used for gray-scale + output (the two-pass method is no improvement then). + + -maxmemory N Set limit for amount of memory to use in processing + large images. Value is in thousands of bytes, or + millions of bytes if "M" is attached to the number. + For example, -max 4m selects 4000000 bytes. If more + space is needed, temporary files will be used. + + -verbose Enable debug printout. More -v's give more printout. + or -debug Also, version information is printed at startup. + + +HINTS FOR CJPEG + +Color GIF files are not the ideal input for JPEG; JPEG is really intended for +compressing full-color (24-bit) images. In particular, don't try to convert +cartoons, line drawings, and other images that have only a few distinct +colors. GIF works great on these, JPEG does not. If you want to convert a +GIF to JPEG, you should experiment with cjpeg's -quality and -smooth options +to get a satisfactory conversion. -smooth 10 or so is often helpful. + +Avoid running an image through a series of JPEG compression/decompression +cycles. Image quality loss will accumulate; after ten or so cycles the image +may be noticeably worse than it was after one cycle. It's best to use a +lossless format while manipulating an image, then convert to JPEG format when +you are ready to file the image away. + +The -optimize option to cjpeg is worth using when you are making a "final" +version for posting or archiving. It's also a win when you are using low +quality settings to make very small JPEG files; the percentage improvement +is often a lot more than it is on larger files. (At present, -optimize +mode is always selected when generating progressive JPEG files.) + +GIF input files are no longer supported, to avoid the Unisys LZW patent. +Use a Unisys-licensed program if you need to read a GIF file. (Conversion +of GIF files to JPEG is usually a bad idea anyway.) + + +HINTS FOR DJPEG + +To get a quick preview of an image, use the -grayscale and/or -scale switches. +"-grayscale -scale 1/8" is the fastest case. + +Several options are available that trade off image quality to gain speed. +"-fast" turns on the recommended settings. + +"-dct fast" and/or "-nosmooth" gain speed at a small sacrifice in quality. +When producing a color-quantized image, "-onepass -dither ordered" is fast but +much lower quality than the default behavior. "-dither none" may give +acceptable results in two-pass mode, but is seldom tolerable in one-pass mode. + +If you are fortunate enough to have very fast floating point hardware, +"-dct float" may be even faster than "-dct fast". But on most machines +"-dct float" is slower than "-dct int"; in this case it is not worth using, +because its theoretical accuracy advantage is too small to be significant +in practice. + +Two-pass color quantization requires a good deal of memory; on MS-DOS machines +it may run out of memory even with -maxmemory 0. In that case you can still +decompress, with some loss of image quality, by specifying -onepass for +one-pass quantization. + +To avoid the Unisys LZW patent, djpeg produces uncompressed GIF files. These +are larger than they should be, but are readable by standard GIF decoders. + + +HINTS FOR BOTH PROGRAMS + +If more space is needed than will fit in the available main memory (as +determined by -maxmemory), temporary files will be used. (MS-DOS versions +will try to get extended or expanded memory first.) The temporary files are +often rather large: in typical cases they occupy three bytes per pixel, for +example 3*800*600 = 1.44Mb for an 800x600 image. If you don't have enough +free disk space, leave out -progressive and -optimize (for cjpeg) or specify +-onepass (for djpeg). + +On MS-DOS, the temporary files are created in the directory named by the TMP +or TEMP environment variable, or in the current directory if neither of those +exist. Amiga implementations put the temp files in the directory named by +JPEGTMP:, so be sure to assign JPEGTMP: to a disk partition with adequate free +space. + +The default memory usage limit (-maxmemory) is set when the software is +compiled. If you get an "insufficient memory" error, try specifying a smaller +-maxmemory value, even -maxmemory 0 to use the absolute minimum space. You +may want to recompile with a smaller default value if this happens often. + +On machines that have "environment" variables, you can define the environment +variable JPEGMEM to set the default memory limit. The value is specified as +described for the -maxmemory switch. JPEGMEM overrides the default value +specified when the program was compiled, and itself is overridden by an +explicit -maxmemory switch. + +On MS-DOS machines, -maxmemory is the amount of main (conventional) memory to +use. (Extended or expanded memory is also used if available.) Most +DOS-specific versions of this software do their own memory space estimation +and do not need you to specify -maxmemory. + + +JPEGTRAN + +jpegtran performs various useful transformations of JPEG files. +It can translate the coded representation from one variant of JPEG to another, +for example from baseline JPEG to progressive JPEG or vice versa. It can also +perform some rearrangements of the image data, for example turning an image +from landscape to portrait format by rotation. + +jpegtran works by rearranging the compressed data (DCT coefficients), without +ever fully decoding the image. Therefore, its transformations are lossless: +there is no image degradation at all, which would not be true if you used +djpeg followed by cjpeg to accomplish the same conversion. But by the same +token, jpegtran cannot perform lossy operations such as changing the image +quality. + +jpegtran uses a command line syntax similar to cjpeg or djpeg. +On Unix-like systems, you say: + jpegtran [switches] [inputfile] >outputfile +On most non-Unix systems, you say: + jpegtran [switches] inputfile outputfile +where both the input and output files are JPEG files. + +To specify the coded JPEG representation used in the output file, +jpegtran accepts a subset of the switches recognized by cjpeg: + -optimize Perform optimization of entropy encoding parameters. + -progressive Create progressive JPEG file. + -restart N Emit a JPEG restart marker every N MCU rows, or every + N MCU blocks if "B" is attached to the number. + -scans file Use the scan script given in the specified text file. +See the previous discussion of cjpeg for more details about these switches. +If you specify none of these switches, you get a plain baseline-JPEG output +file. The quality setting and so forth are determined by the input file. + +The image can be losslessly transformed by giving one of these switches: + -flip horizontal Mirror image horizontally (left-right). + -flip vertical Mirror image vertically (top-bottom). + -rotate 90 Rotate image 90 degrees clockwise. + -rotate 180 Rotate image 180 degrees. + -rotate 270 Rotate image 270 degrees clockwise (or 90 ccw). + -transpose Transpose image (across UL-to-LR axis). + -transverse Transverse transpose (across UR-to-LL axis). + +The transpose transformation has no restrictions regarding image dimensions. +The other transformations operate rather oddly if the image dimensions are not +a multiple of the iMCU size (usually 8 or 16 pixels), because they can only +transform complete blocks of DCT coefficient data in the desired way. + +jpegtran's default behavior when transforming an odd-size image is designed +to preserve exact reversibility and mathematical consistency of the +transformation set. As stated, transpose is able to flip the entire image +area. Horizontal mirroring leaves any partial iMCU column at the right edge +untouched, but is able to flip all rows of the image. Similarly, vertical +mirroring leaves any partial iMCU row at the bottom edge untouched, but is +able to flip all columns. The other transforms can be built up as sequences +of transpose and flip operations; for consistency, their actions on edge +pixels are defined to be the same as the end result of the corresponding +transpose-and-flip sequence. + +For practical use, you may prefer to discard any untransformable edge pixels +rather than having a strange-looking strip along the right and/or bottom edges +of a transformed image. To do this, add the -trim switch: + -trim Drop non-transformable edge blocks. +Obviously, a transformation with -trim is not reversible, so strictly speaking +jpegtran with this switch is not lossless. Also, the expected mathematical +equivalences between the transformations no longer hold. For example, +"-rot 270 -trim" trims only the bottom edge, but "-rot 90 -trim" followed by +"-rot 180 -trim" trims both edges. + +Another not-strictly-lossless transformation switch is: + -grayscale Force grayscale output. +This option discards the chrominance channels if the input image is YCbCr +(ie, a standard color JPEG), resulting in a grayscale JPEG file. The +luminance channel is preserved exactly, so this is a better method of reducing +to grayscale than decompression, conversion, and recompression. This switch +is particularly handy for fixing a monochrome picture that was mistakenly +encoded as a color JPEG. (In such a case, the space savings from getting rid +of the near-empty chroma channels won't be large; but the decoding time for +a grayscale JPEG is substantially less than that for a color JPEG.) + +jpegtran also recognizes these switches that control what to do with "extra" +markers, such as comment blocks: + -copy none Copy no extra markers from source file. This setting + suppresses all comments and other excess baggage + present in the source file. + -copy comments Copy only comment markers. This setting copies + comments from the source file, but discards + any other inessential data. + -copy all Copy all extra markers. This setting preserves + miscellaneous markers found in the source file, such + as JFIF thumbnails and Photoshop settings. In some + files these extra markers can be sizable. +The default behavior is -copy comments. (Note: in IJG releases v6 and v6a, +jpegtran always did the equivalent of -copy none.) + +Additional switches recognized by jpegtran are: + -outfile filename + -maxmemory N + -verbose + -debug +These work the same as in cjpeg or djpeg. + + +THE COMMENT UTILITIES + +The JPEG standard allows "comment" (COM) blocks to occur within a JPEG file. +Although the standard doesn't actually define what COM blocks are for, they +are widely used to hold user-supplied text strings. This lets you add +annotations, titles, index terms, etc to your JPEG files, and later retrieve +them as text. COM blocks do not interfere with the image stored in the JPEG +file. The maximum size of a COM block is 64K, but you can have as many of +them as you like in one JPEG file. + +We provide two utility programs to display COM block contents and add COM +blocks to a JPEG file. + +rdjpgcom searches a JPEG file and prints the contents of any COM blocks on +standard output. The command line syntax is + rdjpgcom [-verbose] [inputfilename] +The switch "-verbose" (or just "-v") causes rdjpgcom to also display the JPEG +image dimensions. If you omit the input file name from the command line, +the JPEG file is read from standard input. (This may not work on some +operating systems, if binary data can't be read from stdin.) + +wrjpgcom adds a COM block, containing text you provide, to a JPEG file. +Ordinarily, the COM block is added after any existing COM blocks, but you +can delete the old COM blocks if you wish. wrjpgcom produces a new JPEG +file; it does not modify the input file. DO NOT try to overwrite the input +file by directing wrjpgcom's output back into it; on most systems this will +just destroy your file. + +The command line syntax for wrjpgcom is similar to cjpeg's. On Unix-like +systems, it is + wrjpgcom [switches] [inputfilename] +The output file is written to standard output. The input file comes from +the named file, or from standard input if no input file is named. + +On most non-Unix systems, the syntax is + wrjpgcom [switches] inputfilename outputfilename +where both input and output file names must be given explicitly. + +wrjpgcom understands three switches: + -replace Delete any existing COM blocks from the file. + -comment "Comment text" Supply new COM text on command line. + -cfile name Read text for new COM block from named file. +(Switch names can be abbreviated.) If you have only one line of comment text +to add, you can provide it on the command line with -comment. The comment +text must be surrounded with quotes so that it is treated as a single +argument. Longer comments can be read from a text file. + +If you give neither -comment nor -cfile, then wrjpgcom will read the comment +text from standard input. (In this case an input image file name MUST be +supplied, so that the source JPEG file comes from somewhere else.) You can +enter multiple lines, up to 64KB worth. Type an end-of-file indicator +(usually control-D or control-Z) to terminate the comment text entry. + +wrjpgcom will not add a COM block if the provided comment string is empty. +Therefore -replace -comment "" can be used to delete all COM blocks from a +file. + +These utility programs do not depend on the IJG JPEG library. In +particular, the source code for rdjpgcom is intended as an illustration of +the minimum amount of code required to parse a JPEG file header correctly. diff --git a/Utilities/FLTK/jpeg/wizard.doc b/Utilities/FLTK/jpeg/wizard.doc new file mode 100644 index 0000000000..54170b227d --- /dev/null +++ b/Utilities/FLTK/jpeg/wizard.doc @@ -0,0 +1,211 @@ +Advanced usage instructions for the Independent JPEG Group's JPEG software +========================================================================== + +This file describes cjpeg's "switches for wizards". + +The "wizard" switches are intended for experimentation with JPEG by persons +who are reasonably knowledgeable about the JPEG standard. If you don't know +what you are doing, DON'T USE THESE SWITCHES. You'll likely produce files +with worse image quality and/or poorer compression than you'd get from the +default settings. Furthermore, these switches must be used with caution +when making files intended for general use, because not all JPEG decoders +will support unusual JPEG parameter settings. + + +Quantization Table Adjustment +----------------------------- + +Ordinarily, cjpeg starts with a default set of tables (the same ones given +as examples in the JPEG standard) and scales them up or down according to +the -quality setting. The details of the scaling algorithm can be found in +jcparam.c. At very low quality settings, some quantization table entries +can get scaled up to values exceeding 255. Although 2-byte quantization +values are supported by the IJG software, this feature is not in baseline +JPEG and is not supported by all implementations. If you need to ensure +wide compatibility of low-quality files, you can constrain the scaled +quantization values to no more than 255 by giving the -baseline switch. +Note that use of -baseline will result in poorer quality for the same file +size, since more bits than necessary are expended on higher AC coefficients. + +You can substitute a different set of quantization values by using the +-qtables switch: + + -qtables file Use the quantization tables given in the named file. + +The specified file should be a text file containing decimal quantization +values. The file should contain one to four tables, each of 64 elements. +The tables are implicitly numbered 0,1,etc. in order of appearance. Table +entries appear in normal array order (NOT in the zigzag order in which they +will be stored in the JPEG file). + +Quantization table files are free format, in that arbitrary whitespace can +appear between numbers. Also, comments can be included: a comment starts +with '#' and extends to the end of the line. Here is an example file that +duplicates the default quantization tables: + + # Quantization tables given in JPEG spec, section K.1 + + # This is table 0 (the luminance table): + 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 + + # This is table 1 (the chrominance table): + 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 + +If the -qtables switch is used without -quality, then the specified tables +are used exactly as-is. If both -qtables and -quality are used, then the +tables taken from the file are scaled in the same fashion that the default +tables would be scaled for that quality setting. If -baseline appears, then +the quantization values are constrained to the range 1-255. + +By default, cjpeg will use quantization table 0 for luminance components and +table 1 for chrominance components. To override this choice, use the -qslots +switch: + + -qslots N[,...] Select which quantization table to use for + each color component. + +The -qslots switch specifies a quantization table number for each color +component, in the order in which the components appear in the JPEG SOF marker. +For example, to create a separate table for each of Y,Cb,Cr, you could +provide a -qtables file that defines three quantization tables and say +"-qslots 0,1,2". If -qslots gives fewer table numbers than there are color +components, then the last table number is repeated as necessary. + + +Sampling Factor Adjustment +-------------------------- + +By default, cjpeg uses 2:1 horizontal and vertical downsampling when +compressing YCbCr data, and no downsampling for all other color spaces. +You can override this default with the -sample switch: + + -sample HxV[,...] Set JPEG sampling factors for each color + component. + +The -sample switch specifies the JPEG sampling factors for each color +component, in the order in which they appear in the JPEG SOF marker. +If you specify fewer HxV pairs than there are components, the remaining +components are set to 1x1 sampling. For example, the default YCbCr setting +is equivalent to "-sample 2x2,1x1,1x1", which can be abbreviated to +"-sample 2x2". + +There are still some JPEG decoders in existence that support only 2x1 +sampling (also called 4:2:2 sampling). Compatibility with such decoders can +be achieved by specifying "-sample 2x1". This is not recommended unless +really necessary, since it increases file size and encoding/decoding time +with very little quality gain. + + +Multiple Scan / Progression Control +----------------------------------- + +By default, cjpeg emits a single-scan sequential JPEG file. The +-progressive switch generates a progressive JPEG file using a default series +of progression parameters. You can create multiple-scan sequential JPEG +files or progressive JPEG files with custom progression parameters by using +the -scans switch: + + -scans file Use the scan sequence given in the named file. + +The specified file should be a text file containing a "scan script". +The script specifies the contents and ordering of the scans to be emitted. +Each entry in the script defines one scan. A scan definition specifies +the components to be included in the scan, and for progressive JPEG it also +specifies the progression parameters Ss,Se,Ah,Al for the scan. Scan +definitions are separated by semicolons (';'). A semicolon after the last +scan definition is optional. + +Each scan definition contains one to four component indexes, optionally +followed by a colon (':') and the four progressive-JPEG parameters. The +component indexes denote which color component(s) are to be transmitted in +the scan. Components are numbered in the order in which they appear in the +JPEG SOF marker, with the first component being numbered 0. (Note that these +indexes are not the "component ID" codes assigned to the components, just +positional indexes.) + +The progression parameters for each scan are: + Ss Zigzag index of first coefficient included in scan + Se Zigzag index of last coefficient included in scan + Ah Zero for first scan of a coefficient, else Al of prior scan + Al Successive approximation low bit position for scan +If the progression parameters are omitted, the values 0,63,0,0 are used, +producing a sequential JPEG file. cjpeg automatically determines whether +the script represents a progressive or sequential file, by observing whether +Ss and Se values other than 0 and 63 appear. (The -progressive switch is +not needed to specify this; in fact, it is ignored when -scans appears.) +The scan script must meet the JPEG restrictions on progression sequences. +(cjpeg checks that the spec's requirements are obeyed.) + +Scan script files are free format, in that arbitrary whitespace can appear +between numbers and around punctuation. Also, comments can be included: a +comment starts with '#' and extends to the end of the line. For additional +legibility, commas or dashes can be placed between values. (Actually, any +single punctuation character other than ':' or ';' can be inserted.) For +example, the following two scan definitions are equivalent: + 0 1 2: 0 63 0 0; + 0,1,2 : 0-63, 0,0 ; + +Here is an example of a scan script that generates a partially interleaved +sequential JPEG file: + + 0; # Y only in first scan + 1 2; # Cb and Cr in second scan + +Here is an example of a progressive scan script using only spectral selection +(no successive approximation): + + # Interleaved DC scan for Y,Cb,Cr: + 0,1,2: 0-0, 0, 0 ; + # AC scans: + 0: 1-2, 0, 0 ; # First two Y AC coefficients + 0: 3-5, 0, 0 ; # Three more + 1: 1-63, 0, 0 ; # All AC coefficients for Cb + 2: 1-63, 0, 0 ; # All AC coefficients for Cr + 0: 6-9, 0, 0 ; # More Y coefficients + 0: 10-63, 0, 0 ; # Remaining Y coefficients + +Here is an example of a successive-approximation script. This is equivalent +to the default script used by "cjpeg -progressive" for YCbCr images: + + # Initial DC scan for Y,Cb,Cr (lowest bit not sent) + 0,1,2: 0-0, 0, 1 ; + # First AC scan: send first 5 Y AC coefficients, minus 2 lowest bits: + 0: 1-5, 0, 2 ; + # Send all Cr,Cb AC coefficients, minus lowest bit: + # (chroma data is usually too small to be worth subdividing further; + # but note we send Cr first since eye is least sensitive to Cb) + 2: 1-63, 0, 1 ; + 1: 1-63, 0, 1 ; + # Send remaining Y AC coefficients, minus 2 lowest bits: + 0: 6-63, 0, 2 ; + # Send next-to-lowest bit of all Y AC coefficients: + 0: 1-63, 2, 1 ; + # At this point we've sent all but the lowest bit of all coefficients. + # Send lowest bit of DC coefficients + 0,1,2: 0-0, 1, 0 ; + # Send lowest bit of AC coefficients + 2: 1-63, 1, 0 ; + 1: 1-63, 1, 0 ; + # Y AC lowest bit scan is last; it's usually the largest scan + 0: 1-63, 1, 0 ; + +It may be worth pointing out that this script is tuned for quality settings +of around 50 to 75. For lower quality settings, you'd probably want to use +a script with fewer stages of successive approximation (otherwise the +initial scans will be really bad). For higher quality settings, you might +want to use more stages of successive approximation (so that the initial +scans are not too large). diff --git a/Utilities/FLTK/lib/README.lib b/Utilities/FLTK/lib/README.lib new file mode 100644 index 0000000000..61779843f0 --- /dev/null +++ b/Utilities/FLTK/lib/README.lib @@ -0,0 +1,16 @@ +README.lib +---------- + +This README file is a placeholder for library files on your +system. + +Under Microsoft Windows a successful build of all projects and +configurations will contain debug and release libraries for you +to link to - all are built using the multi-threaded DLL +settings. The DLL files (fltkdll.dll and fltkdlld.dll) required +for a complete DLL-based binary distribution are located in the +"visualc" directory. + +Under UNIX a single set of library files will be built, with or +without debug information depending on the options you provided +to the configure script. diff --git a/Utilities/FLTK/png/ANNOUNCE b/Utilities/FLTK/png/ANNOUNCE new file mode 100644 index 0000000000..6370130a75 --- /dev/null +++ b/Utilities/FLTK/png/ANNOUNCE @@ -0,0 +1,28 @@ + +Libpng 1.2.7 - September 12, 2004 + +This is a public release of libpng, intended for use in production codes. + +Changes since the last public release (1.2.6): + + Revised pngtest so memory allocation testing is only done when PNG_DEBUG==1. + Removed unused pngasmrd.h file. + Removed references to uu.net for archived files. Added references to + PNG Spec (second edition) and the PNG ISO/IEC Standard. + Added "test-dd" target in 15 makefiles, to run pngtest in DESTDIR. + Fixed bug with "optimized window size" in the IDAT datastream, that + causes libpng to write PNG files with incorrect zlib header bytes. + Fixed bug with sCAL chunk and big-endian machines (David Munro). + Undid new code added in 1.2.6 to update the color_type in + png_set_filler(). + Added png_set_add_alpha() that updates color type. + Revised png_set_strip_filler() to not remove alpha if color_type has alpha. + Added makefile.hp64 + Changed projects/msvc/png32ms.def to scripts/png32ms.def in makefile.cygwin + +Send comments/corrections/commendations to +png-implement@ccrc.wustl.edu (subscription required; write to +majordomo@ccrc.wustl.edu with "subscribe png-implement" in the message) +or to glennrp@users.sourceforge.net + +Glenn R-P diff --git a/Utilities/FLTK/png/CHANGES b/Utilities/FLTK/png/CHANGES new file mode 100644 index 0000000000..b34597fc5e --- /dev/null +++ b/Utilities/FLTK/png/CHANGES @@ -0,0 +1,1373 @@ + +CHANGES - changes for libpng + +version 0.2 + added reader into png.h + fixed small problems in stub file + +version 0.3 + added pull reader + split up pngwrite.c to several files + added pnglib.txt + added example.c + cleaned up writer, adding a few new tranformations + fixed some bugs in writer + interfaced with zlib 0.5 + added K&R support + added check for 64 KB blocks for 16 bit machines + +version 0.4 + cleaned up code and commented code + simplified time handling into png_time + created png_color_16 and png_color_8 to handle color needs + cleaned up color type defines + fixed various bugs + made various names more consistant + interfaced with zlib 0.71 + cleaned up zTXt reader and writer (using zlib's Reset functions) + split transformations into pngrtran.c and pngwtran.c + +version 0.5 + interfaced with zlib 0.8 + fixed many reading and writing bugs + saved using 3 spaces instead of tabs + +version 0.6 + added png_large_malloc() and png_large_free() + added png_size_t + cleaned up some compiler warnings + added png_start_read_image() + +version 0.7 + cleaned up lots of bugs + finished dithering and other stuff + added test program + changed name from pnglib to libpng + +version 0.71 [June, 1995] + changed pngtest.png for zlib 0.93 + fixed error in libpng.txt and example.c + +version 0.8 + cleaned up some bugs + added png_set_filler() + split up pngstub.c into pngmem.c, pngio.c, and pngerror.c + added #define's to remove unwanted code + moved png_info_init() to png.c + added old_size into png_realloc() + added functions to manually set filtering and compression info + changed compression parameters based on image type + optimized filter selection code + added version info + changed external functions passing floats to doubles (k&r problems?) + put all the configurable stuff in pngconf.h + enabled png_set_shift to work with paletted images on read + added png_read_update_info() - updates info structure with + transformations + +version 0.81 [August, 1995] + incorporated Tim Wegner's medium model code (thanks, Tim) + +version 0.82 [September, 1995] + [unspecified changes] + +version 0.85 [December, 1995] + added more medium model code (almost everything's a far) + added i/o, error, and memory callback functions + fixed some bugs (16 bit, 4 bit interlaced, etc.) + added first run progressive reader (barely tested) + +version 0.86 [January, 1996] + fixed bugs + improved documentation + +version 0.87 [January, 1996] + fixed medium model bugs + fixed other bugs introduced in 0.85 and 0.86 + added some minor documentation + +version 0.88 [January, 1996] + fixed progressive bugs + replaced tabs with spaces + cleaned up documentation + added callbacks for read/write and warning/error functions + +version 0.89 [July, 1996] + added new initialization API to make libpng work better with shared libs + we now have png_create_read_struct(), png_create_write_struct(), + png_create_info_struct(), png_destroy_read_struct(), and + png_destroy_write_struct() instead of the separate calls to + malloc and png_read_init(), png_info_init(), and png_write_init() + changed warning/error callback functions to fix bug - this means you + should use the new initialization API if you were using the old + png_set_message_fn() calls, and that the old API no longer exists + so that people are aware that they need to change their code + changed filter selection API to allow selection of multiple filters + since it didn't work in previous versions of libpng anyways + optimized filter selection code + fixed png_set_background() to allow using an arbitrary RGB color for + paletted images + fixed gamma and background correction for paletted images, so + png_correct_palette is not needed unless you are correcting an + external palette (you will need to #define PNG_CORRECT_PALETTE_SUPPORTED + in pngconf.h) - if nobody uses this, it may disappear in the future. + fixed bug with Borland 64K memory allocation (Alexander Lehmann) + fixed bug in interlace handling (Smarasderagd, I think) + added more error checking for writing and image to reduce invalid files + separated read and write functions so that they won't both be linked + into a binary when only reading or writing functionality is used + new pngtest image also has interlacing and zTXt + updated documentation to reflect new API + +version 0.90 [January, 1997] + made CRC errors/warnings on critical and ancillary chunks configurable + libpng will use the zlib CRC routines by (compile-time) default + changed DOS small/medium model memory support - needs zlib 1.04 (Tim Wegner) + added external C++ wrapper statements to png.h (Gilles Dauphin) + allow PNG file to be read when some or all of file signature has already + been read from the beginning of the stream. ****This affects the size + of info_struct and invalidates all programs that use a shared libpng**** + fixed png_filler() declarations + fixed? background color conversions + fixed order of error function pointers to match documentation + current chunk name is now available in png_struct to reduce the number + of nearly identical error messages (will simplify multi-lingual + support when available) + try to get ready for unknown-chunk callback functions: + - previously read critical chunks are flagged, so the chunk handling + routines can determine if the chunk is in the right place + - all chunk handling routines have the same prototypes, so we will + be able to handle all chunks via a callback mechanism + try to fix Linux "setjmp" buffer size problems + removed png_large_malloc, png_large_free, and png_realloc functions. + +version 0.95 [March, 1997] + fixed bug in pngwutil.c allocating "up_row" twice and "avg_row" never + fixed bug in PNG file signature compares when start != 0 + changed parameter type of png_set_filler(...filler...) from png_byte + to png_uint_32 + added test for MACOS to ensure that both math.h and fp.h are not #included + added macros for libpng to be compiled as a Windows DLL (Andreas Kupries) + added "packswap" transformation, which changes the endianness of + packed-pixel bytes (Kevin Bracey) + added "strip_alpha" transformation, which removes the alpha channel of + input images without using it (not neccesarily a good idea) + added "swap_alpha" transformation, which puts the alpha channel in front + of the color bytes instead of after + removed all implicit variable tests which assume NULL == 0 (I think) + changed several variables to "png_size_t" to show 16/32-bit limitations + added new pCAL chunk read/write support + added experimental filter selection weighting (Greg Roelofs) + removed old png_set_rgbx() and png_set_xrgb() functions that have been + obsolete for about 2 years now (use png_set_filler() instead) + added macros to read 16- and 32-bit ints directly from buffer, to be + used only on those systems that support it (namely PowerPC and 680x0) + With some testing, this may become the default for MACOS/PPC systems. + only calculate CRC on data if we are going to use it + added macros for zTXt compression type PNG_zTXt_COMPRESSION_??? + added macros for simple libpng debugging output selectable at compile time + removed PNG_READ_END_MODE in progressive reader (Smarasderagd) + more description of info_struct in libpng.txt and png.h + more instructions in example.c + more chunk types tested in pngtest.c + renamed pngrcb.c to pngset.c, and all png_read_<chunk> functions to be + png_set_<chunk>. We now have corresponding png_get_<chunk> + functions in pngget.c to get infomation in info_ptr. This isolates + the application from the internal organization of png_info_struct + (good for shared library implementations). + +version 0.96 [May, 1997] + fixed serious bug with < 8bpp images introduced in 0.95 + fixed 256-color transparency bug (Greg Roelofs) + fixed up documentation (Greg Roelofs, Laszlo Nyul) + fixed "error" in pngconf.h for Linux setjmp() behaviour + fixed DOS medium model support (Tim Wegner) + fixed png_check_keyword() for case with error in static string text + added read of CRC after IEND chunk for embedded PNGs (Laszlo Nyul) + added typecasts to quiet compiler errors + added more debugging info + +version 0.97 [January, 1998] + removed PNG_USE_OWN_CRC capability + relocated png_set_crc_action from pngrutil.c to pngrtran.c + fixed typecasts of "new_key", etc. (Andreas Dilger) + added RFC 1152 [sic] date support + fixed bug in gamma handling of 4-bit grayscale + added 2-bit grayscale gamma handling (Glenn R-P) + added more typecasts. 65536L becomes (png_uint_32)65536L, etc. (Glenn R-P) + minor corrections in libpng.txt + added simple sRGB support (Glenn R-P) + easier conditional compiling, e.g. define PNG_READ/WRITE_NOT_FULLY_SUPPORTED; + all configurable options can be selected from command-line instead + of having to edit pngconf.h (Glenn R-P) + fixed memory leak in pngwrite.c (free info_ptr->text) (Glenn R-P) + added more conditions for png_do_background, to avoid changing + black pixels to background when a background is supplied and + no pixels are transparent + repaired PNG_NO_STDIO behaviour + tested NODIV support and made it default behaviour (Greg Roelofs) + added "-m" option and PNGTEST_DEBUG_MEMORY to pngtest (John Bowler) + regularized version numbering scheme and bumped shared-library major + version number to 2 to avoid problems with libpng 0.89 apps (Greg Roelofs) + +version 0.98 [January, 1998] + cleaned up some typos in libpng.txt and in code documentation + fixed memory leaks in pCAL chunk processing (Glenn R-P and John Bowler) + cosmetic change "display_gamma" to "screen_gamma" in pngrtran.c + changed recommendation about file_gamma for PC images to .51 from .45, + in example.c and libpng.txt, added comments to distinguish between + screen_gamma, viewing_gamma, and display_gamma. + changed all references to RFC1152 to read RFC1123 and changed the + PNG_TIME_RFC1152_SUPPORTED macro to PNG_TIME_RFC1123_SUPPORTED + added png_invert_alpha capability (Glenn R-P -- suggestion by Jon Vincent) + changed srgb_intent from png_byte to int to avoid compiler bugs + +version 0.99 [January 30, 1998] + free info_ptr->text instead of end_info_ptr->text in pngread.c (John Bowler) + fixed a longstanding "packswap" bug in pngtrans.c + fixed some inconsistencies in pngconf.h that prevented compiling with + PNG_READ_GAMMA_SUPPORTED and PNG_READ_hIST_SUPPORTED undefined + fixed some typos and made other minor rearrangement of libpng.txt (Andreas) + changed recommendation about file_gamma for PC images to .50 from .51 in + example.c and libpng.txt, and changed file_gamma for sRGB images to .45 + added a number of functions to access information from the png structure + png_get_image_height(), etc. (Glenn R-P, suggestion by Brad Pettit) + added TARGET_MACOS similar to zlib-1.0.8 + define PNG_ALWAYS_EXTERN when __MWERKS__ && WIN32 are defined + added type casting to all png_malloc() function calls +version 0.99a [January 31, 1998] + Added type casts and parentheses to all returns that return a value.(Tim W.) +version 0.99b [February 4, 1998] + Added type cast png_uint_32 on malloc function calls where needed. + Changed type of num_hist from png_uint_32 to int (same as num_palette). + Added checks for rowbytes overflow, in case png_size_t is less than 32 bits. + Renamed makefile.elf to makefile.lnx. +version 0.99c [February 7, 1998] + More type casting. Removed erroneous overflow test in pngmem.c. + Added png_buffered_memcpy() and png_buffered_memset(), apply them to rowbytes. + Added UNIX manual pages libpng.3 (incorporating libpng.txt) and png.5. +version 0.99d [February 11, 1998] + Renamed "far_to_near()" "png_far_to_near()" + Revised libpng.3 + Version 99c "buffered" operations didn't work as intended. Replaced them + with png_memcpy_check() and png_memset_check(). + Added many "if (png_ptr == NULL) return" to quell compiler warnings about + unused png_ptr, mostly in pngget.c and pngset.c. + Check for overlength tRNS chunk present when indexed-color PLTE is read. + Cleaned up spelling errors in libpng.3/libpng.txt + Corrected a problem with png_get_tRNS() which returned undefined trans array +version 0.99e [February 28, 1998] + Corrected png_get_tRNS() again. + Add parentheses for easier reading of pngget.c, fixed "||" should be "&&". + Touched up example.c to make more of it compileable, although the entire + file still can't be compiled (Willem van Schaik) + Fixed a bug in png_do_shift() (Bryan Tsai) + Added a space in png.h prototype for png_write_chunk_start() + Replaced pngtest.png with one created with zlib 1.1.1 + Changed pngtest to report PASS even when file size is different (Jean-loup G.) + Corrected some logic errors in png_do_invert_alpha() (Chris Patterson) +version 0.99f [March 5, 1998] + Corrected a bug in pngpread() introduced in version 99c (Kevin Bracey) + Moved makefiles into a "scripts" directory, and added INSTALL instruction file + Added makefile.os2 and pngos2.def (A. Zabolotny) and makefile.s2x (W. Sebok) + Added pointers to "note on libpng versions" in makefile.lnx and README + Added row callback feature when reading and writing nonprogressive rows + and added a test of this feature in pngtest.c + Added user transform callbacks, with test of the feature in pngtest.c +version 0.99g [March 6, 1998, morning] + Minor changes to pngtest.c to suppress compiler warnings. + Removed "beta" language from documentation. +version 0.99h [March 6, 1998, evening] + Minor changes to previous minor changes to pngtest.c + Changed PNG_READ_NOT_FULLY_SUPPORTED to PNG_READ_TRANSFORMS_NOT_SUPPORTED + and added PNG_PROGRESSIVE_READ_NOT_SUPPORTED macro + Added user transform capability + +version 1.00 [March 7, 1998] + Changed several typedefs in pngrutil.c + Added makefile.wat (Pawel Mrochen), updated makefile.tc3 (Willem van Schaik) + replaced "while(1)" with "for(;;)" + added PNGARG() to prototypes in pngtest.c and removed some prototypes + updated some of the makefiles (Tom Lane) + changed some typedefs (s_start, etc.) in pngrutil.c + fixed dimensions of "short_months" array in pngwrite.c + Replaced ansi2knr.c with the one from jpeg-v6 + +version 1.0.0 [March 8, 1998] + Changed name from 1.00 to 1.0.0 (Adam Costello) + Added smakefile.ppc (with SCOPTIONS.ppc) for Amiga PPC (Andreas Kleinert) +version 1.0.0a [March 9, 1998] + Fixed three bugs in pngrtran.c to make gamma+background handling consistent + (Greg Roelofs) + Changed format of the PNG_LIBPNG_VER integer to xyyzz instead of xyz + for major, minor, and bugfix releases. This is 10001. (Adam Costello, + Tom Lane) + Make months range from 1-12 in png_convert_to_rfc1123 +version 1.0.0b [March 13, 1998] + Quieted compiler complaints about two empty "for" loops in pngrutil.c + Minor changes to makefile.s2x + Removed #ifdef/#endif around a png_free() in pngread.c + +version 1.0.1 [March 14, 1998] + Changed makefile.s2x to reduce security risk of using a relative pathname + Fixed some typos in the documentation (Greg). + Fixed a problem with value of "channels" returned by png_read_update_info() +version 1.0.1a [April 21, 1998] + Optimized Paeth calculations by replacing abs() function calls with intrinsics + plus other loop optimizations. Improves avg decoding speed by about 20%. + Commented out i386istic "align" compiler flags in makefile.lnx. + Reduced the default warning level in some makefiles, to make them consistent. + Removed references to IJG and JPEG in the ansi2knr.c copyright statement. + Fixed a bug in png_do_strip_filler with XXRRGGBB => RRGGBB transformation. + Added grayscale and 16-bit capability to png_do_read_filler(). + Fixed a bug in pngset.c, introduced in version 0.99c, that sets rowbytes + too large when writing an image with bit_depth < 8 (Bob Dellaca). + Corrected some bugs in the experimental weighted filtering heuristics. + Moved a misplaced pngrutil code block that truncates tRNS if it has more + than num_palette entries -- test was done before num_palette was defined. + Fixed a png_convert_to_rfc1123() bug that converts day 31 to 0 (Steve Eddins). + Changed compiler flags in makefile.wat for better optimization (Pawel Mrochen). +version 1.0.1b [May 2, 1998] + Relocated png_do_gray_to_rgb() within png_do_read_transformations() (Greg). + Relocated the png_composite macros from pngrtran.c to png.h (Greg). + Added makefile.sco (contributed by Mike Hopkirk). + Fixed two bugs (missing definitions of "istop") introduced in libpng-1.0.1a. + Fixed a bug in pngrtran.c that would set channels=5 under some circumstances. + More work on the Paeth-filtering, achieving imperceptible speedup (A Kleinert). + More work on loop optimization which may help when compiled with C++ compilers. + Added warnings when people try to use transforms they've defined out. + Collapsed 4 "i" and "c" loops into single "i" loops in pngrtran and pngwtran. + Revised paragraph about png_set_expand() in libpng.txt and libpng.3 (Greg) +version 1.0.1c [May 11, 1998] + Fixed a bug in pngrtran.c (introduced in libpng-1.0.1a) where the masks for + filler bytes should have been 0xff instead of 0xf. + Added max_pixel_depth=32 in pngrutil.c when using FILLER with palette images. + Moved PNG_WRITE_WEIGHTED_FILTER_SUPPORTED and PNG_WRITE_FLUSH_SUPPORTED + out of the PNG_WRITE_TRANSFORMS_NOT_SUPPORTED block of pngconf.h + Added "PNG_NO_WRITE_TRANSFORMS" etc., as alternatives for *_NOT_SUPPORTED, + for consistency, in pngconf.h + Added individual "ifndef PNG_NO_[CAPABILITY]" in pngconf.h to make it easier + to remove unwanted capabilities via the compile line + Made some corrections to grammar (which, it's) in documentation (Greg). + Corrected example.c, use of row_pointers in png_write_image(). +version 1.0.1d [May 24, 1998] + Corrected several statements that used side effects illegally in pngrutil.c + and pngtrans.c, that were introduced in version 1.0.1b + Revised png_read_rows() to avoid repeated if-testing for NULL (A Kleinert) + More corrections to example.c, use of row_pointers in png_write_image() + and png_read_rows(). + Added pngdll.mak and pngdef.pas to scripts directory, contributed by + Bob Dellaca, to make a png32bd.dll with Borland C++ 4.5 + Fixed error in example.c with png_set_text: num_text is 3, not 2 (Guido V.) + Changed several loops from count-down to count-up, for consistency. +version 1.0.1e [June 6, 1998] + Revised libpng.txt and libpng.3 description of png_set_read|write_fn(), and + added warnings when people try to set png_read_fn and png_write_fn in + the same structure. + Added a test such that png_do_gamma will be done when num_trans==0 + for truecolor images that have defined a background. This corrects an + error that was introduced in libpng-0.90 that can cause gamma processing + to be skipped. + Added tests in png.h to include "trans" and "trans_values" in structures + when PNG_READ_BACKGROUND_SUPPORTED or PNG_READ_EXPAND_SUPPORTED is defined. + Add png_free(png_ptr->time_buffer) in png_destroy_read_struct() + Moved png_convert_to_rfc_1123() from pngwrite.c to png.c + Added capability for user-provided malloc_fn() and free_fn() functions, + and revised pngtest.c to demonstrate their use, replacing the + PNGTEST_DEBUG_MEM feature. + Added makefile.w32, for Microsoft C++ 4.0 and later (Tim Wegner). + +version 1.0.2 [June 14, 1998] + Fixed two bugs in makefile.bor . +version 1.0.2a [December 30, 1998] + Replaced and extended code that was removed from png_set_filler() in 1.0.1a. + Fixed a bug in png_do_filler() that made it fail to write filler bytes in + the left-most pixel of each row (Kevin Bracey). + Changed "static pngcharp tIME_string" to "static char tIME_string[30]" + in pngtest.c (Duncan Simpson). + Fixed a bug in pngtest.c that caused pngtest to try to write a tIME chunk + even when no tIME chunk was present in the source file. + Fixed a problem in pngrutil.c: gray_to_rgb didn't always work with 16-bit. + Fixed a problem in png_read_push_finish_row(), which would not skip some + passes that it should skip, for images that are less than 3 pixels high. + Interchanged the order of calls to png_do_swap() and png_do_shift() + in pngwtran.c (John Cromer). + Added #ifdef PNG_DEBUG/#endif surrounding use of PNG_DEBUG in png.h . + Changed "bad adaptive filter type" from error to warning in pngrutil.c . + Fixed a documentation error about default filtering with 8-bit indexed-color. + Separated the PNG_NO_STDIO macro into PNG_NO_STDIO and PNG_NO_CONSOLE_IO + (L. Peter Deutsch). + Added png_set_rgb_to_gray() and png_get_rgb_to_gray_status() functions. + Added png_get_copyright() and png_get_header_version() functions. + Revised comments on png_set_progressive_read_fn() in libpng.txt and example.c + Added information about debugging in libpng.txt and libpng.3 . + Changed "ln -sf" to "ln -s -f" in makefile.s2x, makefile.lnx, and makefile.sco. + Removed lines after Dynamic Dependencies" in makefile.aco . + Revised makefile.dec to make a shared library (Jeremie Petit). + Removed trailing blanks from all files. +version 1.0.2a [January 6, 1999] + Removed misplaced #endif and #ifdef PNG_NO_EXTERN near the end of png.h + Added "if" tests to silence complaints about unused png_ptr in png.h and png.c + Changed "check_if_png" function in example.c to return true (nonzero) if PNG. + Changed libpng.txt to demonstrate png_sig_cmp() instead of png_check_sig() + which is obsolete. + +version 1.0.3 [January 14, 1999] + Added makefile.hux, for Hewlett Packard HPUX 10.20 and 11.00 (Jim Rice) + Added a statement of Y2K compliance in png.h, libpng.3, and Y2KINFO. +version 1.0.3a [August 12, 1999] + Added check for PNG_READ_INTERLACE_SUPPORTED in pngread.c; issue a warning + if an attempt is made to read an interlaced image when it's not supported. + Added check if png_ptr->trans is defined before freeing it in pngread.c + Modified the Y2K statement to include versions back to version 0.71 + Fixed a bug in the check for valid IHDR bit_depth/color_types in pngrutil.c + Modified makefile.wat (added -zp8 flag, ".symbolic", changed some comments) + Replaced leading blanks with tab characters in makefile.hux + Changed "dworkin.wustl.edu" to "ccrc.wustl.edu" in various documents. + Changed (float)red and (float)green to (double)red, (double)green + in png_set_rgb_to_gray() to avoid "promotion" problems in AIX. + Fixed a bug in pngconf.h that omitted <stdio.h> when PNG_DEBUG==0 (K Bracey). + Reformatted libpng.3 and libpngpf.3 with proper fonts (script by J. vanZandt). + Updated documentation to refer to the PNG-1.2 specification. + Removed ansi2knr.c and left pointers to the latest source for ansi2knr.c + in makefile.knr, INSTALL, and README (L. Peter Deutsch) + Fixed bugs in calculation of the length of rowbytes when adding alpha + channels to 16-bit images, in pngrtran.c (Chris Nokleberg) + Added function png_set_user_transform_info() to store user_transform_ptr, + user_depth, and user_channels into the png_struct, and a function + png_get_user_transform_ptr() to retrieve the pointer (Chris Nokleberg) + Added function png_set_empty_plte_permitted() to make libpng useable + in MNG applications. + Corrected the typedef for png_free_ptr in png.h (Jesse Jones). + Correct gamma with srgb is 45455 instead of 45000 in pngrutil.c, to be + consistent with PNG-1.2, and allow variance of 500 before complaining. + Added assembler code contributed by Intel in file pngvcrd.c and modified + makefile.w32 to use it (Nirav Chhatrapati, INTEL Corporation, Gilles Vollant) + Changed "ln -s -f" to "ln -f -s" in the makefiles to make Solaris happy. + Added some aliases for png_set_expand() in pngrtran.c, namely + png_set_expand_PLTE(), png_set_expand_depth(), and png_set_expand_tRNS() + (Greg Roelofs, in "PNG: The Definitive Guide"). + Added makefile.beo for BEOS on X86, contributed by Sander Stok. +version 1.0.3b [August 26, 1999] + Replaced 2147483647L several places with PNG_MAX_UINT macro, defined in png.h + Changed leading blanks to tabs in all makefiles. + Define PNG_USE_PNGVCRD in makefile.w32, to get MMX assembler code. + Made alternate versions of png_set_expand() in pngrtran.c, namely + png_set_gray_1_2_4_to_8, png_set_palette_to_rgb, and png_set_tRNS_to_alpha + (Greg Roelofs, in "PNG: The Definitive Guide"). Deleted the 1.0.3a aliases. + Relocated start of 'extern "C"' block in png.h so it doesn't include pngconf.h + Revised calculation of num_blocks in pngmem.c to avoid a potentially + negative shift distance, whose results are undefined in the C language. + Added a check in pngset.c to prevent writing multiple tIME chunks. + Added a check in pngwrite.c to detect invalid small window_bits sizes. +version 1.0.3d [September 4, 1999] + Fixed type casting of igamma in pngrutil.c + Added new png_expand functions to scripts/pngdef.pas and pngos2.def + Added a demo read_user_transform_fn that examines the row filters in pngtest.c + +version 1.0.4 [September 24, 1999] + Define PNG_ALWAYS_EXTERN in pngconf.h if __STDC__ is defined + Delete #define PNG_INTERNAL and include "png.h" from pngasmrd.h + Made several minor corrections to pngtest.c + Renamed the makefiles with longer but more user friendly extensions. + Copied the PNG copyright and license to a separate LICENSE file. + Revised documentation, png.h, and example.c to remove reference to + "viewing_gamma" which no longer appears in the PNG specification. + Revised pngvcrd.c to use MMX code for interlacing only on the final pass. + Updated pngvcrd.c to use the faster C filter algorithms from libpng-1.0.1a + Split makefile.win32vc into two versions, makefile.vcawin32 (uses MMX + assembler code) and makefile.vcwin32 (doesn't). + Added a CPU timing report to pngtest.c (enabled by defining PNGTEST_TIMING) + Added a copy of pngnow.png to the distribution. +version 1.0.4a [September 25, 1999] + Increase max_pixel_depth in pngrutil.c if a user transform needs it. + Changed several division operations to right-shifts in pngvcrd.c +version 1.0.4b [September 30, 1999] + Added parentheses in line 3732 of pngvcrd.c + Added a comment in makefile.linux warning about buggy -O3 in pgcc 2.95.1 +version 1.0.4c [October 1, 1999] + Added a "png_check_version" function in png.c and pngtest.c that will generate + a helpful compiler error if an old png.h is found in the search path. + Changed type of png_user_transform_depth|channels from int to png_byte. +version 1.0.4d [October 6, 1999] + Changed 0.45 to 0.45455 in png_set_sRGB() + Removed unused PLTE entries from pngnow.png + Re-enabled some parts of pngvcrd.c (png_combine_row) that work properly. +version 1.0.4e [October 10, 1999] + Fixed sign error in pngvcrd.c (Greg Roelofs) + Replaced some instances of memcpy with simple assignments in pngvcrd (GR-P) +version 1.0.4f [October 15, 1999] + Surrounded example.c code with #if 0 .. #endif to prevent people from + inadvertently trying to compile it. + Changed png_get_header_version() from a function to a macro in png.h + Added type casting mostly in pngrtran.c and pngwtran.c + Removed some pointless "ptr = NULL" in pngmem.c + Added a "contrib" directory containing the source code from Greg's book. + +version 1.0.5 [October 15, 1999] + Minor editing of the INSTALL and README files. +version 1.0.5a [October 23, 1999] + Added contrib/pngsuite and contrib/pngminus (Willem van Schaik) + Fixed a typo in the png_set_sRGB() function call in example.c (Jan Nijtmans) + Further optimization and bugfix of pngvcrd.c + Revised pngset.c so that it does not allocate or free memory in the user's + text_ptr structure. Instead, it makes its own copy. + Created separate write_end_info_struct in pngtest.c for a more severe test. + Added code in pngwrite.c to free info_ptr->text[i].key to stop a memory leak. +version 1.0.5b [November 23, 1999] + Moved PNG_FLAG_HAVE_CHUNK_HEADER, PNG_FLAG_BACKGROUND_IS_GRAY and + PNG_FLAG_WROTE_tIME from flags to mode. + Added png_write_info_before_PLTE() function. + Fixed some typecasting in contrib/gregbook/*.c + Updated scripts/makevms.com and added makevms.com to contrib/gregbook + and contrib/pngminus (Martin Zinser) +version 1.0.5c [November 26, 1999] + Moved png_get_header_version from png.h to png.c, to accomodate ansi2knr. + Removed all global arrays (according to PNG_NO_GLOBAL_ARRAYS macro), to + accomodate making DLL's: Moved usr_png_ver from global variable to function + png_get_header_ver() in png.c. Moved png_sig to png_sig_bytes in png.c and + eliminated use of png_sig in pngwutil.c. Moved the various png_CHNK arrays + into pngtypes.h. Eliminated use of global png_pass arrays. Declared the + png_CHNK and png_pass arrays to be "const". Made the global arrays + available to applications (although none are used in libpng itself) when + PNG_NO_GLOBAL_ARRAYS is not defined or when PNG_GLOBAL_ARRAYS is defined. + Removed some extraneous "-I" from contrib/pngminus/makefile.std + Changed the PNG_sRGB_INTENT macros in png.h to be consistent with PNG-1.2. + Change PNG_SRGB_INTENT to PNG_sRGB_INTENT in libpng.txt and libpng.3 +version 1.0.5d [November 29, 1999] + Add type cast (png_const_charp) two places in png.c + Eliminated pngtypes.h; use macros instead to declare PNG_CHNK arrays. + Renamed "PNG_GLOBAL_ARRAYS" to "PNG_USE_GLOBAL_ARRAYS" and made available + to applications a macro "PNG_USE_LOCAL_ARRAYS". + #ifdef out all the new declarations when PNG_USE_GLOBAL_ARRAYS is defined. + Added PNG_EXPORT_VAR macro to accommodate making DLL's. +version 1.0.5e [November 30, 1999] + Added iCCP, iTXt, and sPLT support; added "lang" member to the png_text + structure; refactored the inflate/deflate support to make adding new chunks + with trailing compressed parts easier in the future, and added new functions + png_free_iCCP, png_free_pCAL, png_free_sPLT, png_free_text, png_get_iCCP, + png_get_spalettes, png_set_iCCP, png_set_spalettes (Eric S. Raymond). + NOTE: Applications that write text chunks MUST define png_text->lang + before calling png_set_text(). It must be set to NULL if you want to + write tEXt or zTXt chunks. If you want your application to be able to + run with older versions of libpng, use + + #ifdef PNG_iTXt_SUPPORTED + png_text[i].lang = NULL; + #endif + + Changed png_get_oFFs() and png_set_oFFs() to use signed rather than unsigned + offsets (Eric S. Raymond). + Combined PNG_READ_cHNK_SUPPORTED and PNG_WRITE_cHNK_SUPPORTED macros into + PNG_cHNK_SUPPORTED and combined the three types of PNG_text_SUPPORTED + macros, leaving the separate macros also available. + Removed comments on #endifs at the end of many short, non-nested #if-blocks. +version 1.0.5f [December 6, 1999] + Changed makefile.solaris to issue a warning about potential problems when + the ucb "ld" is in the path ahead of the ccs "ld". + Removed "- [date]" from the "synopsis" line in libpng.3 and libpngpf.3. + Added sCAL chunk support (Eric S. Raymond). +version 1.0.5g [December 7, 1999] + Fixed "png_free_spallettes" typo in png.h + Added code to handle new chunks in pngpread.c + Moved PNG_CHNK string macro definitions outside of PNG_NO_EXTERN block + Added "translated_key" to png_text structure and png_write_iTXt(). + Added code in pngwrite.c to work around a newly discovered zlib bug. +version 1.0.5h [December 10, 1999] + NOTE: regarding the note for version 1.0.5e, the following must also + be included in your code: + png_text[i].translated_key = NULL; + Unknown chunk handling is now supported. + Option to eliminate all floating point support was added. Some new + fixed-point functions such as png_set_gAMA_fixed() were added. + Expanded tabs and removed trailing blanks in source files. +version 1.0.5i [December 13, 1999] + Added some type casts to silence compiler warnings. + Renamed "png_free_spalette" to "png_free_spalettes" for consistency. + Removed leading blanks from a #define in pngvcrd.c + Added some parameters to the new png_set_keep_unknown_chunks() function. + Added a test for up->location != 0 in the first instance of writing + unknown chunks in pngwrite.c + Changed "num" to "i" in png_free_spalettes() and png_free_unknowns() to + prevent recursion. + Added png_free_hIST() function. + Various patches to fix bugs in the sCAL and integer cHRM processing, + and to add some convenience macros for use with sCAL. +version 1.0.5j [December 21, 1999] + Changed "unit" parameter of png_write_sCAL from png_byte to int, to work + around buggy compilers. + Added new type "png_fixed_point" for integers that hold float*100000 values + Restored backward compatibility of tEXt/zTXt chunk processing: + Restored the first four members of png_text to the same order as v.1.0.5d. + Added members "lang_key" and "itxt_length" to png_text struct. Set + text_length=0 when "text" contains iTXt data. Use the "compression" + member to distinguish among tEXt/zTXt/iTXt types. Added + PNG_ITXT_COMPRESSION_NONE (1) and PNG_ITXT_COMPRESSION_zTXt(2) macros. + The "Note" above, about backward incompatibility of libpng-1.0.5e, no + longer applies. + Fixed png_read|write_iTXt() to read|write parameters in the right order, + and to write the iTXt chunk after IDAT if it appears in the end_ptr. + Added pnggccrd.c, version of pngvcrd.c Intel assembler for gcc (Greg Roelofs) + Reversed the order of trying to write floating-point and fixed-point gAMA. +version 1.0.5k [December 27, 1999] + Added many parentheses, e.g., "if (a && b & c)" becomes "if (a && (b & c))" + Added png_handle_as_unknown() function (Glenn) + Added png_free_chunk_list() function and chunk_list and num_chunk_list members + of png_ptr. + Eliminated erroneous warnings about multiple sPLT chunks and sPLT-after-PLTE. + Fixed a libpng-1.0.5h bug in pngrutil.c that was issuing erroneous warnings + about ignoring incorrect gAMA with sRGB (gAMA was in fact not ignored) + Added png_free_tRNS(); png_set_tRNS() now malloc's its own trans array (ESR). + Define png_get_int_32 when oFFs chunk is supported as well as when pCAL is. + Changed type of proflen from png_int_32 to png_uint_32 in png_get_iCCP(). +version 1.0.5l [January 1, 2000] + Added functions png_set_read_user_chunk_fn() and png_get_user_chunk_ptr() + for setting a callback function to handle unknown chunks and for + retrieving the associated user pointer (Glenn). +version 1.0.5m [January 7, 2000] + Added high-level functions png_read_png(), png_write_png(), png_free_pixels(). +version 1.0.5n [January 9, 2000] + Added png_free_PLTE() function, and modified png_set_PLTE() to malloc its + own memory for info_ptr->palette. This makes it safe for the calling + application to free its copy of the palette any time after it calls + png_set_PLTE(). +version 1.0.5o [January 20, 2000] + Cosmetic changes only (removed some trailing blanks and TABs) +version 1.0.5p [January 31, 2000] + Renamed pngdll.mak to makefile.bd32 + Cosmetic changes in pngtest.c +version 1.0.5q [February 5, 2000] + Relocated the makefile.solaris warning about PATH problems. + Fixed pngvcrd.c bug by pushing/popping registers in mmxsupport (Bruce Oberg) + Revised makefile.gcmmx + Added PNG_SETJMP_SUPPORTED, PNG_SETJMP_NOT_SUPPORTED, and PNG_ABORT() macros +version 1.0.5r [February 7, 2000] + Removed superfluous prototype for png_get_itxt from png.h + Fixed a bug in pngrtran.c that improperly expanded the background color. + Return *num_text=0 from png_get_text() when appropriate, and fix documentation + of png_get_text() in libpng.txt/libpng.3. +version 1.0.5s [February 18, 2000] + Added "png_jmp_env()" macro to pngconf.h, to help people migrate to the + new error handler that's planned for the next libpng release, and changed + example.c, pngtest.c, and contrib programs to use this macro. + Revised some of the DLL-export macros in pngconf.h (Greg Roelofs) + Fixed a bug in png_read_png() that caused it to fail to expand some images + that it should have expanded. + Fixed some mistakes in the unused and undocumented INCH_CONVERSIONS functions + in pngget.c + Changed the allocation of palette, history, and trans arrays back to + the version 1.0.5 method (linking instead of copying) which restores + backward compatibility with version 1.0.5. Added some remarks about + that in example.c. Added "free_me" member to info_ptr and png_ptr + and added png_free_data() function. + Updated makefile.linux and makefile.gccmmx to make directories conditionally. + Made cosmetic changes to pngasmrd.h + Added png_set_rows() and png_get_rows(), for use with png_read|write_png(). + Modified png_read_png() to allocate info_ptr->row_pointers only if it + hasn't already been allocated. +version 1.0.5t [March 4, 2000] + Changed png_jmp_env() migration aiding macro to png_jmpbuf(). + Fixed "interlace" typo (should be "interlaced") in contrib/gregbook/read2-x.c + Fixed bug with use of PNG_BEFORE_IHDR bit in png_ptr->mode, introduced when + PNG_FLAG_HAVE_CHUNK_HEADER was moved into png_ptr->mode in version 1.0.5b + Files in contrib/gregbook were revised to use png_jmpbuf() and to select + a 24-bit visual if one is available, and to allow abbreviated options. + Files in contrib/pngminus were revised to use the png_jmpbuf() macro. + Removed spaces in makefile.linux and makefile.gcmmx, introduced in 1.0.5s +version 1.0.5u [March 5, 2000] + Simplified the code that detects old png.h in png.c and pngtest.c + Renamed png_spalette (_p, _pp) to png_sPLT_t (_tp, _tpp) + Increased precision of rgb_to_gray calculations from 8 to 15 bits and + added png_set_rgb_to_gray_fixed() function. + Added makefile.bc32 (32-bit Borland C++, C mode) +version 1.0.5v [March 11, 2000] + Added some parentheses to the png_jmpbuf macro definition. + Updated references to the zlib home page, which has moved to freesoftware.com. + Corrected bugs in documentation regarding png_read_row() and png_write_row(). + Updated documentation of png_rgb_to_gray calculations in libpng.3/libpng.txt. + Renamed makefile.borland,turboc3 back to makefile.bor,tc3 as in version 1.0.3, + revised borland makefiles; added makefile.ibmvac3 and makefile.gcc (Cosmin) + +version 1.0.6 [March 20, 2000] + Minor revisions of makefile.bor, libpng.txt, and gregbook/rpng2-win.c + Added makefile.sggcc (SGI IRIX with gcc) +version 1.0.6d [April 7, 2000] + Changed sprintf() to strcpy() in png_write_sCAL_s() to work without STDIO + Added data_length parameter to png_decompress_chunk() function + Revised documentation to remove reference to abandoned png_free_chnk functions + Fixed an error in png_rgb_to_gray_fixed() + Revised example.c, usage of png_destroy_write_struct(). + Renamed makefile.ibmvac3 to makefile.ibmc, added libpng.icc IBM project file + Added a check for info_ptr->free_me&PNG_FREE_TEXT when freeing text in png.c + Simplify png_sig_bytes() function to remove use of non-ISO-C strdup(). +version 1.0.6e [April 9, 2000] + Added png_data_freer() function. + In the code that checks for over-length tRNS chunks, added check of + info_ptr->num_trans as well as png_ptr->num_trans (Matthias Benckmann) + Minor revisions of libpng.txt/libpng.3. + Check for existing data and free it if the free_me flag is set, in png_set_*() + and png_handle_*(). + Only define PNG_WEIGHTED_FILTERS_SUPPORTED when PNG_FLOATING_POINT_SUPPORTED + is defined. + Changed several instances of PNG_NO_CONSOLE_ID to PNG_NO_STDIO in pngrutil.c + and mentioned the purposes of the two macros in libpng.txt/libpng.3. +version 1.0.6f [April 14, 2000] + Revised png_set_iCCP() and png_set_rows() to avoid prematurely freeing data. + Add checks in png_set_text() for NULL members of the input text structure. + Revised libpng.txt/libpng.3. + Removed superfluous prototype for png_set_itxt from png.h + Removed "else" from pngread.c, after png_error(), and changed "0" to "length". + Changed several png_errors about malformed ancillary chunks to png_warnings. +version 1.0.6g [April 24, 2000] + Added png_pass-* arrays to pnggccrd.c when PNG_USE_LOCAL_ARRAYS is defined. + Relocated paragraph about png_set_background() in libpng.3/libpng.txt + and other revisions (Matthias Benckmann) + Relocated info_ptr->free_me, png_ptr->free_me, and other info_ptr and + png_ptr members to restore binary compatibility with libpng-1.0.5 + (breaks compatibility with libpng-1.0.6). +version 1.0.6h [April 24, 2000] + Changed shared library so-number pattern from 2.x.y.z to xy.z (this builds + libpng.so.10 & libpng.so.10.6h instead of libpng.so.2 & libpng.so.2.1.0.6h) + This is a temporary change for test purposes. +version 1.0.6i [May 2, 2000] + Rearranged some members at the end of png_info and png_struct, to put + unknown_chunks_num and free_me within the original size of the png_structs + and free_me, png_read_user_fn, and png_free_fn within the original png_info, + because some old applications allocate the structs directly instead of + using png_create_*(). + Added documentation of user memory functions in libpng.txt/libpng.3 + Modified png_read_png so that it will use user_allocated row_pointers + if present, unless free_me directs that it be freed, and added description + of the use of png_set_rows() and png_get_rows() in libpng.txt/libpng.3. + Added PNG_LEGACY_SUPPORTED macro, and #ifdef out all new (since version + 1.00) members of png_struct and png_info, to regain binary compatibility + when you define this macro. Capabilities lost in this event + are user transforms (new in version 1.0.0),the user transform pointer + (new in version 1.0.2), rgb_to_gray (new in 1.0.5), iCCP, sCAL, sPLT, + the high-level interface, and unknown chunks support (all new in 1.0.6). + This was necessary because of old applications that allocate the structs + directly as authors were instructed to do in libpng-0.88 and earlier, + instead of using png_create_*(). + Added modes PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT which + can be used to detect codes that directly allocate the structs, and + code to check these modes in png_read_init() and png_write_init() and + generate a libpng error if the modes aren't set and PNG_LEGACY_SUPPORTED + was not defined. + Added makefile.intel and updated makefile.watcom (Pawel Mrochen) +version 1.0.6j [May 3, 2000] + Overloaded png_read_init() and png_write_init() with macros that convert + calls to png_read_init_2() or png_write_init_2() that check the version + and structure sizes. +version 1.0.7beta11 [May 7, 2000] + Removed the new PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT modes + which are no longer used. + Eliminated the three new members of png_text when PNG_LEGACY_SUPPORTED is + defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXT_SUPPORTED + is defined. + Made PNG_NO_READ|WRITE_iTXt the default setting, to avoid memory + overrun when old applications fill the info_ptr->text structure directly. + Added PNGAPI macro, and added it to the definitions of all exported functions. + Relocated version macro definitions ahead of the includes of zlib.h and + pngconf.h in png.h. +version 1.0.7beta12 [May 12, 2000] + Revised pngset.c to avoid a problem with expanding the png_debug macro. + Deleted some extraneous defines from pngconf.h + Made PNG_NO_CONSOLE_IO the default condition when PNG_BUILD_DLL is defined. + Use MSC _RPTn debugging instead of fprintf if _MSC_VER is defined. + Added png_access_version_number() function. + Check for mask&PNG_FREE_CHNK (for TEXT, SCAL, PCAL) in png_free_data(). + Expanded libpng.3/libpng.txt information about png_data_freer(). +version 1.0.7beta14 [May 17, 2000] (beta13 was not published) + Changed pnggccrd.c and pngvcrd.c to handle bad adaptive filter types as + warnings instead of errors, as pngrutil.c does. + Set the PNG_INFO_IDAT valid flag in png_set_rows() so png_write_png() + will actually write IDATs. + Made the default PNG_USE_LOCAL_ARRAYS depend on PNG_DLL instead of WIN32. + Make png_free_data() ignore its final parameter except when freeing data + that can have multiple instances (text, sPLT, unknowns). + Fixed a new bug in png_set_rows(). + Removed info_ptr->valid tests from png_free_data(), as in version 1.0.5. + Added png_set_invalid() function. + Fixed incorrect illustrations of png_destroy_write_struct() in example.c. +version 1.0.7beta15 [May 30, 2000] + Revised the deliberately erroneous Linux setjmp code in pngconf.h to produce + fewer error messages. + Rearranged checks for Z_OK to check the most likely path first in pngpread.c + and pngwutil.c. + Added checks in pngtest.c for png_create_*() returning NULL, and mentioned + in libpng.txt/libpng.3 the need for applications to check this. + Changed names of png_default_*() functions in pngtest to pngtest_*(). + Changed return type of png_get_x|y_offset_*() from png_uint_32 to png_int_32. + Fixed some bugs in the unused PNG_INCH_CONVERSIONS functions in pngget.c + Set each pointer to NULL after freeing it in png_free_data(). + Worked around a problem in pngconf.h; AIX's strings.h defines an "index" + macro that conflicts with libpng's png_color_16.index. (Dimitri Papadapoulos) + Added "msvc" directory with MSVC++ project files (Simon-Pierre Cadieux). +version 1.0.7beta16 [June 4, 2000] + Revised the workaround of AIX string.h "index" bug. + Added a check for overlength PLTE chunk in pngrutil.c. + Added PNG_NO_POINTER_INDEXING macro to use array-indexing instead of pointer + indexing in pngrutil.c and pngwutil.c to accommodate a buggy compiler. + Added a warning in png_decompress_chunk() when it runs out of data, e.g. + when it tries to read an erroneous PhotoShop iCCP chunk. + Added PNG_USE_DLL macro. + Revised the copyright/disclaimer/license notice. + Added contrib/msvctest directory +version 1.0.7rc1 [June 9, 2000] + Corrected the definition of PNG_TRANSFORM_INVERT_ALPHA (0x0400 not 0x0200) + Added contrib/visupng directory (Willem van Schaik) +version 1.0.7beta18 [June 23, 2000] + Revised PNGAPI definition, and pngvcrd.c to work with __GCC__ + and do not redefine PNGAPI if it is passed in via a compiler directive. + Revised visupng/PngFile.c to remove returns from within the Try block. + Removed leading underscores from "_PNG_H" and "_PNG_SAVE_BSD_SOURCE" macros. + Updated contrib/visupng/cexcept.h to version 1.0.0. + Fixed bugs in pngwrite.c and pngwutil.c that prevented writing iCCP chunks. +version 1.0.7rc2 [June 28, 2000] + Updated license to include disclaimers required by UCITA. + Fixed "DJBPP" typo in pnggccrd.c introduced in beta18. + +version 1.0.7 [July 1, 2000] + Revised the definition of "trans_values" in libpng.3/libpng.txt +version 1.0.8beta1 [July 8, 2000] + Added png_free(png_ptr, key) two places in pngpread.c to stop memory leaks. + Changed PNG_NO_STDIO to PNG_NO_CONSOLE_IO, several places in pngrutil.c and + pngwutil.c. + Changed PNG_EXPORT_VAR to use PNG_IMPEXP, in pngconf.h. + Removed unused "#include <assert.h>" from png.c + Added WindowsCE support. + Revised pnggccrd.c to work with gcc-2.95.2 and in the Cygwin environment. +version 1.0.8beta2 [July 10, 2000] + Added project files to the wince directory and made further revisions + of pngtest.c, pngrio.c, and pngwio.c in support of WindowsCE. +version 1.0.8beta3 [July 11, 2000] + Only set the PNG_FLAG_FREE_TRNS or PNG_FREE_TRNS flag in png_handle_tRNS() + for indexed-color input files to avoid potential double-freeing trans array + under some unusual conditions; problem was introduced in version 1.0.6f. + Further revisions to pngtest.c and files in the wince subdirectory. +version 1.0.8beta4 [July 14, 2000] + Added the files pngbar.png and pngbar.jpg to the distribution. + Added makefile.cygwin, and cygwin support in pngconf.h + Added PNG_NO_ZALLOC_ZERO macro (makes png_zalloc skip zeroing memory) +version 1.0.8rc1 [July 16, 2000] + Revised png_debug() macros and statements to eliminate compiler warnings. + +version 1.0.8 [July 24, 2000] + Added png_flush() in pngwrite.c, after png_write_IEND(). + Updated makefile.hpux to build a shared library. +version 1.0.9beta1 [November 10, 2000] + Fixed typo in scripts/makefile.hpux + Updated makevms.com in scripts and contrib/* and contrib/* (Martin Zinser) + Fixed seqence-point bug in contrib/pngminus/png2pnm (Martin Zinser) + Changed "cdrom.com" in documentation to "libpng.org" + Revised pnggccrd.c to get it all working, and updated makefile.gcmmx (Greg). + Changed type of "params" from voidp to png_voidp in png_read|write_png(). + Make sure PNGAPI and PNG_IMPEXP are defined in pngconf.h. + Revised the 3 instances of WRITEFILE in pngtest.c. + Relocated "msvc" and "wince" project subdirectories into "dll" subdirectory. + Updated png.rc in dll/msvc project + Revised makefile.dec to define and use LIBPATH and INCPATH + Increased size of global png_libpng_ver[] array from 12 to 18 chars. + Made global png_libpng_ver[], png_sig[] and png_pass_*[] arrays const. + Removed duplicate png_crc_finish() from png_handle_bKGD() function. + Added a warning when application calls png_read_update_info() multiple times. + Revised makefile.cygwin + Fixed bugs in iCCP support in pngrutil.c and pngwutil.c. + Replaced png_set_empty_plte_permitted() with png_permit_mng_features(). +version 1.0.9beta2 [November 19, 2000] + Renamed the "dll" subdirectory "projects". + Added borland project files to "projects" subdirectory. + Set VS_FF_PRERELEASE and VS_FF_PATCHED flags in msvc/png.rc when appropriate. + Add error message in png_set_compression_buffer_size() when malloc fails. +version 1.0.9beta3 [November 23, 2000] + Revised PNG_LIBPNG_BUILD_TYPE macro in png.h, used in the msvc project. + Removed the png_flush() in pngwrite.c that crashes some applications + that don't set png_output_flush_fn. + Added makefile.macosx and makefile.aix to scripts directory. +version 1.0.9beta4 [December 1, 2000] + Change png_chunk_warning to png_warning in png_check_keyword(). + Increased the first part of msg buffer from 16 to 18 in png_chunk_error(). +version 1.0.9beta5 [December 15, 2000] + Added support for filter method 64 (for PNG datastreams embedded in MNG). +version 1.0.9beta6 [December 18, 2000] + Revised png_set_filter() to accept filter method 64 when appropriate. + Added new PNG_HAVE_PNG_SIGNATURE bit to png_ptr->mode and use it to + help prevent applications from using MNG features in PNG datastreams. + Added png_permit_mng_features() function. + Revised libpng.3/libpng.txt. Changed "filter type" to "filter method". +version 1.0.9rc1 [December 23, 2000] + Revised test for PNG_HAVE_PNG_SIGNATURE in pngrutil.c + Fixed error handling of unknown compression type in png_decompress_chunk(). + In pngconf.h, define __cdecl when _MSC_VER is defined. +version 1.0.9beta7 [December 28, 2000] + Changed PNG_TEXT_COMPRESSION_zTXt to PNG_COMPRESSION_TYPE_BASE several places. + Revised memory management in png_set_hIST and png_handle_hIST in a backward + compatible manner. PLTE and tRNS were revised similarly. + Revised the iCCP chunk reader to ignore trailing garbage. +version 1.0.9beta8 [January 12, 2001] + Moved pngasmrd.h into pngconf.h. + Improved handling of out-of-spec garbage iCCP chunks generated by PhotoShop. +version 1.0.9beta9 [January 15, 2001] + Added png_set_invalid, png_permit_mng_features, and png_mmx_supported to + wince and msvc project module definition files. + Minor revision of makefile.cygwin. + Fixed bug with progressive reading of narrow interlaced images in pngpread.c +version 1.0.9beta10 [January 16, 2001] + Do not typedef png_FILE_p in pngconf.h when PNG_NO_STDIO is defined. + Fixed "png_mmx_supported" typo in project definition files. +version 1.0.9beta11 [January 19, 2001] + Updated makefile.sgi to make shared library. + Removed png_mmx_support() function and disabled PNG_MNG_FEATURES_SUPPORTED + by default, for the benefit of DLL forward compatibility. These will + be re-enabled in version 1.2.0. +version 1.0.9rc2 [January 22, 2001] + Revised cygwin support. + +version 1.0.9 [January 31, 2001] + Added check of cygwin's ALL_STATIC in pngconf.h + Added "-nommx" parameter to contrib/gregbook/rpng2-win and rpng2-x demos. +version 1.0.10beta1 [March 14, 2001] + Revised makefile.dec, makefile.sgi, and makefile.sggcc; added makefile.hpgcc. + Reformatted libpng.3 to eliminate bad line breaks. + Added checks for _mmx_supported in the read_filter_row function of pnggccrd.c + Added prototype for png_mmx_support() near the top of pnggccrd.c + Moved some error checking from png_handle_IHDR to png_set_IHDR. + Added PNG_NO_READ_SUPPORTED and PNG_NO_WRITE_SUPPORTED macros. + Revised png_mmx_support() function in pnggccrd.c + Restored version 1.0.8 PNG_WRITE_EMPTY_PLTE_SUPPORTED behavior in pngwutil.c + Fixed memory leak in contrib/visupng/PngFile.c + Fixed bugs in png_combine_row() in pnggccrd.c and pngvcrd.c (C version) + Added warnings when retrieving or setting gamma=0. + Increased the first part of msg buffer from 16 to 18 in png_chunk_warning(). +version 1.0.10rc1 [March 23, 2001] + Changed all instances of memcpy, strcpy, and strlen to png_memcpy, png_strcpy, + and png_strlen. + Revised png_mmx_supported() function in pnggccrd.c to return proper value. + Fixed bug in progressive reading (pngpread.c) with small images (height < 8). + +version 1.0.10 [March 30, 2001] + Deleted extraneous space (introduced in 1.0.9) from line 42 of makefile.cygwin + Added beos project files (Chris Herborth) +version 1.0.11beta1 [April 3, 2001] + Added type casts on several png_malloc() calls (Dimitri Papadapoulos). + Removed a no-longer needed AIX work-around from pngconf.h + Changed several "//" single-line comments to C-style in pnggccrd.c +version 1.0.11beta2 [April 11, 2001] + Removed PNGAPI from several functions whose prototypes did not have PNGAPI. + Updated scripts/pngos2.def +version 1.0.11beta3 [April 14, 2001] + Added checking the results of many instances of png_malloc() for NULL +version 1.0.11beta4 [April 20, 2001] + Undid the changes from version 1.0.11beta3. Added a check for NULL return + from user's malloc_fn(). + Removed some useless type casts of the NULL pointer. + Added makefile.netbsd + +version 1.0.11 [April 27, 2001] + Revised makefile.netbsd +version 1.0.12beta1 [May 14, 2001] + Test for Windows platform in pngconf.h when including malloc.h (Emmanuel Blot) + Updated makefile.cygwin and handling of Cygwin's ALL_STATIC in pngconf.h + Added some never-to-be-executed code in pnggccrd.c to quiet compiler warnings. + Eliminated the png_error about apps using png_read|write_init(). Instead, + libpng will reallocate the png_struct and info_struct if they are too small. + This retains future binary compatibility for old applications written for + libpng-0.88 and earlier. +version 1.2.0beta1 [May 6, 2001] + Bumped DLLNUM to 2. + Re-enabled PNG_MNG_FEATURES_SUPPORTED and enabled PNG_ASSEMBLER_CODE_SUPPORTED + by default. + Added runtime selection of MMX features. + Added png_set_strip_error_numbers function and related macros. +version 1.2.0beta2 [May 7, 2001] + Finished merging 1.2.0beta1 with version 1.0.11 + Added a check for attempts to read or write PLTE in grayscale PNG datastreams. +version 1.2.0beta3 [May 17, 2001] + Enabled user memory function by default. + Modified png_create_struct so it passes user mem_ptr to user memory allocator. + Increased png_mng_features flag from png_byte to png_uint_32. + Bumped shared-library (so-number) and dll-number to 3. +version 1.2.0beta4 [June 23, 2001] + Check for missing profile length field in iCCP chunk and free chunk_data + in case of truncated iCCP chunk. + Bumped shared-library number to 3 in makefile.sgi and makefile.sggcc + Bumped dll-number from 2 to 3 in makefile.cygwin + Revised contrib/gregbook/rpng*-x.c to avoid a memory leak and to exit cleanly + if user attempts to run it on an 8-bit display. + Updated contrib/gregbook + Use png_malloc instead of png_zalloc to allocate palette in pngset.c + Updated makefile.ibmc + Added some typecasts to eliminate gcc 3.0 warnings. Changed prototypes + of png_write_oFFS width and height from png_uint_32 to png_int_32. + Updated example.c + Revised prototypes for png_debug_malloc and png_debug_free in pngtest.c +version 1.2.0beta5 [August 8, 2001] + Revised contrib/gregbook + Revised makefile.gcmmx + Revised pnggccrd.c to conditionally compile some thread-unsafe code only + when PNG_THREAD_UNSAFE_OK is defined. + Added tests to prevent pngwutil.c from writing a bKGD or tRNS chunk with + value exceeding 2^bit_depth-1 + Revised makefile.sgi and makefile.sggcc + Replaced calls to fprintf(stderr,...) with png_warning() in pnggccrd.c + Removed restriction that do_invert_mono only operate on 1-bit opaque files + +version 1.2.0 [September 1, 2001] + Changed a png_warning() to png_debug() in pnggccrd.c + Fixed contrib/gregbook/rpng-x.c, rpng2-x.c to avoid crash with XFreeGC(). +version 1.2.1beta1 [October 19, 2001] + Revised makefile.std in contrib/pngminus + Include background_1 in png_struct regardless of gamma support. + Revised makefile.netbsd and makefile.macosx, added makefile.darwin. + Revised example.c to provide more details about using row_callback(). +version 1.2.1beta2 [October 25, 2001] + Added type cast to each NULL appearing in a function call, except for + WINCE functions. + Added makefile.so9. +version 1.2.1beta3 [October 27, 2001] + Removed type casts from all NULLs. + Simplified png_create_struct_2(). +version 1.2.1beta4 [November 7, 2001] + Revised png_create_info_struct() and png_creat_struct_2(). + Added error message if png_write_info() was omitted. + Type cast NULLs appearing in function calls when _NO_PROTO or + PNG_TYPECAST_NULL is defined. +version 1.2.1rc1 [November 24, 2001] + Type cast NULLs appearing in function calls except when PNG_NO_TYPECAST_NULL + is defined. + Changed typecast of "size" argument to png_size_t in pngmem.c calls to + the user malloc_fn, to agree with the prototype in png.h + Added a pop/push operation to pnggccrd.c, to preserve Eflag (Maxim Sobolev) + Updated makefile.sgi to recognize LIBPATH and INCPATH. + Updated various makefiles so "make clean" does not remove previous major + version of the shared library. +version 1.2.1rc2 [December 4, 2001] + Always allocate 256-entry internal palette, hist, and trans arrays, to + avoid out-of-bounds memory reference caused by invalid PNG datastreams. + Added a check for prefix_length > data_length in iCCP chunk handler. + +version 1.2.1 [December 7, 2001] + None. +version 1.2.2beta1 [February 22, 2002] + Fixed a bug with reading the length of iCCP profiles (Larry Reeves). + Revised makefile.linux, makefile.gcmmx, and makefile.sgi to generate + libpng.a, libpng12.so (not libpng.so.3), and libpng12/png.h + Revised makefile.darwin to remove "-undefined suppress" option. + Added checks for gamma and chromaticity values over 21474.83, which exceed + the limit for PNG unsigned 32-bit integers when encoded. + Revised calls to png_create_read_struct() and png_create_write_struct() + for simpler debugging. + Revised png_zalloc() so zlib handles errors (uses PNG_FLAG_MALLOC_NULL_MEM_OK) +version 1.2.2beta2 [February 23, 2002] + Check chunk_length and idat_size for invalid (over PNG_MAX_UINT) lengths. + Check for invalid image dimensions in png_get_IHDR. + Added missing "fi;" in the install target of the SGI makefiles. + Added install-static to all makefiles that make shared libraries. + Always do gamma compensation when image is partially transparent. +version 1.2.2beta3 [March 7, 2002] + Compute background.gray and background_1.gray even when color_type is RGB + in case image gets reduced to gray later. + Modified shared-library makefiles to install pkgconfig/libpngNN.pc. + Export (with PNGAPI) png_zalloc, png_zfree, and png_handle_as_unknown + Removed unused png_write_destroy_info prototype from png.h + Eliminated incorrect use of width_mmx from pnggccrd.c in pixel_bytes == 8 case + Added install-shared target to all makefiles that make shared libraries. + Stopped a double free of palette, hist, and trans when not using free_me. + Added makefile.32sunu for Sun Ultra 32 and makefile.64sunu for Sun Ultra 64. +version 1.2.2beta4 [March 8, 2002] + Compute background.gray and background_1.gray even when color_type is RGB + in case image gets reduced to gray later (Jason Summers). + Relocated a misplaced /bin/rm in the "install-shared" makefile targets + Added PNG_1_0_X macro which can be used to build a 1.0.x-compatible library. +version 1.2.2beta5 [March 26, 2002] + Added missing PNGAPI to several function definitions. + Check for invalid bit_depth or color_type in png_get_IHDR(), and + check for missing PLTE or IHDR in png_push_read_chunk() (Matthias Clasen). + Revised iTXt support to accept NULL for lang and lang_key. + Compute gamma for color components of background even when color_type is gray. + Changed "()" to "{}" in scripts/libpng.pc.in. + Revised makefiles to put png.h and pngconf.h only in $prefix/include/libpngNN + Revised makefiles to make symlink to libpng.so.NN in addition to libpngNN.so +version 1.2.2beta6 [March 31, 2002] +version 1.0.13beta1 [March 31, 2002] + Prevent png_zalloc() from trying to memset memory that it failed to acquire. + Add typecasts of PNG_MAX_UINT in pngset_cHRM_fixed() (Matt Holgate). + Ensure that the right function (user or default) is used to free the + png_struct after an error in png_create_read_struct_2(). +version 1.2.2rc1 [April 7, 2002] +version 1.0.13rc1 [April 7, 2002] + Save the ebx register in pnggccrd.c (Sami Farin) + Add "mem_ptr = png_ptr->mem_ptr" in png_destroy_write_struct() (Paul Gardner). + Updated makefiles to put headers in include/libpng and remove old include/*.h. + +version 1.2.2 [April 15, 2002] +version 1.0.13 [April 15, 2002] + Revised description of png_set_filter() in libpng.3/libpng.txt. + Revised makefile.netbsd and added makefile.neNNbsd and makefile.freebsd +version 1.0.13patch01 [April 17, 2002] +version 1.2.2patch01 [April 17, 2002] + Changed ${PNGMAJ}.${PNGVER} bug to ${PNGVER} in makefile.sgi and makefile.sggcc + Fixed VER -> PNGVER typo in makefile.macosx and added install-static to install + Added install: target to makefile.32sunu and makefile.64sunu +version 1.0.13patch03 [April 18, 2002] +version 1.2.2patch03 [April 18, 2002] + Revised 15 makefiles to link libpng.a to libpngNN.a and the include libpng + subdirectory to libpngNN subdirectory without the full pathname. + Moved generation of libpng.pc from "install" to "all" in 15 makefiles. +version 1.2.3rc1 [April 28, 2002] + Added install-man target to 15 makefiles (Dimitri Papadopolous-Orfanos). + Added $(DESTDIR) feature to 24 makefiles (Tim Mooney) + Fixed bug with $prefix, should be $(prefix) in makefile.hpux. + Updated cygwin-specific portion of pngconf.h and revised makefile.cygwin + Added a link from libpngNN.pc to libpng.pc in 15 makefiles. + Added links from include/libpngNN/*.h to include/*.h in 24 makefiles. + Revised makefile.darwin to make relative links without full pathname. + Added setjmp() at the end of png_create_*_struct_2() in case user forgets + to put one in their application. + Restored png_zalloc() and png_zfree() prototypes to version 1.2.1 and + removed them from module definition files. +version 1.2.3rc2 [May 1, 2002] + Fixed bug in reporting number of channels in pngget.c and pngset.c, + that was introduced in version 1.2.2beta5. + Exported png_zalloc(), png_zfree(), png_default_read(), png_default_write(), + png_default_flush(), and png_push_fill_buffer() and included them in + module definition files. + Added "libpng.pc" dependency to the "install-shared" target in 15 makefiles. +version 1.2.3rc3 [May 1, 2002] + Revised prototype for png_default_flush() + Remove old libpng.pc and libpngNN.pc before installing new ones. +version 1.2.3rc4 [May 2, 2002] + Typos in *.def files (png_default_read|write -> png_default_read|write_data) + In makefiles, changed rm libpng.NN.pc to rm libpngNN.pc + Added libpng-config and libpngNN-config and modified makefiles to install them. + Changed $(MANPATH) to $(DESTDIR)$(MANPATH) in makefiles + Added "Win32 DLL VB" configuration to projects/msvc/libpng.dsp +version 1.2.3rc5 [May 11, 2002] + Changed "error" and "message" in prototypes to "error_message" and + "warning_message" to avoid namespace conflict. + Revised 15 makefiles to build libpng-config from libpng-config-*.in + Once more restored png_zalloc and png_zfree to regular nonexported form. + Restored png_default_read|write_data, png_default_flush, png_read_fill_buffer + to nonexported form, but with PNGAPI, and removed them from module def files. +version 1.2.3rc6 [May 14, 2002] + Removed "PNGAPI" from png_zalloc() and png_zfree() in png.c + Changed "Gz" to "Gd" in projects/msvc/libpng.dsp and zlib.dsp. + Removed leftover libpng-config "sed" script from four makefiles. + Revised libpng-config creating script in 16 makefiles. + +version 1.2.3 [May 22, 2002] + Revised libpng-config target in makefile.cygwin. + Removed description of png_set_mem_fn() from documentation. + Revised makefile.freebsd. + Minor cosmetic changes to 15 makefiles, e.g., $(DI) = $(DESTDIR)/$(INCDIR). + Revised projects/msvc/README.txt + Changed -lpng to -lpngNN in LDFLAGS in several makefiles. +version 1.2.4beta1 [May 24, 2002] + Added libpng.pc and libpng-config to "all:" target in 16 makefiles. + Fixed bug in 16 makefiles: $(DESTDIR)/$(LIBPATH) to $(DESTDIR)$(LIBPATH) + Added missing "\" before closing double quote in makefile.gcmmx. + Plugged various memory leaks; added png_malloc_warn() and png_set_text_2() + functions. +version 1.2.4beta2 [June 25, 2002] + Plugged memory leak of png_ptr->current_text (Matt Holgate). + Check for buffer overflow before reading CRC in pngpread.c (Warwick Allison) + Added -soname to the loader flags in makefile.dec, makefile.sgi, and + makefile.sggcc. + Added "test-installed" target to makefile.linux, makefile.gcmmx, + makefile.sgi, and makefile.sggcc. +version 1.2.4beta3 [June 28, 2002] + Plugged memory leak of row_buf in pngtest.c when there is a png_error(). + Detect buffer overflow in pngpread.c when IDAT is corrupted with extra data. + Added "test-installed" target to makefile.32sunu, makefile.64sunu, + makefile.beos, makefile.darwin, makefile.dec, makefile.macosx, + makefile.solaris, makefile.hpux, makefile.hpgcc, and makefile.so9. +version 1.2.4rc1 and 1.0.14rc1 [July 2, 2002] + Added "test-installed" target to makefile.cygwin and makefile.sco. + Revised pnggccrd.c to be able to back out version 1.0.x via PNG_1_0_X macro. + +version 1.2.4 and 1.0.14 [July 8, 2002] + Changed png_warning() to png_error() when width is too large to process. +version 1.2.4patch01 [July 20, 2002] + Revised makefile.cygwin to use DLL number 12 instead of 13. +version 1.2.5beta1 [August 6, 2002] + Added code to contrib/gregbook/readpng2.c to ignore unused chunks. + Replaced toucan.png in contrib/gregbook (it has been corrupt since 1.0.11) + Removed some stray *.o files from contrib/gregbook. + Changed png_error() to png_warning() about "Too much data" in pngpread.c + and about "Extra compressed data" in pngrutil.c. + Prevent png_ptr->pass from exceeding 7 in png_push_finish_row(). + Updated makefile.hpgcc + Updated png.c and pnggccrd.c handling of return from png_mmx_support() +version 1.2.5beta2 [August 15, 2002] + Only issue png_warning() about "Too much data" in pngpread.c when avail_in + is nonzero. + Updated makefiles to install a separate libpng.so.3 with its own rpath. +version 1.2.5rc1 and 1.0.15rc1 [August 24, 2002] + Revised makefiles to not remove previous minor versions of shared libraries. +version 1.2.5rc2 and 1.0.15rc2 [September 16, 2002] + Revised 13 makefiles to remove "-lz" and "-L$(ZLIBLIB)", etc., from shared + library loader directive. + Added missing "$OBJSDLL" line to makefile.gcmmx. + Added missing "; fi" to makefile.32sunu. +version 1.2.5rc3 and 1.0.15rc3 [September 18, 2002] + Revised libpng-config script. + +version 1.2.5 and 1.0.15 [October 3, 2002] + Revised makefile.macosx, makefile.darwin, makefile.hpgcc, and makefile.hpux, + and makefile.aix. + Relocated two misplaced PNGAPI lines in pngtest.c +version 1.2.6beta1 [October 22, 2002] + Commented out warning about uninitialized mmx_support in pnggccrd.c. + Changed "IBMCPP__" flag to "__IBMCPP__" in pngconf.h. + Relocated two more misplaced PNGAPI lines in pngtest.c + Fixed memory overrun bug in png_do_read_filler() with 16-bit datastreams, + introduced in version 1.0.2. + Revised makefile.macosx, makefile.dec, makefile.aix, and makefile.32sunu. +version 1.2.6beta2 [November 1, 2002] + Added libpng-config "--ldopts" output. + Added "AR=ar" and "ARFLAGS=rc" and changed "ar rc" to "$(AR) $(ARFLAGS)" + in makefiles. +version 1.2.6beta3 [July 18, 2004] + Reverted makefile changes from version 1.2.6beta2 and some of the changes + from version 1.2.6beta1; these will be postponed until version 1.2.7. + Version 1.2.6 is going to be a simple bugfix release. + Changed the one instance of "ln -sf" to "ln -f -s" in each Sun makefile. + Fixed potential overrun in pngerror.c by using strncpy instead of memcpy. + Added "#!/bin/sh" at the top of configure, for recognition of the + 'x' flag under Cygwin (Cosmin). + Optimized vacuous tests that silence compiler warnings, in png.c (Cosmin). + Added support for PNG_USER_CONFIG, in pngconf.h (Cosmin). + Fixed the special memory handler for Borland C under DOS, in pngmem.c + (Cosmin). + Removed some spurious assignments in pngrutil.c (Cosmin). + Replaced 65536 with 65536L, and 0xffff with 0xffffL, to silence warnings + on 16-bit platforms (Cosmin). + Enclosed shift op expressions in parentheses, to silence warnings (Cosmin). + Used proper type png_fixed_point, to avoid problems on 16-bit platforms, + in png_handle_sRGB() (Cosmin). + Added compression_type to png_struct, and optimized the window size + inside the deflate stream (Cosmin). + Fixed definition of isnonalpha(), in pngerror.c and pngrutil.c (Cosmin). + Fixed handling of unknown chunks that come after IDAT (Cosmin). + Allowed png_error() and png_warning() to work even if png_ptr == NULL + (Cosmin). + Replaced row_info->rowbytes with row_bytes in png_write_find_filter() + (Cosmin). + Fixed definition of PNG_LIBPNG_VER_DLLNUM (Simon-Pierre). + Used PNG_LIBPNG_VER and PNG_LIBPNG_VER_STRING instead of the hardcoded + values in png.c (Simon-Pierre, Cosmin). + Initialized png_libpng_ver[] with PNG_LIBPNG_VER_STRING (Simon-Pierre). + Replaced PNG_LIBPNG_VER_MAJOR with PNG_LIBPNG_VER_DLLNUM in png.rc + (Simon-Pierre). + Moved the definition of PNG_HEADER_VERSION_STRING near the definitions + of the other PNG_LIBPNG_VER_... symbols in png.h (Cosmin). + Relocated #ifndef PNGAPI guards in pngconf.h (Simon-Pierre, Cosmin). + Updated scripts/makefile.vc(a)win32 (Cosmin). + Updated the MSVC project (Simon-Pierre, Cosmin). + Updated the Borland C++ Builder project (Cosmin). + Avoided access to asm_flags in pngvcrd.c, if PNG_1_0_X is defined (Cosmin). + Commented out warning about uninitialized mmx_support in pngvcrd.c (Cosmin). + Removed scripts/makefile.bd32 and scripts/pngdef.pas (Cosmin). + Added extra guard around inclusion of Turbo C memory headers, in pngconf.h + (Cosmin). + Renamed projects/msvc/ to projects/visualc6/, and projects/borland/ to + projects/cbuilder5/ (Cosmin). + Moved projects/visualc6/png32ms.def to scripts/pngw32.def, + and projects/visualc6/png.rc to scripts/pngw32.rc (Cosmin). + Added projects/visualc6/pngtest.dsp; removed contrib/msvctest/ (Cosmin). + Changed line endings to DOS style in cbuilder5 and visualc6 files, even + in the tar.* distributions (Cosmin). + Updated contrib/visupng/VisualPng.dsp (Cosmin). + Updated contrib/visupng/cexcept.h to version 2.0.0 (Cosmin). + Added a separate distribution with "configure" and supporting files (Junichi). +version 1.2.6beta4 [July 28, 2004] + Added user ability to change png_size_t via a PNG_SIZE_T macro. + Added png_sizeof() and png_convert_size() functions. + Added PNG_SIZE_MAX (maximum value of a png_size_t variable. + Added check in png_malloc_default() for (size_t)size != (png_uint_32)size + which would indicate an overflow. + Changed sPLT failure action from png_error to png_warning and abandon chunk. + Changed sCAL and iCCP failures from png_error to png_warning and abandon. + Added png_get_uint_31(png_ptr, buf) function. + Added PNG_UINT_32_MAX macro. + Renamed PNG_MAX_UINT to PNG_UINT_31_MAX. + Made png_zalloc() issue a png_warning and return NULL on potential + overflow. + Turn on PNG_NO_ZALLOC_ZERO by default in version 1.2.x + Revised "clobber list" in pnggccrd.c so it will compile under gcc-3.4. + Revised Borland portion of png_malloc() to return NULL or issue + png_error() according to setting of PNG_FLAG_MALLOC_NULL_MEM_OK. + Added PNG_NO_SEQUENTIAL_READ_SUPPORTED macro to conditionally remove + sequential read support. + Added some "#if PNG_WRITE_SUPPORTED" blocks. + #ifdef'ed out some redundancy in png_malloc_default(). + Use png_malloc instead of png_zalloc to allocate the pallete. +version 1.0.16rc1 and 1.2.6rc1 [August 4, 2004] + Fixed buffer overflow vulnerability in png_handle_tRNS() + Fixed integer arithmetic overflow vulnerability in png_read_png(). + Fixed some harmless bugs in png_handle_sBIT, etc, that would cause + duplicate chunk types to go undetected. + Fixed some timestamps in the -config version + Rearranged order of processing of color types in png_handle_tRNS(). + Added ROWBYTES macro to calculate rowbytes without integer overflow. + Updated makefile.darwin and removed makefile.macosx from scripts directory. + Imposed default one million column, one-million row limits on the image + dimensions, and added png_set_user_limits() function to override them. + Revised use of PNG_SET_USER_LIMITS_SUPPORTED macro. + Fixed wrong cast of returns from png_get_user_width|height_max(). + Changed some "keep the compiler happy" from empty statements to returns, + Revised libpng.txt to remove 1.2.x stuff from the 1.0.x distribution +version 1.0.16rc2 and 1.2.6rc2 [August 7, 2004] + Revised makefile.darwin and makefile.solaris. Removed makefile.macosx. + Revised pngtest's png_debug_malloc() to use png_malloc() instead of + png_malloc_default() which is not supposed to be exported. + Fixed off-by-one error in one of the conversions to PNG_ROWBYTES() in + pngpread.c. Bug was introduced in 1.2.6rc1. + Fixed bug in RGB to RGBX transformation introduced in 1.2.6rc1. + Fixed old bug in RGB to Gray transformation. + Fixed problem with 64-bit compilers by casting arguments to abs() + to png_int_32. + Changed "ln -sf" to "ln -f -s" in three makefiles (solaris, sco, so9). + Changed "HANDLE_CHUNK_*" to "PNG_HANDLE_CHUNK_*" (Cosmin) + Added "-@/bin/rm -f $(DL)/$(LIBNAME).so.$(PNGMAJ)" to 15 *NIX makefiles. + Added code to update the row_info->colortype in png_do_read_filler() (MSB). +version 1.0.16rc3 and 1.2.6rc3 [August 9, 2004] + Eliminated use of "abs()" in testing cHRM and gAMA values, to avoid + trouble with some 64-bit compilers. Created PNG_OUT_OF_RANGE() macro. + Revised documentation of png_set_keep_unknown_chunks(). + Check handle_as_unknown status in pngpread.c, as in pngread.c previously. + Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_INTERNAL section of png.h + Added "rim" definitions for CONST4 and CONST6 in pnggccrd.c +version 1.0.16rc4 and 1.2.6rc4 [August 10, 2004] + Fixed mistake in pngtest.c introduced in 1.2.6rc2 (declaration of + "pinfo" was out of place). +version 1.0.16rc5 and 1.2.6rc5 [August 10, 2004] + Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_ASSEMBLER_CODE_SUPPORTED + section of png.h where they were inadvertently placed in version rc3. + +version 1.0.16 and 1.2.6 [August 15, 2004] + Revised pngtest so memory allocation testing is only done when PNG_DEBUG==1. +version 1.2.7beta1 [August 26, 2004] + Removed unused pngasmrd.h file. + Removed references to uu.net for archived files. Added references to + PNG Spec (second edition) and the PNG ISO/IEC Standard. + Added "test-dd" target in 15 makefiles, to run pngtest in DESTDIR. + Fixed bug with "optimized window size" in the IDAT datastream, that + causes libpng to write PNG files with incorrect zlib header bytes. +version 1.2.7beta2 [August 28, 2004] + Fixed bug with sCAL chunk and big-endian machines (David Munro). + Undid new code added in 1.2.6rc2 to update the color_type in + png_set_filler(). + Added png_set_add_alpha() that updates color type. +version 1.0.17rc1 and 1.2.7rc1 [September 4, 2004] + Revised png_set_strip_filler() to not remove alpha if color_type has alpha. +version 1.0.17 and 1.2.7 [September 12, 2004] + Added makefile.hp64 + Changed projects/msvc/png32ms.def to scripts/png32ms.def in makefile.cygwin + +Send comments/corrections/commendations to +png-implement@ccrc.wustl.edu (subscription required; write to +majordomo@ccrc.wustl.edu with "subscribe png-implement" in the message) +or to glennrp@users.sourceforge.net + +Glenn R-P diff --git a/Utilities/FLTK/png/CMakeLists.txt b/Utilities/FLTK/png/CMakeLists.txt new file mode 100644 index 0000000000..eb29848858 --- /dev/null +++ b/Utilities/FLTK/png/CMakeLists.txt @@ -0,0 +1,30 @@ +PROJECT(FLTKPNG) +INCLUDE_REGULAR_EXPRESSION("^png.*$") + +INCLUDE_DIRECTORIES(${FLTKZLIB_SOURCE_DIR}) + +IF(ZLIB_INCLUDE_DIR) + INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) +ENDIF(ZLIB_INCLUDE_DIR) + +INCLUDE_DIRECTORIES(${FLTKPNG_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${FLTKPNG_BINARY_DIR}) + +# source files for png +SET(PNG_SRCS + pngget.c pngrio.c pngwrite.c + png.c pngmem.c pngrtran.c pngtrans.c pngwtran.c + pngerror.c pngpread.c pngrutil.c pngwutil.c + pngread.c pngset.c pngwio.c + ) + +ADD_LIBRARY(fltk_png ${PNG_SRCS}) +INSTALL_TARGETS(/lib fltk_png) + + +IF(UNIX) + TARGET_LINK_LIBRARIES(fltk_png ${FLTK_ZLIB_LIBRARIES} -lm) +ELSE(UNIX) + TARGET_LINK_LIBRARIES(fltk_png ${FLTK_ZLIB_LIBRARIES}) +ENDIF(UNIX) + diff --git a/Utilities/FLTK/png/INSTALL b/Utilities/FLTK/png/INSTALL new file mode 100644 index 0000000000..9876e9d30e --- /dev/null +++ b/Utilities/FLTK/png/INSTALL @@ -0,0 +1,167 @@ + +Installing libpng version 1.2.7 - September 12, 2004 + +Before installing libpng, you must first install zlib. zlib +can usually be found wherever you got libpng. zlib can be +placed in another directory, at the same level as libpng. +Note that your system might already have a preinstalled +zlib, but you will still need to have access to the +zlib.h and zconf.h include files that correspond to the +version of zlib that's installed. + +You can rename the directories that you downloaded (they +might be called "libpng-1.2.7" or "lpng109" and "zlib-1.2.1" +or "zlib121") so that you have directories called "zlib" and "libpng". + +Your directory structure should look like this: + + .. (the parent directory) + libpng (this directory) + INSTALL (this file) + README + *.h + *.c + contrib + gregbook + pngminus + pngsuite + visupng + projects + beos + c5builder (Borland) + visualc6 (msvc) + netware.txt + wince.txt + scripts + makefile.* + pngtest.png + etc. + zlib + README + *.h + *.c + contrib + etc. + +If the line endings in the files look funny, you may wish to get the other +distribution of libpng. It is available in both tar.gz (UNIX style line +endings) and zip (DOS style line endings) formats. + + +If you are building libpng with MSVC, you can enter the +libpng projects\visualc6 directory and follow the instructions in +projects\visualc6\README.txt. + +You can build libpng for WindowsCE by downloading and installing +the projects\wince directory as instructed in the projects\wince.txt file, and +then following the instructions in the README* files. Similarly, you can +build libpng for Netware or Beos as instructed in projects\netware.txt +or projects\beos. + +Else enter the zlib directory and follow the instructions in zlib/README, +then come back here and choose the appropriate makefile.sys in the scripts +directory. + +The files that are presently available in the scripts directory +include + + makefile.std => Generic UNIX makefile (cc, creates static libpng.a) + makefile.linux => Linux/ELF makefile + (gcc, creates libpng12.so.0.1.2.7) + makefile.gcmmx => Linux/ELF makefile + (gcc, creates libpng12.so.0.1.2.7, + uses assembler code tuned for Intel MMX platform) + makefile.gcc => Generic makefile (gcc, creates static libpng.a) + makefile.knr => Archaic UNIX Makefile that converts files with + ansi2knr (Requires ansi2knr.c from + ftp://ftp.cs.wisc.edu/ghost) + makefile.aix => AIX/gcc makefile + makefile.cygwin => Cygwin/gcc makefile + makefile.darwin => Darwin makefile, can use on MacosX + makefile.dec => DEC Alpha UNIX makefile + makefile.freebsd => FreeBSD makefile + makefile.hpgcc => HPUX makefile using gcc + makefile.hpux => HPUX (10.20 and 11.00) makefile + makefile.hp64 => HPUX (10.20 and 11.00) makefile, 64-bit + makefile.ibmc => IBM C/C++ version 3.x for Win32 and OS/2 (static) + makefile.intel => Intel C/C++ version 4.0 and later + libpng.icc => Project file for IBM VisualAge/C++ version 4.0 or later + makefile.netbsd => NetBSD/cc makefile, uses PNGGCCRD, makes libpng.so. + makefile.ne12bsd => NetBSD/cc makefile, uses PNGGCCRD, + makes libpng12.so + makefile.openbsd => OpenBSD makefile + makefile.sgi => Silicon Graphics IRIX makefile (cc, creates static lib) + makefile.sggcc => Silicon Graphics (gcc, + creates libpng12.so.0.1.2.7) + makefile.sunos => Sun makefile + makefile.solaris => Solaris 2.X makefile (gcc, + creates libpng12.so.0.1.2.7) + makefile.so9 => Solaris 9 makefile (gcc, + creates libpng12.so.0.1.2.7) + makefile.32sunu => Sun Ultra 32-bit makefile + makefile.64sunu => Sun Ultra 64-bit makefile + makefile.sco => For SCO OSr5 ELF and Unixware 7 with Native cc + makefile.mips => MIPS makefile + makefile.acorn => Acorn makefile + makefile.amiga => Amiga makefile + smakefile.ppc => AMIGA smakefile for SAS C V6.58/7.00 PPC compiler + (Requires SCOPTIONS, copied from scripts/SCOPTIONS.ppc) + makefile.atari => Atari makefile + makefile.beos => BEOS makefile for X86 + makefile.bor => Borland makefile (uses bcc) + makefile.bc32 => 32-bit Borland C++ (all modules compiled in C mode) + makefile.tc3 => Turbo C 3.0 makefile + makefile.dj2 => DJGPP 2 makefile + makefile.msc => Microsoft C makefile + makefile.vcawin32 => makefile for Microsoft Visual C++ 5.0 and later (uses + assembler code tuned for Intel MMX platform) + makefile.vcwin32 => makefile for Microsoft Visual C++ 4.0 and later (does + not use assembler code) + makefile.os2 => OS/2 Makefile (gcc and emx, requires pngos2.def) + pngos2.def => OS/2 module definition file used by makefile.os2 + makefile.watcom => Watcom 10a+ Makefile, 32-bit flat memory model + makevms.com => VMS build script + descrip.mms => VMS makefile for MMS or MMK + SCOPTIONS.ppc => Used with smakefile.ppc + +Copy the file (or files) that you need from the +scripts directory into this directory, for example + + MSDOS example: copy scripts\makefile.msc makefile + UNIX example: cp scripts/makefile.std makefile + +Read the makefile to see if you need to change any source or +target directories to match your preferences. + +Then read pngconf.h to see if you want to make any configuration +changes. + +Then just run "make" which will create the libpng library in +this directory and "make test" which will run a quick test that reads +the "pngtest.png" file and writes a "pngout.png" file that should be +identical to it. Look for "9782 zero samples" in the output of the +test. For more confidence, you can run another test by typing +"pngtest pngnow.png" and looking for "289 zero samples" in the output. +Also, you can run "pngtest -m contrib/pngsuite/*.png" and compare +your output with the result shown in contrib/pngsuite/README. + +Most of the makefiles will allow you to run "make install" to +put the library in its final resting place (if you want to +do that, run "make install" in the zlib directory first if necessary). +Some also allow you to run "make test-installed" after you have +run "make install". + +If you encounter a compiler error message complaining about the +lines + __png.h__ already includes setjmp.h; + __dont__ include it again.; +This means you have compiled another module that includes setjmp.h, +which is hazardous because the two modules might not include exactly +the same setjmp.h. If you are sure that you know what you are doing +and that they are exactly the same, then you can comment out or +delete the two lines. Better yet, use the cexcept interface +instead, as demonstrated in contrib/visupng of the libpng distribution. + +Further information can be found in the README and libpng.txt +files, in the individual makefiles, in png.h, and the manual pages +libpng.3 and png.5. diff --git a/Utilities/FLTK/png/KNOWNBUG b/Utilities/FLTK/png/KNOWNBUG new file mode 100644 index 0000000000..5323527002 --- /dev/null +++ b/Utilities/FLTK/png/KNOWNBUG @@ -0,0 +1,11 @@ + +Known bugs in libpng version 1.2.7 + +1. April 22, 2001: pnggccrd.c has been reported to crash on NetBSD when + reading interlaced PNG files, when assembler code is enabled but running + on a non-MMX i386 platform. + + STATUS: Under investigation. The change to pnggccrd.c in libpng-1.2.1 + fixed a problem under FreeBSD but not the problem with NetBSD, which + still fails as of libpng-1.2.2rc1. + diff --git a/Utilities/FLTK/png/LICENSE b/Utilities/FLTK/png/LICENSE new file mode 100644 index 0000000000..3e5a36abb9 --- /dev/null +++ b/Utilities/FLTK/png/LICENSE @@ -0,0 +1,109 @@ + +This copy of the libpng notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file png.h that is +included in the libpng distribution, the latter shall prevail. + +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + +If you modify libpng you may insert additional notices immediately following +this sentence. + +libpng version 1.2.6, September 12, 2004, is +Copyright (c) 2004 Glenn Randers-Pehrson, and is +distributed according to the same disclaimer and license as libpng-1.2.5 +with the following individual added to the list of Contributing Authors + + Cosmin Truta + +libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are +Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.0.6 +with the following individuals added to the list of Contributing Authors + + Simon-Pierre Cadieux + Eric S. Raymond + Gilles Vollant + +and with the following additions to the disclaimer: + + There is no warranty against interference with your enjoyment of the + library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is with + the user. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-0.96, +with the following individuals added to the list of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996, 1997 Andreas Dilger +Distributed according to the same disclaimer and license as libpng-0.88, +with the following individuals added to the list of Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing Authors +and Group 42, Inc. disclaim all warranties, expressed or implied, +including, without limitation, the warranties of merchantability and of +fitness for any purpose. The Contributing Authors and Group 42, Inc. +assume no liability for direct, indirect, incidental, special, exemplary, +or consequential damages, which may result from the use of the PNG +Reference Library, even if advised of the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + +1. The origin of this source code must not be misrepresented. + +2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. + +3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, without +fee, and encourage the use of this source code as a component to +supporting the PNG file format in commercial products. If you use this +source code in a product, acknowledgment is not required but would be +appreciated. + + +A "png_get_copyright" function is available, for convenient use in "about" +boxes and the like: + + printf("%s",png_get_copyright(NULL)); + +Also, the PNG logo (in PNG format, of course) is supplied in the +files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + +Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a +certification mark of the Open Source Initiative. + +Glenn Randers-Pehrson +glennrp@users.sourceforge.net +September 12, 2004 diff --git a/Utilities/FLTK/png/Makefile b/Utilities/FLTK/png/Makefile new file mode 100644 index 0000000000..bdd48526fd --- /dev/null +++ b/Utilities/FLTK/png/Makefile @@ -0,0 +1,107 @@ +# +# "$Id: Makefile 4052 2005-02-24 21:55:12Z mike $" +# +# PNG library makefile for the Fast Light Toolkit (FLTK). +# +# Copyright 1997-2005 by Easy Software Products. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. +# +# Please report all bugs and problems to "fltk-bugs@fltk.org". +# + +include ../makeinclude + +# +# Object files... +# + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +LIBPNG = ../lib/libfltk_png$(LIBEXT) + + +# +# Make all of the targets... +# + +all: $(LIBPNG) + + +# +# Clean all of the targets and object files... +# + +clean: + $(RM) $(OBJS) + $(RM) $(LIBPNG) + + +# +# Install everything... +# + +install: $(LIBPNG) + echo "Installing libfltk_png$(LIBEXT) in $(libdir)..." + -$(MKDIR) $(libdir) + $(RM) $(libdir)/libfltk_png$(LIBEXT) + $(CP) $(LIBPNG) $(libdir) + $(RANLIB) $(libdir)/libfltk_png$(LIBEXT) + echo "Installing png headers in $(includedir)/FL/images..." + -$(MKDIR) $(includedir)/FL/images + $(CP) png.h pngconf.h $(includedir)/FL/images + + +# +# Uninstall everything... +# + +uninstall: + echo "Uninstalling libfltk_png$(LIBEXT) in $(libdir)..." + $(RM) $(libdir)/libfltk_png$(LIBEXT) + echo "Uninstalling png headers in $(includedir)/FL/images..." + $(RM) $(includedir)/FL/images/png.h + $(RM) $(includedir)/FL/images/pngconf.h + + +# +# libfltk_png.a +# + +$(LIBPNG): $(OBJS) + echo Archiving $@... + $(RM) $@ + $(LIBCOMMAND) $@ $(OBJS) + $(RANLIB) $@ + + +# +# Make dependencies... +# + +depend: $(OBJS:.o=.c) + makedepend -Y -I.. -f makedepend $(OBJS:.o=.c) + +include makedepend + +$(OBJS): ../makeinclude + + +# +# End of "$Id: Makefile 4052 2005-02-24 21:55:12Z mike $". +# diff --git a/Utilities/FLTK/png/README b/Utilities/FLTK/png/README new file mode 100644 index 0000000000..7109660f13 --- /dev/null +++ b/Utilities/FLTK/png/README @@ -0,0 +1,260 @@ +README for libpng version 1.2.7 - September 12, 2004 (shared library 12.0) +See the note about version numbers near the top of png.h + +See INSTALL for instructions on how to install libpng. + +Libpng comes in several distribution formats. Get libpng-*.tar.gz +or libpng-*.tar.bz2 if you want UNIX-style line endings in the text +files, or lpng*.zip if you want DOS-style line endings. + +Version 0.89 was the first official release of libpng. Don't let the +fact that it's the first release fool you. The libpng library has been in +extensive use and testing since mid-1995. By late 1997 it had +finally gotten to the stage where there hadn't been significant +changes to the API in some time, and people have a bad feeling about +libraries with versions < 1.0. Version 1.0.0 was released in +March 1998. + +**** +Note that some of the changes to the png_info structure render this +version of the library binary incompatible with libpng-0.89 or +earlier versions if you are using a shared library. The type of the +"filler" parameter for png_set_filler() has changed from png_byte to +png_uint_32, which will affect shared-library applications that use +this function. + +To avoid problems with changes to the internals of png_info_struct, +new APIs have been made available in 0.95 to avoid direct application +access to info_ptr. These functions are the png_set_<chunk> and +png_get_<chunk> functions. These functions should be used when +accessing/storing the info_struct data, rather than manipulating it +directly, to avoid such problems in the future. + +It is important to note that the APIs do not make current programs +that access the info struct directly incompatible with the new +library. However, it is strongly suggested that new programs use +the new APIs (as shown in example.c and pngtest.c), and older programs +be converted to the new format, to facilitate upgrades in the future. +**** + +Additions since 0.90 include the ability to compile libpng as a +Windows DLL, and new APIs for accessing data in the info struct. +Experimental functions include the ability to set weighting and cost +factors for row filter selection, direct reads of integers from buffers +on big-endian processors that support misaligned data access, faster +methods of doing alpha composition, and more accurate 16->8 bit color +conversion. + +The additions since 0.89 include the ability to read from a PNG stream +which has had some (or all) of the signature bytes read by the calling +application. This also allows the reading of embedded PNG streams that +do not have the PNG file signature. As well, it is now possible to set +the library action on the detection of chunk CRC errors. It is possible +to set different actions based on whether the CRC error occurred in a +critical or an ancillary chunk. + +The changes made to the library, and bugs fixed are based on discussions +on the PNG-implement mailing list +and not on material submitted privately to Guy, Andreas, or Glenn. They will +forward any good suggestions to the list. + +For a detailed description on using libpng, read libpng.txt. For +examples of libpng in a program, see example.c and pngtest.c. For usage +information and restrictions (what little they are) on libpng, see +png.h. For a description on using zlib (the compression library used by +libpng) and zlib's restrictions, see zlib.h + +I have included a general makefile, as well as several machine and +compiler specific ones, but you may have to modify one for your own needs. + +You should use zlib 1.0.4 or later to run this, but it MAY work with +versions as old as zlib 0.95. Even so, there are bugs in older zlib +versions which can cause the output of invalid compression streams for +some images. You will definitely need zlib 1.0.4 or later if you are +taking advantage of the MS-DOS "far" structure allocation for the small +and medium memory models. You should also note that zlib is a +compression library that is useful for more things than just PNG files. +You can use zlib as a drop-in replacement for fread() and fwrite() if +you are so inclined. + +zlib should be available at the same place that libpng is, or at. +ftp://ftp.info-zip.org/pub/infozip/zlib + +You may also want a copy of the PNG specification. It is available +as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find +these at http://www.libpng.org/pub/png/documents/ + +This code is currently being archived at libpng.sf.net in the +[DOWNLOAD] area, and on CompuServe, Lib 20 (PNG SUPPORT) +at GO GRAPHSUP. If you can't find it in any of those places, +e-mail me, and I'll help you find it. + +If you have any code changes, requests, problems, etc., please e-mail +them to me. Also, I'd appreciate any make files or project files, +and any modifications you needed to make to get libpng to compile, +along with a #define variable to tell what compiler/system you are on. +If you needed to add transformations to libpng, or wish libpng would +provide the image in a different way, drop me a note (and code, if +possible), so I can consider supporting the transformation. +Finally, if you get any warning messages when compiling libpng +(note: not zlib), and they are easy to fix, I'd appreciate the +fix. Please mention "libpng" somewhere in the subject line. Thanks. + +This release was created and will be supported by myself (of course +based in a large way on Guy's and Andreas' earlier work), and the PNG group. + +glennrp@users.sourceforge.net +png-implement@ccrc.wustl.edu (subscription required; write to +majordomo@ccrc.wustl.edu with "subscribe png-implement" in the message). + +You can't reach Guy, the original libpng author, at the addresses +given in previous versions of this document. He and Andreas will read mail +addressed to the png-implement list, however. + +Please do not send general questions about PNG. Send them to +the (png-list@ccrc.wustl.edu, subscription required, write to +majordomo@ccrc.wustl.edu with "subscribe png-list" in your message). +On the other hand, +please do not send libpng questions to that address, send them to me +or to the png-implement list. I'll +get them in the end anyway. If you have a question about something +in the PNG specification that is related to using libpng, send it +to me. Send me any questions that start with "I was using libpng, +and ...". If in doubt, send questions to me. I'll bounce them +to others, if necessary. + +Please do not send suggestions on how to change PNG. We have +been discussing PNG for nine years now, and it is official and +finished. If you have suggestions for libpng, however, I'll +gladly listen. Even if your suggestion is not used immediately, +it may be used later. + +Files in this distribution: + + ANNOUNCE => Announcement of this version, with recent changes + CHANGES => Description of changes between libpng versions + KNOWNBUG => List of known bugs and deficiencies + LICENSE => License to use and redistribute libpng + README => This file + TODO => Things not implemented in the current library + Y2KINFO => Statement of Y2K compliance + example.c => Example code for using libpng functions + libpng.3 => manual page for libpng (includes libpng.txt) + libpng.txt => Description of libpng and its functions + libpngpf.3 => manual page for libpng's private functions + png.5 => manual page for the PNG format + png.c => Basic interface functions common to library + png.h => Library function and interface declarations + pngconf.h => System specific library configuration + pngasmrd.h => Header file for assembler-coded functions + pngerror.c => Error/warning message I/O functions + pngget.c => Functions for retrieving info from struct + pngmem.c => Memory handling functions + pngbar.png => PNG logo, 88x31 + pngnow.png => PNG logo, 98x31 + pngpread.c => Progressive reading functions + pngread.c => Read data/helper high-level functions + pngrio.c => Lowest-level data read I/O functions + pngrtran.c => Read data transformation functions + pngrutil.c => Read data utility functions + pngset.c => Functions for storing data into the info_struct + pngtest.c => Library test program + pngtest.png => Library test sample image + pngtrans.c => Common data transformation functions + pngwio.c => Lowest-level write I/O functions + pngwrite.c => High-level write functions + pngwtran.c => Write data transformations + pngwutil.c => Write utility functions + contrib => Contributions + gregbook => source code for PNG reading and writing, from + Greg Roelofs' "PNG: The Definitive Guide", + O'Reilly, 1999 + msvctest => Builds and runs pngtest using a MSVC workspace + pngminus => Simple pnm2png and png2pnm programs + pngsuite => Test images + visupng => Contains a MSVC workspace for VisualPng + projects => Contains project files and workspaces for building DLL + beos => Contains a Beos workspace for building libpng + c5builder => Contains a Borland workspace for building libpng + and zlib + visualc6 => Contains a Microsoft Visual C++ (MSVC) workspace + for building libpng and zlib + netware.txt => Contains instructions for downloading a set of + project files for building libpng and zlib on + Netware. + wince.txt => Contains instructions for downloading a Microsoft + Visual C++ (Windows CD Toolkit) workspace for + building libpng and zlib on WindowsCE + scripts => Directory containing scripts for building libpng: + descrip.mms => VMS makefile for MMS or MMK + makefile.std => Generic UNIX makefile (cc, creates static libpng.a) + makefile.linux => Linux/ELF makefile + (gcc, creates libpng12.so.0.1.2.7) + makefile.gcmmx => Linux/ELF makefile + (gcc, creates libpng12.so.0.1.2.7, + uses assembler code tuned for Intel MMX platform) + makefile.gcc => Generic makefile (gcc, creates static libpng.a) + makefile.knr => Archaic UNIX Makefile that converts files with + ansi2knr (Requires ansi2knr.c from + ftp://ftp.cs.wisc.edu/ghost) + makefile.aix => AIX makefile + makefile.cygwin => Cygwin/gcc makefile + makefile.darwin => Darwin makefile + makefile.dec => DEC Alpha UNIX makefile + makefile.freebsd => FreeBSD makefile + makefile.hpgcc => HPUX makefile using gcc + makefile.hpux => HPUX (10.20 and 11.00) makefile + makefile.hp64 => HPUX (10.20 and 11.00) makefile, 64 bit + makefile.ibmc => IBM C/C++ version 3.x for Win32 and OS/2 (static) + makefile.intel => Intel C/C++ version 4.0 and later + libpng.icc => Project file, IBM VisualAge/C++ 4.0 or later + makefile.netbsd => NetBSD/cc makefile, PNGGCCRD, makes libpng.so. + makefile.ne12bsd => NetBSD/cc makefile, PNGGCCRD, makes libpng12.so + makefile.openbsd => OpenBSD makefile + makefile.sgi => Silicon Graphics IRIX (cc, creates static lib) + makefile.sggcc => Silicon Graphics + (gcc, creates libpng12.so.0.1.2.7) + makefile.sunos => Sun makefile + makefile.solaris => Solaris 2.X makefile + (gcc, creates libpng12.so.0.1.2.7) + makefile.so9 => Solaris 9 makefile + (gcc, creates libpng12.so.0.1.2.7) + makefile.32sunu => Sun Ultra 32-bit makefile + makefile.64sunu => Sun Ultra 64-bit makefile + makefile.sco => For SCO OSr5 ELF and Unixware 7 with Native cc + makefile.mips => MIPS makefile + makefile.acorn => Acorn makefile + makefile.amiga => Amiga makefile + smakefile.ppc => AMIGA smakefile for SAS C V6.58/7.00 PPC + compiler (Requires SCOPTIONS, copied from + scripts/SCOPTIONS.ppc) + makefile.atari => Atari makefile + makefile.beos => BEOS makefile for X86 + makefile.bor => Borland makefile (uses bcc) + makefile.bc32 => 32-bit Borland C++ (all modules compiled in C mode) + makefile.tc3 => Turbo C 3.0 makefile + makefile.dj2 => DJGPP 2 makefile + makefile.msc => Microsoft C makefile + makefile.vcawin32=> makefile for Microsoft Visual C++ 5.0 and + later (uses assembler code tuned for Intel MMX + platform) + makefile.vcwin32 => makefile for Microsoft Visual C++ 4.0 and + later (does not use assembler code) + makefile.os2 => OS/2 Makefile (gcc and emx, requires pngos2.def) + pngos2.def => OS/2 module definition file used by makefile.os2 + makefile.watcom => Watcom 10a+ Makefile, 32-bit flat memory model + makevms.com => VMS build script + SCOPTIONS.ppc => Used with smakefile.ppc + +Good luck, and happy coding. + +-Glenn Randers-Pehrson (current maintainer) + Internet: glennrp@users.sourceforge.net + +-Andreas Eric Dilger (former maintainer, 1996-1997) + Internet: adilger@enel.ucalgary.ca + Web: http://www-mddsp.enel.ucalgary.ca/People/adilger/ + +-Guy Eric Schalnat (original author and former maintainer, 1995-1996) + (formerly of Group 42, Inc) + Internet: gschal@infinet.com diff --git a/Utilities/FLTK/png/TODO b/Utilities/FLTK/png/TODO new file mode 100644 index 0000000000..a5f639577d --- /dev/null +++ b/Utilities/FLTK/png/TODO @@ -0,0 +1,24 @@ +TODO - list of things to do for libpng: + +Final bug fixes. +Improve API by hiding the png_struct and png_info structs. +Finish work on the no-floating-point version (including gamma compensation) +Better C++ wrapper/full C++ implementation? +Fix problem with C++ and EXTERN "C". +cHRM transformation. +Improve setjmp/longjmp usage or remove it in favor of returning error codes. +Add "grayscale->palette" transformation and "palette->grayscale" detection. +Improved dithering. +Multi-lingual error and warning message support. +Complete sRGB transformation (presently it simply uses gamma=0.45455). +Man pages for function calls. +Better documentation. +Better filter selection + (counting huffman bits/precompression? filter inertia? filter costs?). +Histogram creation. +Text conversion between different code pages (Latin-1 -> Mac and DOS). +Should we always malloc 2^bit_depth PLTE/tRNS/hIST entries for safety? +Build gamma tables using fixed point (and do away with floating point entirely). +Use greater precision when changing to linear gamma for compositing against + background and doing rgb-to-gray transformation. +Investigate pre-incremented loop counters and other loop constructions. diff --git a/Utilities/FLTK/png/Y2KINFO b/Utilities/FLTK/png/Y2KINFO new file mode 100644 index 0000000000..5d1f2f7ac9 --- /dev/null +++ b/Utilities/FLTK/png/Y2KINFO @@ -0,0 +1,55 @@ + Y2K compliance in libpng: + ========================= + + September 12, 2004 + + Since the PNG Development group is an ad-hoc body, we can't make + an official declaration. + + This is your unofficial assurance that libpng from version 0.71 and + upward through 1.2.7 are Y2K compliant. It is my belief that earlier + versions were also Y2K compliant. + + Libpng only has three year fields. One is a 2-byte unsigned integer + that will hold years up to 65535. The other two hold the date in text + format, and will hold years up to 9999. + + The integer is + "png_uint_16 year" in png_time_struct. + + The strings are + "png_charp time_buffer" in png_struct and + "near_time_buffer", which is a local character string in png.c. + + There are seven time-related functions: + + png_convert_to_rfc_1123() in png.c + (formerly png_convert_to_rfc_1152() in error) + png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c + png_convert_from_time_t() in pngwrite.c + png_get_tIME() in pngget.c + png_handle_tIME() in pngrutil.c, called in pngread.c + png_set_tIME() in pngset.c + png_write_tIME() in pngwutil.c, called in pngwrite.c + + All appear to handle dates properly in a Y2K environment. The + png_convert_from_time_t() function calls gmtime() to convert from system + clock time, which returns (year - 1900), which we properly convert to + the full 4-digit year. There is a possibility that applications using + libpng are not passing 4-digit years into the png_convert_to_rfc_1123() + function, or that they are incorrectly passing only a 2-digit year + instead of "year - 1900" into the png_convert_from_struct_tm() function, + but this is not under our control. The libpng documentation has always + stated that it works with 4-digit years, and the APIs have been + documented as such. + + The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned + integer to hold the year, and can hold years as large as 65535. + + zlib, upon which libpng depends, is also Y2K compliant. It contains + no date-related code. + + + Glenn Randers-Pehrson + libpng maintainer + PNG Development Group diff --git a/Utilities/FLTK/png/libpng.3 b/Utilities/FLTK/png/libpng.3 new file mode 100644 index 0000000000..0d4d82958f --- /dev/null +++ b/Utilities/FLTK/png/libpng.3 @@ -0,0 +1,4016 @@ +.TH LIBPNG 3 "September 12, 2004" +.SH NAME +libpng \- Portable Network Graphics (PNG) Reference Library 1.2.7 +.SH SYNOPSIS +\fI\fB + +\fB#include <png.h>\fP + +\fI\fB + +\fBpng_uint_32 png_access_version_number \fI(void\fP\fB);\fP + +\fI\fB + +\fBint png_check_sig (png_bytep \fP\fIsig\fP\fB, int \fInum\fP\fB);\fP + +\fI\fB + +\fBvoid png_chunk_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP + +\fI\fB + +\fBvoid png_chunk_warning (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fImessage\fP\fB);\fP + +\fI\fB + +\fBvoid png_convert_from_struct_tm (png_timep \fP\fIptime\fP\fB, struct tm FAR * \fIttime\fP\fB);\fP + +\fI\fB + +\fBvoid png_convert_from_time_t (png_timep \fP\fIptime\fP\fB, time_t \fIttime\fP\fB);\fP + +\fI\fB + +\fBpng_charp png_convert_to_rfc1123 (png_structp \fP\fIpng_ptr\fP\fB, png_timep \fIptime\fP\fB);\fP + +\fI\fB + +\fBpng_infop png_create_info_struct (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_structp png_create_read_struct (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarn_fn\fP\fB);\fP + +\fI\fB + +\fBpng_structp png_create_read_struct_2(png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fP\fIwarn_fn\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP + +\fI\fB + +\fBpng_structp png_create_write_struct (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarn_fn\fP\fB);\fP + +\fI\fB + +\fBpng_structp png_create_write_struct_2(png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fP\fIwarn_fn\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP + +\fI\fB + +\fBint png_debug(int \fP\fIlevel\fP\fB, png_const_charp \fImessage\fP\fB);\fP + +\fI\fB + +\fBint png_debug1(int \fP\fIlevel\fP\fB, png_const_charp \fP\fImessage\fP\fB, \fIp1\fP\fB);\fP + +\fI\fB + +\fBint png_debug2(int \fP\fIlevel\fP\fB, png_const_charp \fP\fImessage\fP\fB, \fP\fIp1\fP\fB, \fIp2\fP\fB);\fP + +\fI\fB + +\fBvoid png_destroy_info_struct (png_structp \fP\fIpng_ptr\fP\fB, png_infopp \fIinfo_ptr_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_destroy_read_struct (png_structpp \fP\fIpng_ptr_ptr\fP\fB, png_infopp \fP\fIinfo_ptr_ptr\fP\fB, png_infopp \fIend_info_ptr_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_destroy_write_struct (png_structpp \fP\fIpng_ptr_ptr\fP\fB, png_infopp \fIinfo_ptr_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP + +\fI\fB + +\fBvoid png_free (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fIptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_free_chunk_list (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_free_default(png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fIptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_free_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fInum\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_bit_depth (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_16p \fI*background\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_channels (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fP\fI*white_x\fP\fB, double \fP\fI*white_y\fP\fB, double \fP\fI*red_x\fP\fB, double \fP\fI*red_y\fP\fB, double \fP\fI*green_x\fP\fB, double \fP\fI*green_y\fP\fB, double \fP\fI*blue_x\fP\fB, double \fI*blue_y\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*white_x\fP\fB, png_uint_32 \fP\fI*white_y\fP\fB, png_uint_32 \fP\fI*red_x\fP\fB, png_uint_32 \fP\fI*red_y\fP\fB, png_uint_32 \fP\fI*green_x\fP\fB, png_uint_32 \fP\fI*green_y\fP\fB, png_uint_32 \fP\fI*blue_x\fP\fB, png_uint_32 \fI*blue_y\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_color_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_compression_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_copyright (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_error_ptr (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_filter_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_gAMA (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fI*file_gamma\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_gAMA_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fI*int_file_gamma\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_header_ver (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_header_version (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fI*hist\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charpp \fP\fIname\fP\fB, int \fP\fI*compression_type\fP\fB, png_charpp \fP\fIprofile\fP\fB, png_uint_32 \fI*proflen\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*width\fP\fB, png_uint_32 \fP\fI*height\fP\fB, int \fP\fI*bit_depth\fP\fB, int \fP\fI*color_type\fP\fB, int \fP\fI*interlace_type\fP\fB, int \fP\fI*compression_type\fP\fB, int \fI*filter_type\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_image_height (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_image_width (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_interlace_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_io_ptr (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_libpng_ver (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_mem_ptr(png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*offset_x\fP\fB, png_uint_32 \fP\fI*offset_y\fP\fB, int \fI*unit_type\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fI*purpose\fP\fB, png_int_32 \fP\fI*X0\fP\fB, png_int_32 \fP\fI*X1\fP\fB, int \fP\fI*type\fP\fB, int \fP\fI*nparams\fP\fB, png_charp \fP\fI*units\fP\fB, png_charpp \fI*params\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*res_x\fP\fB, png_uint_32 \fP\fI*res_y\fP\fB, int \fI*unit_type\fP\fB);\fP + +\fI\fB + +\fBfloat png_get_pixel_aspect_ratio (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pixels_per_meter (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_progressive_ptr (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_colorp \fP\fI*palette\fP\fB, int \fI*num_palette\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_rgb_to_gray_status (png_structp \fIpng_ptr) + +\fBpng_uint_32 png_get_rowbytes (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_bytepp png_get_rows (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fI*sig_bit\fP\fB);\fP + +\fI\fB + +\fBpng_bytep png_get_signature (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fI*splt_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_sRGB (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fI*intent\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_text (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fI*text_ptr\fP\fB, int \fI*num_text\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_timep \fI*mod_time\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fI*trans\fP\fB, int \fP\fI*num_trans\fP\fB, png_color_16p \fI*trans_values\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkpp \fIunknowns\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_user_chunk_ptr (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_user_height_max( png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_user_transform_ptr (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_user_width_max (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_valid (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIflag\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_x_offset_microns (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_x_offset_pixels (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_x_pixels_per_meter (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_y_offset_microns (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_y_offset_pixels (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_y_pixels_per_meter (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_compression_buffer_size (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBint png_handle_as_unknown (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIchunk_name\fP\fB);\fP + +\fI\fB + +\fBvoid png_init_io (png_structp \fP\fIpng_ptr\fP\fB, FILE \fI*fp\fP\fB);\fP + +\fI\fB + +\fBDEPRECATED: void png_info_init (png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBDEPRECATED: void png_info_init_2 (png_infopp \fP\fIptr_ptr\fP\fB, png_size_t \fIpng_info_struct_size\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_malloc (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_malloc_default(png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP + +\fI\fB + +\fBvoidp png_memcpy (png_voidp \fP\fIs1\fP\fB, png_voidp \fP\fIs2\fP\fB, png_size_t \fIsize\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_memcpy_check (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIs1\fP\fB, png_voidp \fP\fIs2\fP\fB, png_uint_32 \fIsize\fP\fB);\fP + +\fI\fB + +\fBvoidp png_memset (png_voidp \fP\fIs1\fP\fB, int \fP\fIvalue\fP\fB, png_size_t \fIsize\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_memset_check (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIs1\fP\fB, int \fP\fIvalue\fP\fB, png_uint_32 \fIsize\fP\fB);\fP + +\fI\fB + +\fBDEPRECATED: void png_permit_empty_plte (png_structp \fP\fIpng_ptr\fP\fB, int \fIempty_plte_permitted\fP\fB);\fP + +\fI\fB + +\fBvoid png_process_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIbuffer_size\fP\fB);\fP + +\fI\fB + +\fBvoid png_progressive_combine_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIold_row\fP\fB, png_bytep \fInew_row\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_destroy (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_infop \fIend_info_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_image (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fIimage\fP\fB);\fP + +\fI\fB + +\fBDEPRECATED: void png_read_init (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBDEPRECATED: void png_read_init_2 (png_structpp \fP\fIptr_ptr\fP\fB, png_const_charp \fP\fIuser_png_ver\fP\fB, png_size_t \fP\fIpng_struct_size\fP\fB, png_size_t \fIpng_info_size\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, png_voidp \fIparams\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fIdisplay_row\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_rows (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fP\fIrow\fP\fB, png_bytepp \fP\fIdisplay_row\fP\fB, png_uint_32 \fInum_rows\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_update_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fB#if \fI!defined(PNG_1_0_X) + +\fBvoid png_set_add_alpha (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, int \fIflags\fP\fB);\fP + +\fI\fB#endif + +\fI\fB + +\fBvoid png_set_background (png_structp \fP\fIpng_ptr\fP\fB, png_color_16p \fP\fIbackground_color\fP\fB, int \fP\fIbackground_gamma_code\fP\fB, int \fP\fIneed_expand\fP\fB, double \fIbackground_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_bgr (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_16p \fIbackground\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fP\fIwhite_x\fP\fB, double \fP\fIwhite_y\fP\fB, double \fP\fIred_x\fP\fB, double \fP\fIred_y\fP\fB, double \fP\fIgreen_x\fP\fB, double \fP\fIgreen_y\fP\fB, double \fP\fIblue_x\fP\fB, double \fIblue_y\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIwhite_x\fP\fB, png_uint_32 \fP\fIwhite_y\fP\fB, png_uint_32 \fP\fIred_x\fP\fB, png_uint_32 \fP\fIred_y\fP\fB, png_uint_32 \fP\fIgreen_x\fP\fB, png_uint_32 \fP\fIgreen_y\fP\fB, png_uint_32 \fP\fIblue_x\fP\fB, png_uint_32 \fIblue_y\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_level (png_structp \fP\fIpng_ptr\fP\fB, int \fIlevel\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_mem_level (png_structp \fP\fIpng_ptr\fP\fB, int \fImem_level\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_method (png_structp \fP\fIpng_ptr\fP\fB, int \fImethod\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_strategy (png_structp \fP\fIpng_ptr\fP\fB, int \fIstrategy\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_window_bits (png_structp \fP\fIpng_ptr\fP\fB, int \fIwindow_bits\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_crc_action (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIcrit_action\fP\fB, int \fIancil_action\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_dither (png_structp \fP\fIpng_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fP\fInum_palette\fP\fB, int \fP\fImaximum_colors\fP\fB, png_uint_16p \fP\fIhistogram\fP\fB, int \fIfull_dither\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_error_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarning_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_expand (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_filler (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, int \fIflags\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_filter (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fImethod\fP\fB, int \fIfilters\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_filter_heuristics (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIheuristic_method\fP\fB, int \fP\fInum_weights\fP\fB, png_doublep \fP\fIfilter_weights\fP\fB, png_doublep \fIfilter_costs\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_flush (png_structp \fP\fIpng_ptr\fP\fB, int \fInrows\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gamma (png_structp \fP\fIpng_ptr\fP\fB, double \fP\fIscreen_gamma\fP\fB, double \fIdefault_file_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gAMA (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fIfile_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gAMA_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIfile_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gray_1_2_4_to_8(png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gray_to_rgb (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fIhist\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIname\fP\fB, int \fP\fIcompression_type\fP\fB, png_charp \fP\fIprofile\fP\fB, png_uint_32 \fIproflen\fP\fB);\fP + +\fI\fB + +\fBint png_set_interlace_handling (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_invalid (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fImask\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_invert_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_invert_mono (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIwidth\fP\fB, png_uint_32 \fP\fIheight\fP\fB, int \fP\fIbit_depth\fP\fB, int \fP\fIcolor_type\fP\fB, int \fP\fIinterlace_type\fP\fB, int \fP\fIcompression_type\fP\fB, int \fIfilter_type\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_keep_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIkeep\fP\fB, png_bytep \fP\fIchunk_list\fP\fB, int \fInum_chunks\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_mem_fn(png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIoffset_x\fP\fB, png_uint_32 \fP\fIoffset_y\fP\fB, int \fIunit_type\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_packing (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_packswap (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_palette_to_rgb(png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIpurpose\fP\fB, png_int_32 \fP\fIX0\fP\fB, png_int_32 \fP\fIX1\fP\fB, int \fP\fItype\fP\fB, int \fP\fInparams\fP\fB, png_charp \fP\fIunits\fP\fB, png_charpp \fIparams\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIres_x\fP\fB, png_uint_32 \fP\fIres_y\fP\fB, int \fIunit_type\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_progressive_read_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIprogressive_ptr\fP\fB, png_progressive_info_ptr \fP\fIinfo_fn\fP\fB, png_progressive_row_ptr \fP\fIrow_fn\fP\fB, png_progressive_end_ptr \fIend_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fInum_palette\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_read_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIio_ptr\fP\fB, png_rw_ptr \fIread_data_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_read_status_fn (png_structp \fP\fIpng_ptr\fP\fB, png_read_status_ptr \fIread_row_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_read_user_transform_fn (png_structp \fP\fIpng_ptr\fP\fB, png_user_transform_ptr \fIread_user_transform_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_rgb_to_gray (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIerror_action\fP\fB, double \fP\fIred\fP\fB, double \fIgreen\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_rgb_to_gray_fixed (png_structp \fP\fIpng_ptr\fP\fB, int error_action png_fixed_point \fP\fIred\fP\fB, png_fixed_point \fIgreen\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_rows (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytepp \fIrow_pointers\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fIsig_bit\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIunit\fP\fB, double \fP\fIwidth\fP\fB, double \fIheight\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_shift (png_structp \fP\fIpng_ptr\fP\fB, png_color_8p \fItrue_bits\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sig_bytes (png_structp \fP\fIpng_ptr\fP\fB, int \fInum_bytes\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fP\fIsplt_ptr\fP\fB, int \fInum_spalettes\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sRGB (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fIintent\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sRGB_gAMA_and_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fIintent\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_strip_16 (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_strip_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_swap (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_swap_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_text (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fItext_ptr\fP\fB, int \fInum_text\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_timep \fImod_time\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fItrans\fP\fB, int \fP\fInum_trans\fP\fB, png_color_16p \fItrans_values\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_tRNS_to_alpha(png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_set_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkp \fP\fIunknowns\fP\fB, int \fP\fInum\fP\fB, int \fIlocation\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_unknown_chunk_location(png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIchunk\fP\fB, int \fIlocation\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_read_user_chunk_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIuser_chunk_ptr\fP\fB, png_user_chunk_ptr \fIread_user_chunk_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_user_limits (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIuser_width_max\fP\fB, png_uint_32 \fIuser_height_max\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_user_transform_info (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIuser_transform_ptr\fP\fB, int \fP\fIuser_transform_depth\fP\fB, int \fIuser_transform_channels\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_write_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIio_ptr\fP\fB, png_rw_ptr \fP\fIwrite_data_fn\fP\fB, png_flush_ptr \fIoutput_flush_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_write_status_fn (png_structp \fP\fIpng_ptr\fP\fB, png_write_status_ptr \fIwrite_row_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_write_user_transform_fn (png_structp \fP\fIpng_ptr\fP\fB, png_user_transform_ptr \fIwrite_user_transform_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_buffer_size(png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP + +\fI\fB + +\fBint png_sig_cmp (png_bytep \fP\fIsig\fP\fB, png_size_t \fP\fIstart\fP\fB, png_size_t \fInum_to_check\fP\fB);\fP + +\fI\fB + +\fBvoid png_start_read_image (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_warning (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fImessage\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_chunk (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_chunk_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_chunk_end (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_chunk_start (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_destroy (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_flush (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_image (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fIimage\fP\fB);\fP + +\fI\fB + +\fBDEPRECATED: void png_write_init (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBDEPRECATED: void png_write_init_2 (png_structpp \fP\fIptr_ptr\fP\fB, png_const_charp \fP\fIuser_png_ver\fP\fB, png_size_t \fP\fIpng_struct_size\fP\fB, png_size_t \fIpng_info_size\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_info_before_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, png_voidp \fIparams\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_rows (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fP\fIrow\fP\fB, png_uint_32 \fInum_rows\fP\fB);\fP + +\fI\fB + +\fBvoidpf png_zalloc (voidpf \fP\fIpng_ptr\fP\fB, uInt \fP\fIitems\fP\fB, uInt \fIsize\fP\fB);\fP + +\fI\fB + +\fBvoid png_zfree (voidpf \fP\fIpng_ptr\fP\fB, voidpf \fIptr\fP\fB);\fP + +\fI\fB + +.SH DESCRIPTION +The +.I libpng +library supports encoding, decoding, and various manipulations of +the Portable Network Graphics (PNG) format image files. It uses the +.IR zlib(3) +compression library. +Following is a copy of the libpng.txt file that accompanies libpng. +.SH LIBPNG.TXT +libpng.txt - A description on how to use and modify libpng + + libpng version 1.2.7 - September 12, 2004 + Updated and distributed by Glenn Randers-Pehrson + <glennrp@users.sourceforge.net> + Copyright (c) 1998-2004 Glenn Randers-Pehrson + For conditions of distribution and use, see copyright + notice in png.h. + + based on: + + libpng 1.0 beta 6 version 0.96 May 28, 1997 + Updated and distributed by Andreas Dilger + Copyright (c) 1996, 1997 Andreas Dilger + + libpng 1.0 beta 2 - version 0.88 January 26, 1996 + For conditions of distribution and use, see copyright + notice in png.h. Copyright (c) 1995, 1996 Guy Eric + Schalnat, Group 42, Inc. + + Updated/rewritten per request in the libpng FAQ + Copyright (c) 1995, 1996 Frank J. T. Wojcik + December 18, 1995 & January 20, 1996 + +.SH I. Introduction + +This file describes how to use and modify the PNG reference library +(known as libpng) for your own use. There are five sections to this +file: introduction, structures, reading, writing, and modification and +configuration notes for various special platforms. In addition to this +file, example.c is a good starting point for using the library, as +it is heavily commented and should include everything most people +will need. We assume that libpng is already installed; see the +INSTALL file for instructions on how to install libpng. + +Libpng was written as a companion to the PNG specification, as a way +of reducing the amount of time and effort it takes to support the PNG +file format in application programs. + +The PNG specification (second edition), November 2003, is available as +a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2003 (E)) at +<http://www.w3.org/TR/2003/REC-PNG-20031110/ +The W3C and ISO documents have identical technical content. + +The PNG-1.2 specification is available at +<http://www.libpng.org/pub/png/documents/> + +The PNG-1.0 specification is available +as RFC 2083 <http://www.libpng.org/pub/png/documents/> and as a +W3C Recommendation <http://www.w3.org/TR/REC.png.html>. Some +additional chunks are described in the special-purpose public chunks +documents at <http://www.libpng.org/pub/png/documents/>. + +Other information +about PNG, and the latest version of libpng, can be found at the PNG home +page, <http://www.libpng.org/pub/png/>. + +Most users will not have to modify the library significantly; advanced +users may want to modify it more. All attempts were made to make it as +complete as possible, while keeping the code easy to understand. +Currently, this library only supports C. Support for other languages +is being considered. + +Libpng has been designed to handle multiple sessions at one time, +to be easily modifiable, to be portable to the vast majority of +machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy +to use. The ultimate goal of libpng is to promote the acceptance of +the PNG file format in whatever way possible. While there is still +work to be done (see the TODO file), libpng should cover the +majority of the needs of its users. + +Libpng uses zlib for its compression and decompression of PNG files. +Further information about zlib, and the latest version of zlib, can +be found at the zlib home page, <http://www.info-zip.org/pub/infozip/zlib/>. +The zlib compression utility is a general purpose utility that is +useful for more than PNG files, and can be used without libpng. +See the documentation delivered with zlib for more details. +You can usually find the source files for the zlib utility wherever you +find the libpng source files. + +Libpng is thread safe, provided the threads are using different +instances of the structures. Each thread should have its own +png_struct and png_info instances, and thus its own image. +Libpng does not protect itself against two threads using the +same instance of a structure. Note: thread safety may be defeated +by use of some of the MMX assembler code in pnggccrd.c, which is only +compiled when the user defines PNG_THREAD_UNSAFE_OK. + +.SH II. Structures + +There are two main structures that are important to libpng, png_struct +and png_info. The first, png_struct, is an internal structure that +will not, for the most part, be used by a user except as the first +variable passed to every libpng function call. + +The png_info structure is designed to provide information about the +PNG file. At one time, the fields of png_info were intended to be +directly accessible to the user. However, this tended to cause problems +with applications using dynamically loaded libraries, and as a result +a set of interface functions for png_info (the png_get_*() and png_set_*() +functions) was developed. The fields of png_info are still available for +older applications, but it is suggested that applications use the new +interfaces if at all possible. + +Applications that do make direct access to the members of png_struct (except +for png_ptr->jmpbuf) must be recompiled whenever the library is updated, +and applications that make direct access to the members of png_info must +be recompiled if they were compiled or loaded with libpng version 1.0.6, +in which the members were in a different order. In version 1.0.7, the +members of the png_info structure reverted to the old order, as they were +in versions 0.97c through 1.0.5. Starting with version 2.0.0, both +structures are going to be hidden, and the contents of the structures will +only be accessible through the png_get/png_set functions. + +The png.h header file is an invaluable reference for programming with libpng. +And while I'm on the topic, make sure you include the libpng header file: + +#include <png.h> + +.SH III. Reading + +We'll now walk you through the possible functions to call when reading +in a PNG file sequentially, briefly explaining the syntax and purpose +of each one. See example.c and png.h for more detail. While +progressive reading is covered in the next section, you will still +need some of the functions discussed in this section to read a PNG +file. + +.SS Setup + +You will want to do the I/O initialization(*) before you get into libpng, +so if it doesn't work, you don't have much to undo. Of course, you +will also want to insure that you are, in fact, dealing with a PNG +file. Libpng provides a simple check to see if a file is a PNG file. +To use it, pass in the first 1 to 8 bytes of the file to the function +png_sig_cmp(), and it will return 0 if the bytes match the corresponding +bytes of the PNG signature, or nonzero otherwise. Of course, the more bytes +you pass in, the greater the accuracy of the prediction. + +If you are intending to keep the file pointer open for use in libpng, +you must ensure you don't read more than 8 bytes from the beginning +of the file, and you also have to make a call to png_set_sig_bytes_read() +with the number of bytes you read from the beginning. Libpng will +then only check the bytes (if any) that your program didn't read. + +(*): If you are not using the standard I/O functions, you will need +to replace them with custom functions. See the discussion under +Customizing libpng. + + + FILE *fp = fopen(file_name, "rb"); + if (!fp) + { + return (ERROR); + } + fread(header, 1, number, fp); + is_png = !png_sig_cmp(header, 0, number); + if (!is_png) + { + return (NOT_PNG); + } + + +Next, png_struct and png_info need to be allocated and initialized. In +order to ensure that the size of these structures is correct even with a +dynamically linked libpng, there are functions to initialize and +allocate the structures. We also pass the library version, optional +pointers to error handling functions, and a pointer to a data struct for +use by the error functions, if necessary (the pointer and functions can +be NULL if the default error handlers are to be used). See the section +on Changes to Libpng below regarding the old initialization functions. +The structure allocation functions quietly return NULL if they fail to +create the structure, so your application should check for that. + + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + if (!png_ptr) + return (ERROR); + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + return (ERROR); + } + + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + +If you want to use your own memory allocation routines, +define PNG_USER_MEM_SUPPORTED and use +png_create_read_struct_2() instead of png_create_read_struct(): + + png_structp png_ptr = png_create_read_struct_2 + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn, (png_voidp) + user_mem_ptr, user_malloc_fn, user_free_fn); + +The error handling routines passed to png_create_read_struct() +and the memory alloc/free routines passed to png_create_struct_2() +are only necessary if you are not using the libpng supplied error +handling and memory alloc/free functions. + +When libpng encounters an error, it expects to longjmp back +to your routine. Therefore, you will need to call setjmp and pass +your png_jmpbuf(png_ptr). If you read the file from different +routines, you will need to update the jmpbuf field every time you enter +a new routine that will call a png_*() function. + +See your documentation of setjmp/longjmp for your compiler for more +information on setjmp/longjmp. See the discussion on libpng error +handling in the Customizing Libpng section below for more information +on the libpng error handling. If an error occurs, and libpng longjmp's +back to your setjmp, you will want to call png_destroy_read_struct() to +free any memory. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + fclose(fp); + return (ERROR); + } + +If you would rather avoid the complexity of setjmp/longjmp issues, +you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +Now you need to set up the input code. The default for libpng is to +use the C function fread(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. If you wish to handle reading data in another +way, you need not call the png_init_io() function, but you must then +implement the libpng I/O methods discussed in the Customizing Libpng +section below. + + png_init_io(png_ptr, fp); + +If you had previously opened the file and read any of the signature from +the beginning in order to see if this was a PNG file, you need to let +libpng know that there are some bytes missing from the start of the file. + + png_set_sig_bytes(png_ptr, number); + +.SS Setting up callback code + +You can set up a callback function to handle any unknown chunks in the +input stream. You must supply the function + + read_chunk_callback(png_ptr ptr, + png_unknown_chunkp chunk); + { + /* The unknown chunk structure contains your + chunk data: */ + png_byte name[5]; + png_byte *data; + png_size_t size; + /* Note that libpng has already taken care of + the CRC handling */ + + /* put your code here. Return one of the + following: */ + + return (-n); /* chunk had an error */ + return (0); /* did not recognize */ + return (n); /* success */ + } + +(You can give your function another name that you like instead of +"read_chunk_callback") + +To inform libpng about your function, use + + png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, + read_chunk_callback); + +This names not only the callback function, but also a user pointer that +you can retrieve with + + png_get_user_chunk_ptr(png_ptr); + +At this point, you can set up a callback function that will be +called after each row has been read, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void read_row_callback(png_ptr ptr, png_uint_32 row, + int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "read_row_callback") + +To inform libpng about your function, use + + png_set_read_status_fn(png_ptr, read_row_callback); + +.SS Width and height limits + +The PNG specification allows the width and height of an image to be as +large as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns. +Since very few applications really need to process such large images, +we have imposed an arbitrary 1-million limit on rows and columns. +Larger images will be rejected immediately with a png_error() call. If +you wish to override this limit, you can use + + png_set_user_limits(png_ptr, width_max, height_max); + +to set your own limits, or use width_max = height_max = 0x7fffffffL +to allow all valid dimensions (libpng may reject some very large images +anyway because of potential buffer overflow conditions). + +You should put this statement after you create the PNG structure and +before calling png_read_info(), png_read_png(), or png_process_data(). +If you need to retrieve the limits that are being applied, use + + width_max = png_get_user_width_max(png_ptr); + height_max = png_get_user_height_max(png_ptr); + +.SS Unknown-chunk handling + +Now you get to set the way the library processes unknown chunks in the +input PNG stream. Both known and unknown chunks will be read. Normal +behavior is that known chunks will be parsed into information in +various info_ptr members; unknown chunks will be discarded. To change +this, you can call: + + png_set_keep_unknown_chunks(png_ptr, keep, + chunk_list, num_chunks); + keep - 0: do not handle as unknown + 1: do not keep + 2: keep only if safe-to-copy + 3: keep even if unsafe-to-copy + You can use these definitions: + PNG_HANDLE_CHUNK_AS_DEFAULT 0 + PNG_HANDLE_CHUNK_NEVER 1 + PNG_HANDLE_CHUNK_IF_SAFE 2 + PNG_HANDLE_CHUNK_ALWAYS 3 + chunk_list - list of chunks affected (a byte string, + five bytes per chunk, NULL or '\0' if + num_chunks is 0) + num_chunks - number of chunks affected; if 0, all + unknown chunks are affected. If nonzero, + only the chunks in the list are affected + +Unknown chunks declared in this way will be saved as raw data onto a +list of png_unknown_chunk structures. If a chunk that is normally +known to libpng is named in the list, it will be handled as unknown, +according to the "keep" directive. If a chunk is named in successive +instances of png_set_keep_unknown_chunks(), the final instance will +take precedence. The IHDR and IEND chunks should not be named in +chunk_list; if they are, libpng will process them normally anyway. + +.SS The high-level read interface + +At this point there are two ways to proceed; through the high-level +read interface, or through a sequence of low-level read operations. +You can use the high-level interface if (a) you are willing to read +the entire image into memory, and (b) the input transformations +you want to do are limited to the following set: + + PNG_TRANSFORM_IDENTITY No transformation + PNG_TRANSFORM_STRIP_16 Strip 16-bit samples to + 8 bits + PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel + PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit + samples to bytes + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_EXPAND Perform set_expand() + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + +(This excludes setting a background color, doing gamma transformation, +dithering, and setting filler.) If this is the case, simply do this: + + png_read_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the logical OR of +some set of transformation flags. This call is equivalent to png_read_info(), +followed the set of transformations indicated by the transform mask, +then png_read_image(), and finally png_read_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future input transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_read_png(). + +After you have called png_read_png(), you can retrieve the image data +with + + row_pointers = png_get_rows(png_ptr, info_ptr); + +where row_pointers is an array of pointers to the pixel data for each row: + + png_bytep row_pointers[height]; + +If you know your image size and pixel size ahead of time, you can allocate +row_pointers prior to calling png_read_png() with + + if (height > PNG_UINT_32_MAX/png_sizeof(png_byte)) + png_error (png_ptr, + "Image is too tall to process in memory"); + if (width > PNG_UINT_32_MAX/pixel_size) + png_error (png_ptr, + "Image is too wide to process in memory"); + row_pointers = png_malloc(png_ptr, + height*png_sizeof(png_bytep)); + for (int i=0; i<height, i++) + row_pointers[i]=png_malloc(png_ptr, + width*pixel_size); + png_set_rows(png_ptr, info_ptr, &row_pointers); + +Alternatively you could allocate your image in one big block and define +row_pointers[i] to point into the proper places in your block. + +If you use png_set_rows(), the application is responsible for freeing +row_pointers (and row_pointers[i], if they were separately allocated). + +If you don't allocate row_pointers ahead of time, png_read_png() will +do it, and it'll be free'ed when you call png_destroy_*(). + +.SS The low-level read interface + +If you are going the low-level route, you are now ready to read all +the file information up to the actual image data. You do this with a +call to png_read_info(). + + png_read_info(png_ptr, info_ptr); + +This will process all chunks up to but not including the image data. + +.SS Querying the info structure + +Functions are used to get the information from the info_ptr once it +has been read. Note that these fields may not be completely filled +in until png_read_end() has read the chunk data following the image. + + png_get_IHDR(png_ptr, info_ptr, &width, &height, + &bit_depth, &color_type, &interlace_type, + &compression_type, &filter_method); + + width - holds the width of the image + in pixels (up to 2^31). + height - holds the height of the image + in pixels (up to 2^31). + bit_depth - holds the bit depth of one of the + image channels. (valid values are + 1, 2, 4, 8, 16 and depend also on + the color_type. See also + significant bits (sBIT) below). + color_type - describes which color/alpha channels + are present. + PNG_COLOR_TYPE_GRAY + (bit depths 1, 2, 4, 8, 16) + PNG_COLOR_TYPE_GRAY_ALPHA + (bit depths 8, 16) + PNG_COLOR_TYPE_PALETTE + (bit depths 1, 2, 4, 8) + PNG_COLOR_TYPE_RGB + (bit_depths 8, 16) + PNG_COLOR_TYPE_RGB_ALPHA + (bit_depths 8, 16) + + PNG_COLOR_MASK_PALETTE + PNG_COLOR_MASK_COLOR + PNG_COLOR_MASK_ALPHA + + filter_method - (must be PNG_FILTER_TYPE_BASE + for PNG 1.0, and can also be + PNG_INTRAPIXEL_DIFFERENCING if + the PNG datastream is embedded in + a MNG-1.0 datastream) + compression_type - (must be PNG_COMPRESSION_TYPE_BASE + for PNG 1.0) + interlace_type - (PNG_INTERLACE_NONE or + PNG_INTERLACE_ADAM7) + Any or all of interlace_type, compression_type, of + filter_method can be NULL if you are + not interested in their values. + + channels = png_get_channels(png_ptr, info_ptr); + channels - number of channels of info for the + color type (valid values are 1 (GRAY, + PALETTE), 2 (GRAY_ALPHA), 3 (RGB), + 4 (RGB_ALPHA or RGB + filler byte)) + rowbytes = png_get_rowbytes(png_ptr, info_ptr); + rowbytes - number of bytes needed to hold a row + + signature = png_get_signature(png_ptr, info_ptr); + signature - holds the signature read from the + file (if any). The data is kept in + the same offset it would be if the + whole signature were read (i.e. if an + application had already read in 4 + bytes of signature before starting + libpng, the remaining 4 bytes would + be in signature[4] through signature[7] + (see png_set_sig_bytes())). + + + width = png_get_image_width(png_ptr, + info_ptr); + height = png_get_image_height(png_ptr, + info_ptr); + bit_depth = png_get_bit_depth(png_ptr, + info_ptr); + color_type = png_get_color_type(png_ptr, + info_ptr); + filter_method = png_get_filter_type(png_ptr, + info_ptr); + compression_type = png_get_compression_type(png_ptr, + info_ptr); + interlace_type = png_get_interlace_type(png_ptr, + info_ptr); + + +These are also important, but their validity depends on whether the chunk +has been read. The png_get_valid(png_ptr, info_ptr, PNG_INFO_<chunk>) and +png_get_<chunk>(png_ptr, info_ptr, ...) functions return non-zero if the +data has been read, or zero if it is missing. The parameters to the +png_get_<chunk> are set directly if they are simple data types, or a pointer +into the info_ptr is returned for any complex types. + + png_get_PLTE(png_ptr, info_ptr, &palette, + &num_palette); + palette - the palette for the file + (array of png_color) + num_palette - number of entries in the palette + + png_get_gAMA(png_ptr, info_ptr, &gamma); + gamma - the gamma the file is written + at (PNG_INFO_gAMA) + + png_get_sRGB(png_ptr, info_ptr, &srgb_intent); + srgb_intent - the rendering intent (PNG_INFO_sRGB) + The presence of the sRGB chunk + means that the pixel data is in the + sRGB color space. This chunk also + implies specific values of gAMA and + cHRM. + + png_get_iCCP(png_ptr, info_ptr, &name, + &compression_type, &profile, &proflen); + name - The profile name. + compression - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + profile - International Color Consortium color + profile data. May contain NULs. + proflen - length of profile data in bytes. + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, + red, green, and blue channels, + whichever are appropriate for the + given color type (png_color_16) + + png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, + &trans_values); + trans - array of transparent entries for + palette (PNG_INFO_tRNS) + trans_values - graylevel or color sample values of + the single transparent color for + non-paletted images (PNG_INFO_tRNS) + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + png_get_hIST(png_ptr, info_ptr, &hist); + (PNG_INFO_hIST) + hist - histogram of palette (array of + png_uint_16) + + png_get_tIME(png_ptr, info_ptr, &mod_time); + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_get_bKGD(png_ptr, info_ptr, &background); + background - background color (PNG_VALID_bKGD) + valid 16-bit red, green and blue + values, regardless of color_type + + num_comments = png_get_text(png_ptr, info_ptr, + &text_ptr, &num_text); + num_comments - number of comments + text_ptr - array of png_text holding image + comments + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + text_ptr[i].text - text comments for current + keyword. Can be empty. + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + text_ptr[i].lang - language of comment (empty + string for unknown). + text_ptr[i].lang_key - keyword in UTF-8 + (empty string for unknown). + num_text - number of comments (same as + num_comments; you can put NULL here + to avoid the duplication) + Note while png_set_text() will accept text, language, + and translated keywords that can be NULL pointers, the + structure returned by png_get_text will always contain + regular zero-terminated C strings. They might be + empty strings but they will never be NULL pointers. + + num_spalettes = png_get_sPLT(png_ptr, info_ptr, + &palette_ptr); + palette_ptr - array of palette structures holding + contents of one or more sPLT chunks + read. + num_spalettes - number of sPLT chunks read. + + png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, + &unit_type); + offset_x - positive offset from the left edge + of the screen + offset_y - positive offset from the top edge + of the screen + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, + &unit_type); + res_x - pixels/unit physical resolution in + x direction + res_y - pixels/unit physical resolution in + x direction + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_get_sCAL(png_ptr, info_ptr, &unit, &width, + &height) + unit - physical scale units (an integer) + width - width of a pixel in physical scale units + height - height of a pixel in physical scale units + (width and height are doubles) + + png_get_sCAL_s(png_ptr, info_ptr, &unit, &width, + &height) + unit - physical scale units (an integer) + width - width of a pixel in physical scale units + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + num_unknown_chunks = png_get_unknown_chunks(png_ptr, + info_ptr, &unknowns) + unknowns - array of png_unknown_chunk + structures holding unknown chunks + unknowns[i].name - name of unknown chunk + unknowns[i].data - data of unknown chunk + unknowns[i].size - size of unknown chunk's data + unknowns[i].location - position of chunk in file + + The value of "i" corresponds to the order in which the + chunks were read from the PNG file or inserted with the + png_set_unknown_chunks() function. + +The data from the pHYs chunk can be retrieved in several convenient +forms: + + res_x = png_get_x_pixels_per_meter(png_ptr, + info_ptr) + res_y = png_get_y_pixels_per_meter(png_ptr, + info_ptr) + res_x_and_y = png_get_pixels_per_meter(png_ptr, + info_ptr) + res_x = png_get_x_pixels_per_inch(png_ptr, + info_ptr) + res_y = png_get_y_pixels_per_inch(png_ptr, + info_ptr) + res_x_and_y = png_get_pixels_per_inch(png_ptr, + info_ptr) + aspect_ratio = png_get_pixel_aspect_ratio(png_ptr, + info_ptr) + + (Each of these returns 0 [signifying "unknown"] if + the data is not present or if res_x is 0; + res_x_and_y is 0 if res_x != res_y) + +The data from the oFFs chunk can be retrieved in several convenient +forms: + + x_offset = png_get_x_offset_microns(png_ptr, info_ptr); + y_offset = png_get_y_offset_microns(png_ptr, info_ptr); + x_offset = png_get_x_offset_inches(png_ptr, info_ptr); + y_offset = png_get_y_offset_inches(png_ptr, info_ptr); + + (Each of these returns 0 [signifying "unknown" if both + x and y are 0] if the data is not present or if the + chunk is present but the unit is the pixel) + +For more information, see the png_info definition in png.h and the +PNG specification for chunk contents. Be careful with trusting +rowbytes, as some of the transformations could increase the space +needed to hold a row (expand, filler, gray_to_rgb, etc.). +See png_read_update_info(), below. + +A quick word about text_ptr and num_text. PNG stores comments in +keyword/text pairs, one pair per chunk, with no limit on the number +of text chunks, and a 2^31 byte limit on their size. While there are +suggested keywords, there is no requirement to restrict the use to these +strings. It is strongly suggested that keywords and text be sensible +to humans (that's the point), so don't use abbreviations. Non-printing +symbols are not allowed. See the PNG specification for more details. +There is also no requirement to have text after the keyword. + +Keywords should be limited to 79 Latin-1 characters without leading or +trailing spaces, but non-consecutive spaces are allowed within the +keyword. It is possible to have the same keyword any number of times. +The text_ptr is an array of png_text structures, each holding a +pointer to a language string, a pointer to a keyword and a pointer to +a text string. The text string, language code, and translated +keyword may be empty or NULL pointers. The keyword/text +pairs are put into the array in the order that they are received. +However, some or all of the text chunks may be after the image, so, to +make sure you have read all the text chunks, don't mess with these +until after you read the stuff after the image. This will be +mentioned again below in the discussion that goes with png_read_end(). + +.SS Input transformations + +After you've read the header information, you can set up the library +to handle any special transformations of the image data. The various +ways to transform the data will be described in the order that they +should occur. This is important, as some of these change the color +type and/or bit depth of the data, and some others only work on +certain color types and bit depths. Even though each transformation +checks to see if it has data that it can do something with, you should +make sure to only enable a transformation if it will be valid for the +data. For example, don't swap red and blue on grayscale data. + +The colors used for the background and transparency values should be +supplied in the same format/depth as the current image data. They +are stored in the same format/depth as the image data in a bKGD or tRNS +chunk, so this is what libpng expects for this data. The colors are +transformed to keep in sync with the image data when an application +calls the png_read_update_info() routine (see below). + +Data will be decoded into the supplied row buffers packed into bytes +unless the library has been told to transform it into another format. +For example, 4 bit/pixel paletted or grayscale data will be returned +2 pixels/byte with the leftmost pixel in the high-order bits of the +byte, unless png_set_packing() is called. 8-bit RGB data will be stored +in RGB RGB RGB format unless png_set_filler() or png_set_add_alpha() +is called to insert filler bytes, either before or after each RGB triplet. +16-bit RGB data will be returned RRGGBB RRGGBB, with the most significant +byte of the color value first, unless png_set_strip_16() is called to +transform it to regular RGB RGB triplets, or png_set_filler|add alpha() +is called to insert filler bytes, either before or after each RRGGBB +triplet. Similarly, 8-bit or 16-bit grayscale data can be modified with +png_set_filler(), png_set_add_alpha(), or png_set_strip_16(). + +The following code transforms grayscale images of less than 8 to 8 bits, +changes paletted images to RGB, and adds a full alpha channel if there is +transparency information in a tRNS chunk. This is most useful on +grayscale images with bit depths of 2 or 4 or if there is a multiple-image +viewing application that wishes to treat all images in the same way. + + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png_ptr); + + if (color_type == PNG_COLOR_TYPE_GRAY && + bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr); + + if (png_get_valid(png_ptr, info_ptr, + PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); + +These three functions are actually aliases for png_set_expand(), added +in libpng version 1.0.4, with the function names expanded to improve code +readability. In some future version they may actually do different +things. + +PNG can have files with 16 bits per channel. If you only can handle +8 bits per channel, this will strip the pixels down to 8 bit. + + if (bit_depth == 16) + png_set_strip_16(png_ptr); + +If, for some reason, you don't need the alpha channel on an image, +and you want to remove it rather than combining it with the background +(but the image author certainly had in mind that you *would* combine +it with the background, so that's what you should probably do): + + if (color_type & PNG_COLOR_MASK_ALPHA) + png_set_strip_alpha(png_ptr); + +In PNG files, the alpha channel in an image +is the level of opacity. If you need the alpha channel in an image to +be the level of transparency instead of opacity, you can invert the +alpha channel (or the tRNS chunk data) after it's read, so that 0 is +fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit +images) is fully transparent, with + + png_set_invert_alpha(png_ptr); + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit +files. This code expands to 1 pixel per byte without changing the +values of the pixels: + + if (bit_depth < 8) + png_set_packing(png_ptr); + +PNG files have possible bit depths of 1, 2, 4, 8, and 16. All pixels +stored in a PNG image have been "scaled" or "shifted" up to the next +higher possible bit depth (e.g. from 5 bits/sample in the range [0,31] to +8 bits/sample in the range [0, 255]). However, it is also possible to +convert the PNG pixel data back to the original bit depth of the image. +This call reduces the pixels back down to the original bit depth: + + png_color_8p sig_bit; + + if (png_get_sBIT(png_ptr, info_ptr, &sig_bit)) + png_set_shift(png_ptr, sig_bit); + +PNG files store 3-color pixels in red, green, blue order. This code +changes the storage of the pixels to blue, green, red: + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_bgr(png_ptr); + +PNG files store RGB pixels packed into 3 or 6 bytes. This code expands them +into 4 or 8 bytes for windowing systems that need them in this format: + + if (color_type == PNG_COLOR_TYPE_RGB) + png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE); + +where "filler" is the 8 or 16-bit number to fill with, and the location is +either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether +you want the filler before the RGB or after. This transformation +does not affect images that already have full alpha channels. To add an +opaque alpha channel, use filler=0xff or 0xffff and PNG_FILLER_AFTER which +will generate RGBA pixels. + +Note that png_set_filler() does not change the color type. If you want +to do that, you can add a true alpha channel with + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY) + png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER); + +where "filler" contains the alpha value to assign to each pixel. +This function became available in libpng-1.2.7. + +If you are reading an image with an alpha channel, and you need the +data as ARGB instead of the normal PNG format RGBA: + + if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_swap_alpha(png_ptr); + +For some uses, you may want a grayscale image to be represented as +RGB. This code will do that conversion: + + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + +Conversely, you can convert an RGB or RGBA image to grayscale or grayscale +with alpha. + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_rgb_to_gray_fixed(png_ptr, error_action, + int red_weight, int green_weight); + + error_action = 1: silently do the conversion + error_action = 2: issue a warning if the original + image has any pixel where + red != green or red != blue + error_action = 3: issue an error and abort the + conversion if the original + image has any pixel where + red != green or red != blue + + red_weight: weight of red component times 100000 + green_weight: weight of green component times 100000 + If either weight is negative, default + weights (21268, 71514) are used. + +If you have set error_action = 1 or 2, you can +later check whether the image really was gray, after processing +the image rows, with the png_get_rgb_to_gray_status(png_ptr) function. +It will return a png_byte that is zero if the image was gray or +1 if there were any non-gray pixels. bKGD and sBIT data +will be silently converted to grayscale, using the green channel +data, regardless of the error_action setting. + +With red_weight+green_weight<=100000, +the normalized graylevel is computed: + + int rw = red_weight * 65536; + int gw = green_weight * 65536; + int bw = 65536 - (rw + gw); + gray = (rw*red + gw*green + bw*blue)/65536; + +The default values approximate those recommended in the Charles +Poynton's Color FAQ, <http://www.inforamp.net/~poynton/> +Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net + + Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + +Libpng approximates this with + + Y = 0.21268 * R + 0.7151 * G + 0.07217 * B + +which can be expressed with integers as + + Y = (6969 * R + 23434 * G + 2365 * B)/32768 + +The calculation is done in a linear colorspace, if the image gamma +is known. + +If you have a grayscale and you are using png_set_expand_depth(), +png_set_expand(), or png_set_gray_to_rgb to change to truecolor or to +a higher bit-depth, you must either supply the background color as a gray +value at the original file bit-depth (need_expand = 1) or else supply the +background color as an RGB triplet at the final, expanded bit depth +(need_expand = 0). Similarly, if you are reading a paletted image, you +must either supply the background color as a palette index (need_expand = 1) +or as an RGB triplet that may or may not be in the palette (need_expand = 0). + + png_color_16 my_background; + png_color_16p image_background; + + if (png_get_bKGD(png_ptr, info_ptr, &image_background)) + png_set_background(png_ptr, image_background, + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + else + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + +The png_set_background() function tells libpng to composite images +with alpha or simple transparency against the supplied background +color. If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid), +you may use this color, or supply another color more suitable for +the current display (e.g., the background color from a web page). You +need to tell libpng whether the color is in the gamma space of the +display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file +(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one +that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't +know why anyone would use this, but it's here). + +To properly display PNG images on any kind of system, the application needs +to know what the display gamma is. Ideally, the user will know this, and +the application will allow them to set it. One method of allowing the user +to set the display gamma separately for each system is to check for a +SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be +correctly set. + +Note that display_gamma is the overall gamma correction required to produce +pleasing results, which depends on the lighting conditions in the surrounding +environment. In a dim or brightly lit room, no compensation other than +the physical gamma exponent of the monitor is needed, while in a dark room +a slightly smaller exponent is better. + + double gamma, screen_gamma; + + if (/* We have a user-defined screen + gamma value */) + { + screen_gamma = user_defined_screen_gamma; + } + /* One way that applications can share the same + screen gamma value */ + else if ((gamma_str = getenv("SCREEN_GAMMA")) + != NULL) + { + screen_gamma = (double)atof(gamma_str); + } + /* If we don't have another value */ + else + { + screen_gamma = 2.2; /* A good guess for a + PC monitor in a bright office or a dim room */ + screen_gamma = 2.0; /* A good guess for a + PC monitor in a dark room */ + screen_gamma = 1.7 or 1.0; /* A good + guess for Mac systems */ + } + +The png_set_gamma() function handles gamma transformations of the data. +Pass both the file gamma and the current screen_gamma. If the file does +not have a gamma value, you can pass one anyway if you have an idea what +it is (usually 0.45455 is a good guess for GIF images on PCs). Note +that file gammas are inverted from screen gammas. See the discussions +on gamma in the PNG specification for an excellent description of what +gamma is, and why all applications should support it. It is strongly +recommended that PNG viewers support gamma correction. + + if (png_get_gAMA(png_ptr, info_ptr, &gamma)) + png_set_gamma(png_ptr, screen_gamma, gamma); + else + png_set_gamma(png_ptr, screen_gamma, 0.45455); + +If you need to reduce an RGB file to a paletted file, or if a paletted +file has more entries then will fit on your screen, png_set_dither() +will do that. Note that this is a simple match dither that merely +finds the closest color available. This should work fairly well with +optimized palettes, and fairly badly with linear color cubes. If you +pass a palette that is larger then maximum_colors, the file will +reduce the number of colors in the palette so it will fit into +maximum_colors. If there is a histogram, it will use it to make +more intelligent choices when reducing the palette. If there is no +histogram, it may not do as good a job. + + if (color_type & PNG_COLOR_MASK_COLOR) + { + if (png_get_valid(png_ptr, info_ptr, + PNG_INFO_PLTE)) + { + png_uint_16p histogram = NULL; + + png_get_hIST(png_ptr, info_ptr, + &histogram); + png_set_dither(png_ptr, palette, num_palette, + max_screen_colors, histogram, 1); + } + else + { + png_color std_color_cube[MAX_SCREEN_COLORS] = + { ... colors ... }; + + png_set_dither(png_ptr, std_color_cube, + MAX_SCREEN_COLORS, MAX_SCREEN_COLORS, + NULL,0); + } + } + +PNG files describe monochrome as black being zero and white being one. +The following code will reverse this (make black be one and white be +zero): + + if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY) + png_set_invert_mono(png_ptr); + +This function can also be used to invert grayscale and gray-alpha images: + + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_invert_mono(png_ptr); + +PNG files store 16 bit pixels in network byte order (big-endian, +ie. most significant bits first). This code changes the storage to the +other way (little-endian, i.e. least significant bits first, the +way PCs store them): + + if (bit_depth == 16) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_read_user_transform_fn(png_ptr, + read_transform_fn); + +You must supply the function + + void read_transform_fn(png_ptr ptr, row_info_ptr + row_info, png_bytep data) + +See pngtest.c for a working example. Your function will be called +after all of the other transformations have been processed. + +You can also set up a pointer to a user structure for use by your +callback function, and you can inform libpng that your transform +function will change the number of channels or bit depth with the +function + + png_set_user_transform_info(png_ptr, user_ptr, + user_depth, user_channels); + +The user's application, not libpng, is responsible for allocating and +freeing any memory required for the user structure. + +You can retrieve the pointer via the function +png_get_user_transform_ptr(). For example: + + voidp read_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +The last thing to handle is interlacing; this is covered in detail below, +but you must call the function here if you want libpng to handle expansion +of the interlaced image. + + number_of_passes = png_set_interlace_handling(png_ptr); + +After setting the transformations, libpng can update your png_info +structure to reflect any transformations you've requested with this +call. This is most useful to update the info structure's rowbytes +field so you can use it to allocate your image memory. This function +will also update your palette with the correct screen_gamma and +background if these have been given with the calls above. + + png_read_update_info(png_ptr, info_ptr); + +After you call png_read_update_info(), you can allocate any +memory you need to hold the image. The row data is simply +raw byte data for all forms of images. As the actual allocation +varies among applications, no example will be given. If you +are allocating one large chunk, you will need to build an +array of pointers to each row, as it will be needed for some +of the functions below. + +.SS Reading image data + +After you've allocated memory, you can read the image data. +The simplest way to do this is in one function call. If you are +allocating enough memory to hold the whole image, you can just +call png_read_image() and libpng will read in all the image data +and put it in the memory area supplied. You will need to pass in +an array of pointers to each row. + +This function automatically handles interlacing, so you don't need +to call png_set_interlace_handling() or call this function multiple +times, or any of that other stuff necessary with png_read_rows(). + + png_read_image(png_ptr, row_pointers); + +where row_pointers is: + + png_bytep row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to read in the whole image at once, you can +use png_read_rows() instead. If there is no interlacing (check +interlace_type == PNG_INTERLACE_NONE), this is simple: + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + +where row_pointers is the same as in the png_read_image() call. + +If you are doing this just one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + png_read_row(png_ptr, row_pointer, NULL); + +If the file is interlaced (interlace_type != 0 in the IHDR chunk), things +get somewhat harder. The only current (PNG Specification version 1.2) +interlacing type for PNG is (interlace_type == PNG_INTERLACE_ADAM7) +is a somewhat complicated 2D interlace scheme, known as Adam7, that +breaks down an image into seven smaller images of varying size, based +on an 8x8 grid. + +libpng can fill out those images or it can give them to you "as is". +If you want them filled out, there are two ways to do that. The one +mentioned in the PNG specification is to expand each pixel to cover +those pixels that have not been read yet (the "rectangle" method). +This results in a blocky image for the first pass, which gradually +smooths out as more pixels are read. The other method is the "sparkle" +method, where pixels are drawn only in their final locations, with the +rest of the image remaining whatever colors they were initialized to +before the start of the read. The first method usually looks better, +but tends to be slower, as there are more pixels to put in the rows. + +If you don't want libpng to handle the interlacing details, just call +png_read_rows() seven times to read in all seven images. Each of the +images is a valid image by itself, or they can all be combined on an +8x8 grid to form a single image (although if you intend to combine them +you would be far better off using the libpng interlace handling). + +The first pass will return an image 1/8 as wide as the entire image +(every 8th column starting in column 0) and 1/8 as high as the original +(every 8th row starting in row 0), the second will be 1/8 as wide +(starting in column 4) and 1/8 as high (also starting in row 0). The +third pass will be 1/4 as wide (every 4th pixel starting in column 0) and +1/8 as high (every 8th row starting in row 4), and the fourth pass will +be 1/4 as wide and 1/4 as high (every 4th column starting in column 2, +and every 4th row starting in row 0). The fifth pass will return an +image 1/2 as wide, and 1/4 as high (starting at column 0 and row 2), +while the sixth pass will be 1/2 as wide and 1/2 as high as the original +(starting in column 1 and row 0). The seventh and final pass will be as +wide as the original, and 1/2 as high, containing all of the odd +numbered scanlines. Phew! + +If you want libpng to expand the images, call this before calling +png_start_read_image() or png_read_update_info(): + + if (interlace_type == PNG_INTERLACE_ADAM7) + number_of_passes + = png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this +is seven, but may change if another interlace type is added. +This function can be called even if the file is not interlaced, +where it will return one pass. + +If you are not going to display the image after each pass, but are +going to wait until the entire image is read in, use the sparkle +effect. This effect is faster and the end result of either method +is exactly the same. If you are planning on displaying the image +after each pass, the "rectangle" effect is generally considered the +better looking one. + +If you only want the "sparkle" effect, just call png_read_rows() as +normal, with the third parameter NULL. Make sure you make pass over +the image number_of_passes times, and you don't change the data in the +rows between calls. You can change the locations of the data, just +not the data. Each pass only writes the pixels appropriate for that +pass, and assumes the data from previous passes is still valid. + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + +If you only want the first effect (the rectangles), do the same as +before except pass the row buffer in the third parameter, and leave +the second parameter NULL. + + png_read_rows(png_ptr, NULL, row_pointers, + number_of_rows); + +.SS Finishing a sequential read + +After you are finished reading the image through either the high- or +low-level interfaces, you can finish reading the file. If you are +interested in comments or time, which may be stored either before or +after the image data, you should pass the separate png_info struct if +you want to keep the comments from before and after the image +separate. If you are not interested, you can pass NULL. + + png_read_end(png_ptr, end_info); + +When you are done, you can free all memory allocated by libpng like this: + + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + mask - identifies data to be freed, a mask + containing the logical OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + seq - sequence number of item to be freed + (-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those +cases do nothing. The "seq" parameter is ignored if only one item +of the selected data type, such as PLTE, is allowed. If "seq" is not +-1, and multiple items are allowed for the data type identified in +the mask, such as text or sPLT, only the n'th item in the structure +is freed, where n is "seq". + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_zalloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + mask - which data elements are affected + same choices as in png_free_data() + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + +This function only affects data that has already been allocated. +You can call this function after reading the PNG data but before calling +any png_set_*() functions, to control whether the user or the png_set_*() +function is responsible for freeing any existing data that might be present, +and again after the png_set_*() functions to control whether the user +or png_destroy_*() is supposed to free the data. When the user assumes +responsibility for libpng-allocated data, the application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_zalloc() to allocate it. + +If you allocated your row_pointers in a single block, as suggested above in +the description of the high level read interface, you must not transfer +responsibility for freeing it to the png_set_rows or png_read_destroy function, +because they would also try to free the individual row_pointers[i]. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. + +The png_free_data() function will turn off the "valid" flag for anything +it frees. If you need to turn the flag off for a chunk that was freed by your +application instead of by libpng, you can use + + png_set_invalid(png_ptr, info_ptr, mask); + mask - identifies the chunks to be made invalid, + containing the logical OR of one or + more of + PNG_INFO_gAMA, PNG_INFO_sBIT, + PNG_INFO_cHRM, PNG_INFO_PLTE, + PNG_INFO_tRNS, PNG_INFO_bKGD, + PNG_INFO_hIST, PNG_INFO_pHYs, + PNG_INFO_oFFs, PNG_INFO_tIME, + PNG_INFO_pCAL, PNG_INFO_sRGB, + PNG_INFO_iCCP, PNG_INFO_sPLT, + PNG_INFO_sCAL, PNG_INFO_IDAT + +For a more compact example of reading a PNG image, see the file example.c. + +.SS Reading PNG files progressively + +The progressive reader is slightly different then the non-progressive +reader. Instead of calling png_read_info(), png_read_rows(), and +png_read_end(), you make one call to png_process_data(), which calls +callbacks when it has the info, a row, or the end of the image. You +set up these callbacks with png_set_progressive_read_fn(). You don't +have to worry about the input/output functions of libpng, as you are +giving the library the data directly in png_process_data(). I will +assume that you have read the section on reading PNG files above, +so I will only highlight the differences (although I will show +all of the code). + +png_structp png_ptr; +png_infop info_ptr; + + /* An example code fragment of how you would + initialize the progressive reader in your + application. */ + int + initialize_png_reader() + { + png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + if (!png_ptr) + return (ERROR); + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, (png_infopp)NULL, + (png_infopp)NULL); + return (ERROR); + } + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + + /* This one's new. You can provide functions + to be called when the header info is valid, + when each row is completed, and when the image + is finished. If you aren't using all functions, + you can specify NULL parameters. Even when all + three functions are NULL, you need to call + png_set_progressive_read_fn(). You can use + any struct as the user_ptr (cast to a void pointer + for the function call), and retrieve the pointer + from inside the callbacks using the function + + png_get_progressive_ptr(png_ptr); + + which will return a void pointer, which you have + to cast appropriately. + */ + png_set_progressive_read_fn(png_ptr, (void *)user_ptr, + info_callback, row_callback, end_callback); + + return 0; + } + + /* A code fragment that you call as you receive blocks + of data */ + int + process_data(png_bytep buffer, png_uint_32 length) + { + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + + /* This one's new also. Simply give it a chunk + of data from the file stream (in order, of + course). On machines with segmented memory + models machines, don't give it any more than + 64K. The library seems to run fine with sizes + of 4K. Although you can give it much less if + necessary (I assume you can give it chunks of + 1 byte, I haven't tried less then 256 bytes + yet). When this function returns, you may + want to display any rows that were generated + in the row callback if you don't already do + so there. + */ + png_process_data(png_ptr, info_ptr, buffer, length); + return 0; + } + + /* This function is called (as set by + png_set_progressive_read_fn() above) when enough data + has been supplied so all of the header has been + read. + */ + void + info_callback(png_structp png_ptr, png_infop info) + { + /* Do any setup here, including setting any of + the transformations mentioned in the Reading + PNG files section. For now, you _must_ call + either png_start_read_image() or + png_read_update_info() after all the + transformations are set (even if you don't set + any). You may start getting rows before + png_process_data() returns, so this is your + last chance to prepare for that. + */ + } + + /* This function is called when each row of image + data is complete */ + void + row_callback(png_structp png_ptr, png_bytep new_row, + png_uint_32 row_num, int pass) + { + /* If the image is interlaced, and you turned + on the interlace handler, this function will + be called for every row in every pass. Some + of these rows will not be changed from the + previous pass. When the row is not changed, + the new_row variable will be NULL. The rows + and passes are called in order, so you don't + really need the row_num and pass, but I'm + supplying them because it may make your life + easier. + + For the non-NULL rows of interlaced images, + you must call png_progressive_combine_row() + passing in the row and the old row. You can + call this function for NULL rows (it will just + return) and for non-interlaced images (it just + does the memcpy for you) if it will make the + code easier. Thus, you can just do this for + all cases: + */ + + png_progressive_combine_row(png_ptr, old_row, + new_row); + + /* where old_row is what was displayed for + previously for the row. Note that the first + pass (pass == 0, really) will completely cover + the old row, so the rows do not have to be + initialized. After the first pass (and only + for interlaced images), you will have to pass + the current row, and the function will combine + the old row and the new row. + */ + } + + void + end_callback(png_structp png_ptr, png_infop info) + { + /* This function is called after the whole image + has been read, including any chunks after the + image (up to and including the IEND). You + will usually have the same info chunk as you + had in the header, although some data may have + been added to the comments and time fields. + + Most people won't do much here, perhaps setting + a flag that marks the image as finished. + */ + } + + + +.SH IV. Writing + +Much of this is very similar to reading. However, everything of +importance is repeated here, so you won't have to constantly look +back up in the reading section to understand writing. + +.SS Setup + +You will want to do the I/O initialization before you get into libpng, +so if it doesn't work, you don't have anything to undo. If you are not +using the standard I/O functions, you will need to replace them with +custom writing functions. See the discussion under Customizing libpng. + + FILE *fp = fopen(file_name, "wb"); + if (!fp) + { + return (ERROR); + } + +Next, png_struct and png_info need to be allocated and initialized. +As these can be both relatively large, you may not want to store these +on the stack, unless you have stack space to spare. Of course, you +will want to check if they return NULL. If you are also reading, +you won't want to name your read structure and your write structure +both "png_ptr"; you can call them anything you like, such as +"read_ptr" and "write_ptr". Look at pngtest.c, for example. + + png_structp png_ptr = png_create_write_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + if (!png_ptr) + return (ERROR); + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, + (png_infopp)NULL); + return (ERROR); + } + +If you want to use your own memory allocation routines, +define PNG_USER_MEM_SUPPORTED and use +png_create_write_struct_2() instead of png_create_write_struct(): + + png_structp png_ptr = png_create_write_struct_2 + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn, (png_voidp) + user_mem_ptr, user_malloc_fn, user_free_fn); + +After you have these structures, you will need to set up the +error handling. When libpng encounters an error, it expects to +longjmp() back to your routine. Therefore, you will need to call +setjmp() and pass the png_jmpbuf(png_ptr). If you +write the file from different routines, you will need to update +the png_jmpbuf(png_ptr) every time you enter a new routine that will +call a png_*() function. See your documentation of setjmp/longjmp +for your compiler for more information on setjmp/longjmp. See +the discussion on libpng error handling in the Customizing Libpng +section below for more information on the libpng error handling. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + return (ERROR); + } + ... + return; + +If you would rather avoid the complexity of setjmp/longjmp issues, +you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +Now you need to set up the output code. The default for libpng is to +use the C function fwrite(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. Again, if you wish to handle writing data in +another way, see the discussion on libpng I/O handling in the Customizing +Libpng section below. + + png_init_io(png_ptr, fp); + +.SS Write callbacks + +At this point, you can set up a callback function that will be +called after each row has been written, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void write_row_callback(png_ptr, png_uint_32 row, + int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "write_row_callback") + +To inform libpng about your function, use + + png_set_write_status_fn(png_ptr, write_row_callback); + +You now have the option of modifying how the compression library will +run. The following functions are mainly for testing, but may be useful +in some cases, like if you need to write PNG files extremely fast and +are willing to give up some compression, or if you want to get the +maximum possible compression at the expense of slower writing. If you +have no special needs in this area, let the library do what it wants by +not calling this function at all, as it has been tuned to deliver a good +speed/compression ratio. The second parameter to png_set_filter() is +the filter method, for which the only valid values are 0 (as of the +July 1999 PNG specification, version 1.2) or 64 (if you are writing +a PNG datastream that is to be embedded in a MNG datastream). The third +parameter is a flag that indicates which filter type(s) are to be tested +for each scanline. See the PNG specification for details on the specific filter +types. + + + /* turn on or off filtering, and/or choose + specific filters. You can use either a single + PNG_FILTER_VALUE_NAME or the logical OR of one + or more PNG_FILTER_NAME masks. */ + png_set_filter(png_ptr, 0, + PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | + PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | + PNG_FILTER_UP | PNG_FILTER_VALUE_UP | + PNG_FILTER_AVE | PNG_FILTER_VALUE_AVE | + PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH| + PNG_ALL_FILTERS); + +If an application +wants to start and stop using particular filters during compression, +it should start out with all of the filters (to ensure that the previous +row of pixels will be stored in case it's needed later), and then add +and remove them after the start of compression. + +If you are writing a PNG datastream that is to be embedded in a MNG +datastream, the second parameter can be either 0 or 64. + +The png_set_compression_*() functions interface to the zlib compression +library, and should mostly be ignored unless you really know what you are +doing. The only generally useful call is png_set_compression_level() +which changes how much time zlib spends on trying to compress the image +data. See the Compression Library (zlib.h and algorithm.txt, distributed +with zlib) for details on the compression levels. + + /* set the zlib compression level */ + png_set_compression_level(png_ptr, + Z_BEST_COMPRESSION); + + /* set other zlib parameters */ + png_set_compression_mem_level(png_ptr, 8); + png_set_compression_strategy(png_ptr, + Z_DEFAULT_STRATEGY); + png_set_compression_window_bits(png_ptr, 15); + png_set_compression_method(png_ptr, 8); + png_set_compression_buffer_size(png_ptr, 8192) + +extern PNG_EXPORT(void,png_set_zbuf_size) + +.SS Setting the contents of info for output + +You now need to fill in the png_info structure with all the data you +wish to write before the actual image. Note that the only thing you +are allowed to write after the image is the text chunks and the time +chunk (as of PNG Specification 1.2, anyway). See png_write_end() and +the latest PNG specification for more information on that. If you +wish to write them before the image, fill them in now, and flag that +data as being valid. If you want to wait until after the data, don't +fill them until png_write_end(). For all the fields in png_info and +their data types, see png.h. For explanations of what the fields +contain, see the PNG specification. + +Some of the more important parts of the png_info are: + + png_set_IHDR(png_ptr, info_ptr, width, height, + bit_depth, color_type, interlace_type, + compression_type, filter_method) + width - holds the width of the image + in pixels (up to 2^31). + height - holds the height of the image + in pixels (up to 2^31). + bit_depth - holds the bit depth of one of the + image channels. + (valid values are 1, 2, 4, 8, 16 + and depend also on the + color_type. See also significant + bits (sBIT) below). + color_type - describes which color/alpha + channels are present. + PNG_COLOR_TYPE_GRAY + (bit depths 1, 2, 4, 8, 16) + PNG_COLOR_TYPE_GRAY_ALPHA + (bit depths 8, 16) + PNG_COLOR_TYPE_PALETTE + (bit depths 1, 2, 4, 8) + PNG_COLOR_TYPE_RGB + (bit_depths 8, 16) + PNG_COLOR_TYPE_RGB_ALPHA + (bit_depths 8, 16) + + PNG_COLOR_MASK_PALETTE + PNG_COLOR_MASK_COLOR + PNG_COLOR_MASK_ALPHA + + interlace_type - PNG_INTERLACE_NONE or + PNG_INTERLACE_ADAM7 + compression_type - (must be + PNG_COMPRESSION_TYPE_DEFAULT) + filter_method - (must be PNG_FILTER_TYPE_DEFAULT + or, if you are writing a PNG to + be embedded in a MNG datastream, + can also be + PNG_INTRAPIXEL_DIFFERENCING) + + png_set_PLTE(png_ptr, info_ptr, palette, + num_palette); + palette - the palette for the file + (array of png_color) + num_palette - number of entries in the palette + + png_set_gAMA(png_ptr, info_ptr, gamma); + gamma - the gamma the image was created + at (PNG_INFO_gAMA) + + png_set_sRGB(png_ptr, info_ptr, srgb_intent); + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of + the sRGB chunk means that the pixel + data is in the sRGB color space. + This chunk also implies specific + values of gAMA and cHRM. Rendering + intent is the CSS-1 property that + has been defined by the International + Color Consortium + (http://www.color.org). + It can be one of + PNG_sRGB_INTENT_SATURATION, + PNG_sRGB_INTENT_PERCEPTUAL, + PNG_sRGB_INTENT_ABSOLUTE, or + PNG_sRGB_INTENT_RELATIVE. + + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, + srgb_intent); + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of the + sRGB chunk means that the pixel + data is in the sRGB color space. + This function also causes gAMA and + cHRM chunks with the specific values + that are consistent with sRGB to be + written. + + png_set_iCCP(png_ptr, info_ptr, name, compression_type, + profile, proflen); + name - The profile name. + compression - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + profile - International Color Consortium color + profile data. May contain NULs. + proflen - length of profile data in bytes. + + png_set_sBIT(png_ptr, info_ptr, sig_bit); + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, red, + green, and blue channels, whichever are + appropriate for the given color type + (png_color_16) + + png_set_tRNS(png_ptr, info_ptr, trans, num_trans, + trans_values); + trans - array of transparent entries for + palette (PNG_INFO_tRNS) + trans_values - graylevel or color sample values of + the single transparent color for + non-paletted images (PNG_INFO_tRNS) + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + png_set_hIST(png_ptr, info_ptr, hist); + (PNG_INFO_hIST) + hist - histogram of palette (array of + png_uint_16) + + png_set_tIME(png_ptr, info_ptr, mod_time); + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_set_bKGD(png_ptr, info_ptr, background); + background - background color (PNG_VALID_bKGD) + + png_set_text(png_ptr, info_ptr, text_ptr, num_text); + text_ptr - array of png_text holding image + comments + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + text_ptr[i].text - text comments for current + keyword. Can be NULL or empty. + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + text_ptr[i].lang - language of comment (NULL or + empty for unknown). + text_ptr[i].translated_keyword - keyword in UTF-8 (NULL + or empty for unknown). + num_text - number of comments + + png_set_sPLT(png_ptr, info_ptr, &palette_ptr, + num_spalettes); + palette_ptr - array of png_sPLT_struct structures + to be added to the list of palettes + in the info structure. + num_spalettes - number of palette structures to be + added. + + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, + unit_type); + offset_x - positive offset from the left + edge of the screen + offset_y - positive offset from the top + edge of the screen + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, + unit_type); + res_x - pixels/unit physical resolution + in x direction + res_y - pixels/unit physical resolution + in y direction + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_set_sCAL(png_ptr, info_ptr, unit, width, height) + unit - physical scale units (an integer) + width - width of a pixel in physical scale units + height - height of a pixel in physical scale units + (width and height are doubles) + + png_set_sCAL_s(png_ptr, info_ptr, unit, width, height) + unit - physical scale units (an integer) + width - width of a pixel in physical scale units + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + png_set_unknown_chunks(png_ptr, info_ptr, &unknowns, + num_unknowns) + unknowns - array of png_unknown_chunk + structures holding unknown chunks + unknowns[i].name - name of unknown chunk + unknowns[i].data - data of unknown chunk + unknowns[i].size - size of unknown chunk's data + unknowns[i].location - position to write chunk in file + 0: do not write chunk + PNG_HAVE_IHDR: before PLTE + PNG_HAVE_PLTE: before IDAT + PNG_AFTER_IDAT: after IDAT + +The "location" member is set automatically according to +what part of the output file has already been written. +You can change its value after calling png_set_unknown_chunks() +as demonstrated in pngtest.c. Within each of the "locations", +the chunks are sequenced according to their position in the +structure (that is, the value of "i", which is the order in which +the chunk was either read from the input file or defined with +png_set_unknown_chunks). + +A quick word about text and num_text. text is an array of png_text +structures. num_text is the number of valid structures in the array. +Each png_text structure holds a language code, a keyword, a text value, +and a compression type. + +The compression types have the same valid numbers as the compression +types of the image data. Currently, the only valid number is zero. +However, you can store text either compressed or uncompressed, unlike +images, which always have to be compressed. So if you don't want the +text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE. +Because tEXt and zTXt chunks don't have a language field, if you +specify PNG_TEXT_COMPRESSION_NONE or PNG_TEXT_COMPRESSION_zTXt +any language code or translated keyword will not be written out. + +Until text gets around 1000 bytes, it is not worth compressing it. +After the text has been written out to the file, the compression type +is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR, +so that it isn't written out again at the end (in case you are calling +png_write_end() with the same struct. + +The keywords that are given in the PNG Specification are: + + Title Short (one line) title or + caption for image + Author Name of image's creator + Description Description of image (possibly long) + Copyright Copyright notice + Creation Time Time of original image creation + (usually RFC 1123 format, see below) + Software Software used to create the image + Disclaimer Legal disclaimer + Warning Warning of nature of content + Source Device used to create the image + Comment Miscellaneous comment; conversion + from other image format + +The keyword-text pairs work like this. Keywords should be short +simple descriptions of what the comment is about. Some typical +keywords are found in the PNG specification, as is some recommendations +on keywords. You can repeat keywords in a file. You can even write +some text before the image and some after. For example, you may want +to put a description of the image before the image, but leave the +disclaimer until after, so viewers working over modem connections +don't have to wait for the disclaimer to go over the modem before +they start seeing the image. Finally, keywords should be full +words, not abbreviations. Keywords and text are in the ISO 8859-1 +(Latin-1) character set (a superset of regular ASCII) and can not +contain NUL characters, and should not contain control or other +unprintable characters. To make the comments widely readable, stick +with basic ASCII, and avoid machine specific character set extensions +like the IBM-PC character set. The keyword must be present, but +you can leave off the text string on non-compressed pairs. +Compressed pairs must have a text string, as only the text string +is compressed anyway, so the compression would be meaningless. + +PNG supports modification time via the png_time structure. Two +conversion routines are provided, png_convert_from_time_t() for +time_t and png_convert_from_struct_tm() for struct tm. The +time_t routine uses gmtime(). You don't have to use either of +these, but if you wish to fill in the png_time structure directly, +you should provide the time in universal time (GMT) if possible +instead of your local time. Note that the year number is the full +year (e.g. 1998, rather than 98 - PNG is year 2000 compliant!), and +that months start with 1. + +If you want to store the time of the original image creation, you should +use a plain tEXt chunk with the "Creation Time" keyword. This is +necessary because the "creation time" of a PNG image is somewhat vague, +depending on whether you mean the PNG file, the time the image was +created in a non-PNG format, a still photo from which the image was +scanned, or possibly the subject matter itself. In order to facilitate +machine-readable dates, it is recommended that the "Creation Time" +tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"), +although this isn't a requirement. Unlike the tIME chunk, the +"Creation Time" tEXt chunk is not expected to be automatically changed +by the software. To facilitate the use of RFC 1123 dates, a function +png_convert_to_rfc1123(png_timep) is provided to convert from PNG +time to an RFC 1123 format string. + +.SS Writing unknown chunks + +You can use the png_set_unknown_chunks function to queue up chunks +for writing. You give it a chunk name, raw data, and a size; that's +all there is to it. The chunks will be written by the next following +png_write_info_before_PLTE, png_write_info, or png_write_end function. +Any chunks previously read into the info structure's unknown-chunk +list will also be written out in a sequence that satisfies the PNG +specification's ordering rules. + +.SS The high-level write interface + +At this point there are two ways to proceed; through the high-level +write interface, or through a sequence of low-level write operations. +You can use the high-level interface if your image data is present +in the info structure. All defined output +transformations are permitted, enabled by the following masks. + + PNG_TRANSFORM_IDENTITY No transformation + PNG_TRANSFORM_PACKING Pack 1, 2 and 4-bit samples + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + PNG_TRANSFORM_STRIP_FILLER Strip out filler bytes. + +If you have valid image data in the info structure (you can use +png_set_rows() to put image data in the info structure), simply do this: + + png_write_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the logical OR of some set of +transformation flags. This call is equivalent to png_write_info(), +followed the set of transformations indicated by the transform mask, +then png_write_image(), and finally png_write_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future output transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_write_png(). + +.SS The low-level write interface + +If you are going the low-level route instead, you are now ready to +write all the file information up to the actual image data. You do +this with a call to png_write_info(). + + png_write_info(png_ptr, info_ptr); + +Note that there is one transformation you may need to do before +png_write_info(). In PNG files, the alpha channel in an image is the +level of opacity. If your data is supplied as a level of +transparency, you can invert the alpha channel before you write it, so +that 0 is fully transparent and 255 (in 8-bit or paletted images) or +65535 (in 16-bit images) is fully opaque, with + + png_set_invert_alpha(png_ptr); + +This must appear before png_write_info() instead of later with the +other transformations because in the case of paletted images the tRNS +chunk data has to be inverted before the tRNS chunk is written. If +your image is not a paletted image, the tRNS data (which in such cases +represents a single color to be rendered as transparent) won't need to +be changed, and you can safely do this transformation after your +png_write_info() call. + +If you need to write a private chunk that you want to appear before +the PLTE chunk when PLTE is present, you can write the PNG info in +two steps, and insert code to write your own chunk between them: + + png_write_info_before_PLTE(png_ptr, info_ptr); + png_set_unknown_chunks(png_ptr, info_ptr, ...); + png_write_info(png_ptr, info_ptr); + +After you've written the file information, you can set up the library +to handle any special transformations of the image data. The various +ways to transform the data will be described in the order that they +should occur. This is important, as some of these change the color +type and/or bit depth of the data, and some others only work on +certain color types and bit depths. Even though each transformation +checks to see if it has data that it can do something with, you should +make sure to only enable a transformation if it will be valid for the +data. For example, don't swap red and blue on grayscale data. + +PNG files store RGB pixels packed into 3 or 6 bytes. This code tells +the library to strip input data that has 4 or 8 bytes per pixel down +to 3 or 6 bytes (or strip 2 or 4-byte grayscale+filler data to 1 or 2 +bytes per pixel). + + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); + +where the 0 is unused, and the location is either PNG_FILLER_BEFORE or +PNG_FILLER_AFTER, depending upon whether the filler byte in the pixel +is stored XRGB or RGBX. + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit files. +If the data is supplied at 1 pixel per byte, use this code, which will +correctly pack the pixels into a single byte: + + png_set_packing(png_ptr); + +PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. If your +data is of another bit depth, you can write an sBIT chunk into the +file so that decoders can recover the original data if desired. + + /* Set the true bit depth of the image data */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit.red = true_bit_depth; + sig_bit.green = true_bit_depth; + sig_bit.blue = true_bit_depth; + } + else + { + sig_bit.gray = true_bit_depth; + } + if (color_type & PNG_COLOR_MASK_ALPHA) + { + sig_bit.alpha = true_bit_depth; + } + + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + +If the data is stored in the row buffer in a bit depth other than +one supported by PNG (e.g. 3 bit data in the range 0-7 for a 4-bit PNG), +this will scale the values to appear to be the correct bit depth as +is required by PNG. + + png_set_shift(png_ptr, &sig_bit); + +PNG files store 16 bit pixels in network byte order (big-endian, +ie. most significant bits first). This code would be used if they are +supplied the other way (little-endian, i.e. least significant bits +first, the way PCs store them): + + if (bit_depth > 8) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +PNG files store 3 color pixels in red, green, blue order. This code +would be used if they are supplied as blue, green, red: + + png_set_bgr(png_ptr); + +PNG files describe monochrome as black being zero and white being +one. This code would be used if the pixels are supplied with this reversed +(black being one and white being zero): + + png_set_invert_mono(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_write_user_transform_fn(png_ptr, + write_transform_fn); + +You must supply the function + + void write_transform_fn(png_ptr ptr, row_info_ptr + row_info, png_bytep data) + +See pngtest.c for a working example. Your function will be called +before any of the other transformations are processed. + +You can also set up a pointer to a user structure for use by your +callback function. + + png_set_user_transform_info(png_ptr, user_ptr, 0, 0); + +The user_channels and user_depth parameters of this function are ignored +when writing; you can set them to zero as shown. + +You can retrieve the pointer via the function png_get_user_transform_ptr(). +For example: + + voidp write_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +It is possible to have libpng flush any pending output, either manually, +or automatically after a certain number of lines have been written. To +flush the output stream a single time call: + + png_write_flush(png_ptr); + +and to have libpng flush the output stream periodically after a certain +number of scanlines have been written, call: + + png_set_flush(png_ptr, nrows); + +Note that the distance between rows is from the last time png_write_flush() +was called, or the first row of the image if it has never been called. +So if you write 50 lines, and then png_set_flush 25, it will flush the +output on the next scanline, and every 25 lines thereafter, unless +png_write_flush() is called before 25 more lines have been written. +If nrows is too small (less than about 10 lines for a 640 pixel wide +RGB image) the image compression may decrease noticeably (although this +may be acceptable for real-time applications). Infrequent flushing will +only degrade the compression performance by a few percent over images +that do not use flushing. + +.SS Writing the image data + +That's it for the transformations. Now you can write the image data. +The simplest way to do this is in one function call. If you have the +whole image in memory, you can just call png_write_image() and libpng +will write the image. You will need to pass in an array of pointers to +each row. This function automatically handles interlacing, so you don't +need to call png_set_interlace_handling() or call this function multiple +times, or any of that other stuff necessary with png_write_rows(). + + png_write_image(png_ptr, row_pointers); + +where row_pointers is: + + png_byte *row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to write the whole image at once, you can +use png_write_rows() instead. If the file is not interlaced, +this is simple: + + png_write_rows(png_ptr, row_pointers, + number_of_rows); + +row_pointers is the same as in the png_write_image() call. + +If you are just writing one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + + png_write_row(png_ptr, row_pointer); + +When the file is interlaced, things can get a good deal more +complicated. The only currently (as of the PNG Specification +version 1.2, dated July 1999) defined interlacing scheme for PNG files +is the "Adam7" interlace scheme, that breaks down an +image into seven smaller images of varying size. libpng will build +these images for you, or you can do them yourself. If you want to +build them yourself, see the PNG specification for details of which +pixels to write when. + +If you don't want libpng to handle the interlacing details, just +use png_set_interlace_handling() and call png_write_rows() the +correct number of times to write all seven sub-images. + +If you want libpng to build the sub-images, call this before you start +writing any rows: + + number_of_passes = + png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this +is seven, but may change if another interlace type is added. + +Then write the complete image number_of_passes times. + + png_write_rows(png_ptr, row_pointers, + number_of_rows); + +As some of these rows are not used, and thus return immediately, +you may want to read about interlacing in the PNG specification, +and only update the rows that are actually used. + +.SS Finishing a sequential write + +After you are finished writing the image, you should finish writing +the file. If you are interested in writing comments or time, you should +pass an appropriately filled png_info pointer. If you are not interested, +you can pass NULL. + + png_write_end(png_ptr, info_ptr); + +When you are done, you can free all memory used by libpng like this: + + png_destroy_write_struct(&png_ptr, &info_ptr); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + mask - identifies data to be freed, a mask + containing the logical OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + seq - sequence number of item to be freed + (-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those +cases do nothing. The "seq" parameter is ignored if only one item +of the selected data type, such as PLTE, is allowed. If "seq" is not +-1, and multiple items are allowed for the data type identified in +the mask, such as text or sPLT, only the n'th item in the structure +is freed, where n is "seq". + +If you allocated data such as a palette that you passed +in to libpng with png_set_*, you must not free it until just before the call to +png_destroy_write_struct(). + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_zalloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + mask - which data elements are affected + same choices as in png_free_data() + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + +For example, to transfer responsibility for some data from a read structure +to a write structure, you could use + + png_data_freer(read_ptr, read_info_ptr, + PNG_USER_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + png_data_freer(write_ptr, write_info_ptr, + PNG_DESTROY_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + +thereby briefly reassigning responsibility for freeing to the user but +immediately afterwards reassigning it once more to the write_destroy +function. Having done this, it would then be safe to destroy the read +structure and continue to use the PLTE, tRNS, and hIST data in the write +structure. + +This function only affects data that has already been allocated. +You can call this function before calling after the png_set_*() functions +to control whether the user or png_destroy_*() is supposed to free the data. +When the user assumes responsibility for libpng-allocated data, the +application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_zalloc() to allocate it. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. +For a more compact example of writing a PNG image, see the file example.c. + +.SH V. Modifying/Customizing libpng: + +There are three issues here. The first is changing how libpng does +standard things like memory allocation, input/output, and error handling. +The second deals with more complicated things like adding new chunks, +adding new transformations, and generally changing how libpng works. +Both of those are compile-time issues; that is, they are generally +determined at the time the code is written, and there is rarely a need +to provide the user with a means of changing them. The third is a +run-time issue: choosing between and/or tuning one or more alternate +versions of computationally intensive routines; specifically, optimized +assembly-language (and therefore compiler- and platform-dependent) +versions. + +Memory allocation, input/output, and error handling + +All of the memory allocation, input/output, and error handling in libpng +goes through callbacks that are user-settable. The default routines are +in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively. To change +these functions, call the appropriate png_set_*_fn() function. + +Memory allocation is done through the functions png_malloc() +and png_free(). These currently just call the standard C functions. If +your pointers can't access more then 64K at a time, you will want to set +MAXSEG_64K in zlib.h. Since it is unlikely that the method of handling +memory allocation on a platform will change between applications, these +functions must be modified in the library at compile time. If you prefer +to use a different method of allocating and freeing data, you can use +png_create_read_struct_2() or png_create_write_struct_2() to register +your own functions as described above. +These functions also provide a void pointer that can be retrieved via + + mem_ptr=png_get_mem_ptr(png_ptr); + +Your replacement memory functions must have prototypes as follows: + + png_voidp malloc_fn(png_structp png_ptr, + png_size_t size); + void free_fn(png_structp png_ptr, png_voidp ptr); + +Your malloc_fn() must return NULL in case of failure. The png_malloc() +function will normally call png_error() if it receives a NULL from the +system memory allocator or from your replacement malloc_fn(). + +Input/Output in libpng is done through png_read() and png_write(), +which currently just call fread() and fwrite(). The FILE * is stored in +png_struct and is initialized via png_init_io(). If you wish to change +the method of I/O, the library supplies callbacks that you can set +through the function png_set_read_fn() and png_set_write_fn() at run +time, instead of calling the png_init_io() function. These functions +also provide a void pointer that can be retrieved via the function +png_get_io_ptr(). For example: + + png_set_read_fn(png_structp read_ptr, + voidp read_io_ptr, png_rw_ptr read_data_fn) + + png_set_write_fn(png_structp write_ptr, + voidp write_io_ptr, png_rw_ptr write_data_fn, + png_flush_ptr output_flush_fn); + + voidp read_io_ptr = png_get_io_ptr(read_ptr); + voidp write_io_ptr = png_get_io_ptr(write_ptr); + +The replacement I/O functions must have prototypes as follows: + + void user_read_data(png_structp png_ptr, + png_bytep data, png_size_t length); + void user_write_data(png_structp png_ptr, + png_bytep data, png_size_t length); + void user_flush_data(png_structp png_ptr); + +Supplying NULL for the read, write, or flush functions sets them back +to using the default C stream functions. It is an error to read from +a write stream, and vice versa. + +Error handling in libpng is done through png_error() and png_warning(). +Errors handled through png_error() are fatal, meaning that png_error() +should never return to its caller. Currently, this is handled via +setjmp() and longjmp() (unless you have compiled libpng with +PNG_SETJMP_NOT_SUPPORTED, in which case it is handled via PNG_ABORT()), +but you could change this to do things like exit() if you should wish. + +On non-fatal errors, png_warning() is called +to print a warning message, and then control returns to the calling code. +By default png_error() and png_warning() print a message on stderr via +fprintf() unless the library is compiled with PNG_NO_CONSOLE_IO defined +(because you don't want the messages) or PNG_NO_STDIO defined (because +fprintf() isn't available). If you wish to change the behavior of the error +functions, you will need to set up your own message callbacks. These +functions are normally supplied at the time that the png_struct is created. +It is also possible to redirect errors and warnings to your own replacement +functions after png_create_*_struct() has been called by calling: + + png_set_error_fn(png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warning_fn); + + png_voidp error_ptr = png_get_error_ptr(png_ptr); + +If NULL is supplied for either error_fn or warning_fn, then the libpng +default function will be used, calling fprintf() and/or longjmp() if a +problem is encountered. The replacement error functions should have +parameters as follows: + + void user_error_fn(png_structp png_ptr, + png_const_charp error_msg); + void user_warning_fn(png_structp png_ptr, + png_const_charp warning_msg); + +The motivation behind using setjmp() and longjmp() is the C++ throw and +catch exception handling methods. This makes the code much easier to write, +as there is no need to check every return code of every function call. +However, there are some uncertainties about the status of local variables +after a longjmp, so the user may want to be careful about doing anything after +setjmp returns non-zero besides returning itself. Consult your compiler +documentation for more details. For an alternative approach, you may wish +to use the "cexcept" facility (see http://cexcept.sourceforge.net). + +.SS Custom chunks + +If you need to read or write custom chunks, you may need to get deeper +into the libpng code. The library now has mechanisms for storing +and writing chunks of unknown type; you can even declare callbacks +for custom chunks. Hoewver, this may not be good enough if the +library code itself needs to know about interactions between your +chunk and existing `intrinsic' chunks. + +If you need to write a new intrinsic chunk, first read the PNG +specification. Acquire a first level of +understanding of how it works. Pay particular attention to the +sections that describe chunk names, and look at how other chunks were +designed, so you can do things similarly. Second, check out the +sections of libpng that read and write chunks. Try to find a chunk +that is similar to yours and use it as a template. More details can +be found in the comments inside the code. It is best to handle unknown +chunks in a generic method, via callback functions, instead of by +modifying libpng functions. + +If you wish to write your own transformation for the data, look through +the part of the code that does the transformations, and check out some of +the simpler ones to get an idea of how they work. Try to find a similar +transformation to the one you want to add and copy off of it. More details +can be found in the comments inside the code itself. + +.SS Configuring for 16 bit platforms + +You will want to look into zconf.h to tell zlib (and thus libpng) that +it cannot allocate more then 64K at a time. Even if you can, the memory +won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K. + +.SS Configuring for DOS + +For DOS users who only have access to the lower 640K, you will +have to limit zlib's memory usage via a png_set_compression_mem_level() +call. See zlib.h or zconf.h in the zlib library for more information. + +.SS Configuring for Medium Model + +Libpng's support for medium model has been tested on most of the popular +compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets +defined, and FAR gets defined to far in pngconf.h, and you should be +all set. Everything in the library (except for zlib's structure) is +expecting far data. You must use the typedefs with the p or pp on +the end for pointers (or at least look at them and be careful). Make +note that the rows of data are defined as png_bytepp, which is an +unsigned char far * far *. + +.SS Configuring for gui/windowing platforms: + +You will need to write new error and warning functions that use the GUI +interface, as described previously, and set them to be the error and +warning functions at the time that png_create_*_struct() is called, +in order to have them available during the structure initialization. +They can be changed later via png_set_error_fn(). On some compilers, +you may also have to change the memory allocators (png_malloc, etc.). + +.SS Configuring for compiler xxx: + +All includes for libpng are in pngconf.h. If you need to add/change/delete +an include, this is the place to do it. The includes that are not +needed outside libpng are protected by the PNG_INTERNAL definition, +which is only defined for those routines inside libpng itself. The +files in libpng proper only include png.h, which includes pngconf.h. + +.SS Configuring zlib: + +There are special functions to configure the compression. Perhaps the +most useful one changes the compression level, which currently uses +input compression values in the range 0 - 9. The library normally +uses the default compression level (Z_DEFAULT_COMPRESSION = 6). Tests +have shown that for a large majority of images, compression values in +the range 3-6 compress nearly as well as higher levels, and do so much +faster. For online applications it may be desirable to have maximum speed +(Z_BEST_SPEED = 1). With versions of zlib after v0.99, you can also +specify no compression (Z_NO_COMPRESSION = 0), but this would create +files larger than just storing the raw bitmap. You can specify the +compression level by calling: + + png_set_compression_level(png_ptr, level); + +Another useful one is to reduce the memory level used by the library. +The memory level defaults to 8, but it can be lowered if you are +short on memory (running DOS, for example, where you only have 640K). +Note that the memory level does have an effect on compression; among +other things, lower levels will result in sections of incompressible +data being emitted in smaller stored blocks, with a correspondingly +larger relative overhead of up to 15% in the worst case. + + png_set_compression_mem_level(png_ptr, level); + +The other functions are for configuring zlib. They are not recommended +for normal use and may result in writing an invalid PNG file. See +zlib.h for more information on what these mean. + + png_set_compression_strategy(png_ptr, + strategy); + png_set_compression_window_bits(png_ptr, + window_bits); + png_set_compression_method(png_ptr, method); + png_set_compression_buffer_size(png_ptr, size); + +.SS Controlling row filtering + +If you want to control whether libpng uses filtering or not, which +filters are used, and how it goes about picking row filters, you +can call one of these functions. The selection and configuration +of row filters can have a significant impact on the size and +encoding speed and a somewhat lesser impact on the decoding speed +of an image. Filtering is enabled by default for RGB and grayscale +images (with and without alpha), but not for paletted images nor +for any images with bit depths less than 8 bits/pixel. + +The 'method' parameter sets the main filtering method, which is +currently only '0' in the PNG 1.2 specification. The 'filters' +parameter sets which filter(s), if any, should be used for each +scanline. Possible values are PNG_ALL_FILTERS and PNG_NO_FILTERS +to turn filtering on and off, respectively. + +Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB, +PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise +ORed together with '|' to specify one or more filters to use. +These filters are described in more detail in the PNG specification. +If you intend to change the filter type during the course of writing +the image, you should start with flags set for all of the filters +you intend to use so that libpng can initialize its internal +structures appropriately for all of the filter types. (Note that this +means the first row must always be adaptively filtered, because libpng +currently does not allocate the filter buffers until png_write_row() +is called for the first time.) + + filters = PNG_FILTER_NONE | PNG_FILTER_SUB + PNG_FILTER_UP | PNG_FILTER_AVE | + PNG_FILTER_PAETH | PNG_ALL_FILTERS; + + png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, + filters); + The second parameter can also be + PNG_INTRAPIXEL_DIFFERENCING if you are + writing a PNG to be embedded in a MNG + datastream. This parameter must be the + same as the value of filter_method used + in png_set_IHDR(). + +It is also possible to influence how libpng chooses from among the +available filters. This is done in one or both of two ways - by +telling it how important it is to keep the same filter for successive +rows, and by telling it the relative computational costs of the filters. + + double weights[3] = {1.5, 1.3, 1.1}, + costs[PNG_FILTER_VALUE_LAST] = + {1.0, 1.3, 1.3, 1.5, 1.7}; + + png_set_filter_heuristics(png_ptr, + PNG_FILTER_HEURISTIC_WEIGHTED, 3, + weights, costs); + +The weights are multiplying factors that indicate to libpng that the +row filter should be the same for successive rows unless another row filter +is that many times better than the previous filter. In the above example, +if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a +"sum of absolute differences" 1.5 x 1.3 times higher than other filters +and still be chosen, while the NONE filter could have a sum 1.1 times +higher than other filters and still be chosen. Unspecified weights are +taken to be 1.0, and the specified weights should probably be declining +like those above in order to emphasize recent filters over older filters. + +The filter costs specify for each filter type a relative decoding cost +to be considered when selecting row filters. This means that filters +with higher costs are less likely to be chosen over filters with lower +costs, unless their "sum of absolute differences" is that much smaller. +The costs do not necessarily reflect the exact computational speeds of +the various filters, since this would unduly influence the final image +size. + +Note that the numbers above were invented purely for this example and +are given only to help explain the function usage. Little testing has +been done to find optimum values for either the costs or the weights. + +.SS Removing unwanted object code + +There are a bunch of #define's in pngconf.h that control what parts of +libpng are compiled. All the defines end in _SUPPORTED. If you are +never going to use a capability, you can change the #define to #undef +before recompiling libpng and save yourself code and data space, or +you can turn off individual capabilities with defines that begin with +PNG_NO_. + +You can also turn all of the transforms and ancillary chunk capabilities +off en masse with compiler directives that define +PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS, +or all four, +along with directives to turn on any of the capabilities that you do +want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable +the extra transformations but still leave the library fully capable of reading +and writing PNG files with all known public chunks +Use of the PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive +produces a library that is incapable of reading or writing ancillary chunks. +If you are not using the progressive reading capability, you can +turn that off with PNG_NO_PROGRESSIVE_READ (don't confuse +this with the INTERLACING capability, which you'll still have). + +All the reading and writing specific code are in separate files, so the +linker should only grab the files it needs. However, if you want to +make sure, or if you are building a stand alone library, all the +reading files start with pngr and all the writing files start with +pngw. The files that don't match either (like png.c, pngtrans.c, etc.) +are used for both reading and writing, and always need to be included. +The progressive reader is in pngpread.c + +If you are creating or distributing a dynamically linked library (a .so +or DLL file), you should not remove or disable any parts of the library, +as this will cause applications linked with different versions of the +library to fail if they call functions not available in your library. +The size of the library itself should not be an issue, because only +those sections that are actually used will be loaded into memory. + +.SS Requesting debug printout + +The macro definition PNG_DEBUG can be used to request debugging +printout. Set it to an integer value in the range 0 to 3. Higher +numbers result in increasing amounts of debugging information. The +information is printed to the "stderr" file, unless another file +name is specified in the PNG_DEBUG_FILE macro definition. + +When PNG_DEBUG > 0, the following functions (macros) become available: + + png_debug(level, message) + png_debug1(level, message, p1) + png_debug2(level, message, p1, p2) + +in which "level" is compared to PNG_DEBUG to decide whether to print +the message, "message" is the formatted string to be printed, +and p1 and p2 are parameters that are to be embedded in the string +according to printf-style formatting directives. For example, + + png_debug1(2, "foo=%d\n", foo); + +is expanded to + + if(PNG_DEBUG > 2) + fprintf(PNG_DEBUG_FILE, "foo=%d\n", foo); + +When PNG_DEBUG is defined but is zero, the macros aren't defined, but you +can still use PNG_DEBUG to control your own debugging: + + #ifdef PNG_DEBUG + fprintf(stderr, ... + #endif + +When PNG_DEBUG = 1, the macros are defined, but only png_debug statements +having level = 0 will be printed. There aren't any such statements in +this version of libpng, but if you insert some they will be printed. + +.SH VI. Runtime optimization + +A new feature in libpng 1.2.0 is the ability to dynamically switch between +standard and optimized versions of some routines. Currently these are +limited to three computationally intensive tasks when reading PNG files: +decoding row filters, expanding interlacing, and combining interlaced or +transparent row data with previous row data. Currently the optimized +versions are available only for x86 (Intel, AMD, etc.) platforms with +MMX support, though this may change in future versions. (For example, +the non-MMX assembler optimizations for zlib might become similarly +runtime-selectable in future releases, in which case libpng could be +extended to support them. Alternatively, the compile-time choice of +floating-point versus integer routines for gamma correction might become +runtime-selectable.) + +Because such optimizations tend to be very platform- and compiler-dependent, +both in how they are written and in how they perform, the new runtime code +in libpng has been written to allow programs to query, enable, and disable +either specific optimizations or all such optimizations. For example, to +enable all possible optimizations (bearing in mind that some "optimizations" +may actually run more slowly in rare cases): + + #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) + png_uint_32 mask, flags; + + flags = png_get_asm_flags(png_ptr); + mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE); + png_set_asm_flags(png_ptr, flags | mask); + #endif + +To enable only optimizations relevant to reading PNGs, use PNG_SELECT_READ +by itself when calling png_get_asm_flagmask(); similarly for optimizing +only writing. To disable all optimizations: + + #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) + flags = png_get_asm_flags(png_ptr); + mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE); + png_set_asm_flags(png_ptr, flags & ~mask); + #endif + +To enable or disable only MMX-related features, use png_get_mmx_flagmask() +in place of png_get_asm_flagmask(). The mmx version takes one additional +parameter: + + #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) + int selection = PNG_SELECT_READ | PNG_SELECT_WRITE; + int compilerID; + + mask = png_get_mmx_flagmask(selection, &compilerID); + #endif + +On return, compilerID will indicate which version of the MMX assembler +optimizations was compiled. Currently two flavors exist: Microsoft +Visual C++ (compilerID == 1) and GNU C (a.k.a. gcc/gas, compilerID == 2). +On non-x86 platforms or on systems compiled without MMX optimizations, a +value of -1 is used. + +Note that both png_get_asm_flagmask() and png_get_mmx_flagmask() return +all valid, settable optimization bits for the version of the library that's +currently in use. In the case of shared (dynamically linked) libraries, +this may include optimizations that did not exist at the time the code was +written and compiled. It is also possible, of course, to enable only known, +specific optimizations; for example: + + #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) + flags = PNG_ASM_FLAG_MMX_READ_COMBINE_ROW \ + | PNG_ASM_FLAG_MMX_READ_INTERLACE \ + | PNG_ASM_FLAG_MMX_READ_FILTER_SUB \ + | PNG_ASM_FLAG_MMX_READ_FILTER_UP \ + | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \ + | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ; + png_set_asm_flags(png_ptr, flags); + #endif + +This method would enable only the MMX read-optimizations available at the +time of libpng 1.2.0's release, regardless of whether a later version of +the DLL were actually being used. (Also note that these functions did not +exist in versions older than 1.2.0, so any attempt to run a dynamically +linked app on such an older version would fail.) + +To determine whether the processor supports MMX instructions at all, use +the png_mmx_support() function: + + #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) + mmxsupport = png_mmx_support(); + #endif + +It returns -1 if MMX support is not compiled into libpng, 0 if MMX code +is compiled but MMX is not supported by the processor, or 1 if MMX support +is fully available. Note that png_mmx_support(), png_get_mmx_flagmask(), +and png_get_asm_flagmask() all may be called without allocating and ini- +tializing any PNG structures (for example, as part of a usage screen or +"about" box). + +The following code can be used to prevent an application from using the +thread_unsafe features, even if libpng was built with PNG_THREAD_UNSAFE_OK +defined: + +#if defined(PNG_USE_PNGGCCRD) && defined(PNG_ASSEMBLER_CODE_SUPPORTED) \ + && defined(PNG_THREAD_UNSAFE_OK) + /* Disable thread-unsafe features of pnggccrd */ + if (png_access_version() >= 10200) + { + png_uint_32 mmx_disable_mask = 0; + png_uint_32 asm_flags; + + mmx_disable_mask |= ( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW \ + | PNG_ASM_FLAG_MMX_READ_FILTER_SUB \ + | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \ + | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ); + asm_flags = png_get_asm_flags(png_ptr); + png_set_asm_flags(png_ptr, asm_flags & ~mmx_disable_mask); + } +#endif + +For more extensive examples of runtime querying, enabling and disabling +of optimized features, see contrib/gregbook/readpng2.c in the libpng +source-code distribution. + +.SH VII. MNG support + +The MNG specification (available at http://www.libpng.org/pub/mng) allows +certain extensions to PNG for PNG images that are embedded in MNG datastreams. +Libpng can support some of these extensions. To enable them, use the +png_permit_mng_features() function: + + feature_set = png_permit_mng_features(png_ptr, mask) + mask is a png_uint_32 containing the logical OR of the + features you want to enable. These include + PNG_FLAG_MNG_EMPTY_PLTE + PNG_FLAG_MNG_FILTER_64 + PNG_ALL_MNG_FEATURES + feature_set is a png_uint_32 that is the logical AND of + your mask with the set of MNG features that is + supported by the version of libpng that you are using. + +It is an error to use this function when reading or writing a standalone +PNG file with the PNG 8-byte signature. The PNG datastream must be wrapped +in a MNG datastream. As a minimum, it must have the MNG 8-byte signature +and the MHDR and MEND chunks. Libpng does not provide support for these +or any other MNG chunks; your application must provide its own support for +them. You may wish to consider using libmng (available at +http://www.libmng.com) instead. + +.SH VIII. Changes to Libpng from version 0.88 + +It should be noted that versions of libpng later than 0.96 are not +distributed by the original libpng author, Guy Schalnat, nor by +Andreas Dilger, who had taken over from Guy during 1996 and 1997, and +distributed versions 0.89 through 0.96, but rather by another member +of the original PNG Group, Glenn Randers-Pehrson. Guy and Andreas are +still alive and well, but they have moved on to other things. + +The old libpng functions png_read_init(), png_write_init(), +png_info_init(), png_read_destroy(), and png_write_destroy() have been +moved to PNG_INTERNAL in version 0.95 to discourage their use. These +functions will be removed from libpng version 2.0.0. + +The preferred method of creating and initializing the libpng structures is +via the png_create_read_struct(), png_create_write_struct(), and +png_create_info_struct() because they isolate the size of the structures +from the application, allow version error checking, and also allow the +use of custom error handling routines during the initialization, which +the old functions do not. The functions png_read_destroy() and +png_write_destroy() do not actually free the memory that libpng +allocated for these structs, but just reset the data structures, so they +can be used instead of png_destroy_read_struct() and +png_destroy_write_struct() if you feel there is too much system overhead +allocating and freeing the png_struct for each image read. + +Setting the error callbacks via png_set_message_fn() before +png_read_init() as was suggested in libpng-0.88 is no longer supported +because this caused applications that do not use custom error functions +to fail if the png_ptr was not initialized to zero. It is still possible +to set the error callbacks AFTER png_read_init(), or to change them with +png_set_error_fn(), which is essentially the same function, but with a new +name to force compilation errors with applications that try to use the old +method. + +Starting with version 1.0.7, you can find out which version of the library +you are using at run-time: + + png_uint_32 libpng_vn = png_access_version_number(); + +The number libpng_vn is constructed from the major version, minor +version with leading zero, and release number with leading zero, +(e.g., libpng_vn for version 1.0.7 is 10007). + +You can also check which version of png.h you used when compiling your +application: + + png_uint_32 application_vn = PNG_LIBPNG_VER; + +.SH IX. Y2K Compliance in libpng + +September 12, 2004 + +Since the PNG Development group is an ad-hoc body, we can't make +an official declaration. + +This is your unofficial assurance that libpng from version 0.71 and +upward through 1.2.7 are Y2K compliant. It is my belief that earlier +versions were also Y2K compliant. + +Libpng only has three year fields. One is a 2-byte unsigned integer that +will hold years up to 65535. The other two hold the date in text +format, and will hold years up to 9999. + +The integer is + "png_uint_16 year" in png_time_struct. + +The strings are + "png_charp time_buffer" in png_struct and + "near_time_buffer", which is a local character string in png.c. + +There are seven time-related functions: + + png_convert_to_rfc_1123() in png.c + (formerly png_convert_to_rfc_1152() in error) + png_convert_from_struct_tm() in pngwrite.c, called + in pngwrite.c + png_convert_from_time_t() in pngwrite.c + png_get_tIME() in pngget.c + png_handle_tIME() in pngrutil.c, called in pngread.c + png_set_tIME() in pngset.c + png_write_tIME() in pngwutil.c, called in pngwrite.c + +All appear to handle dates properly in a Y2K environment. The +png_convert_from_time_t() function calls gmtime() to convert from system +clock time, which returns (year - 1900), which we properly convert to +the full 4-digit year. There is a possibility that applications using +libpng are not passing 4-digit years into the png_convert_to_rfc_1123() +function, or that they are incorrectly passing only a 2-digit year +instead of "year - 1900" into the png_convert_from_struct_tm() function, +but this is not under our control. The libpng documentation has always +stated that it works with 4-digit years, and the APIs have been +documented as such. + +The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned +integer to hold the year, and can hold years as large as 65535. + +zlib, upon which libpng depends, is also Y2K compliant. It contains +no date-related code. + + + Glenn Randers-Pehrson + libpng maintainer + PNG Development Group + +.SH NOTE + +Note about libpng version numbers: + +Due to various miscommunications, unforeseen code incompatibilities +and occasional factors outside the authors' control, version numbering +on the library has not always been consistent and straightforward. +The following table summarizes matters since version 0.89c, which was +the first widely used release: + + source png.h png.h shared-lib + version string int version + ------- ------ ----- ---------- + 0.89c ("beta 3") 0.89 89 1.0.89 + 0.90 ("beta 4") 0.90 90 0.90 + 0.95 ("beta 5") 0.95 95 0.95 + 0.96 ("beta 6") 0.96 96 0.96 + 0.97b ("beta 7") 1.00.97 97 1.0.1 + 0.97c 0.97 97 2.0.97 + 0.98 0.98 98 2.0.98 + 0.99 0.99 98 2.0.99 + 0.99a-m 0.99 99 2.0.99 + 1.00 1.00 100 2.1.0 + 1.0.0 1.0.0 100 2.1.0 + 1.0.0 (from here on, the 100 2.1.0 + 1.0.1 png.h string is 10001 2.1.0 + 1.0.1a-e identical to the 10002 from here on, the + 1.0.2 source version) 10002 shared library is 2.V + 1.0.2a-b 10003 where V is the source + 1.0.1 10001 code version except as + 1.0.1a-e 10002 2.1.0.1a-e noted. + 1.0.2 10002 2.1.0.2 + 1.0.2a-b 10003 2.1.0.2a-b + 1.0.3 10003 2.1.0.3 + 1.0.3a-d 10004 2.1.0.3a-d + 1.0.4 10004 2.1.0.4 + 1.0.4a-f 10005 2.1.0.4a-f + 1.0.5 (+ 2 patches) 10005 2.1.0.5 + 1.0.5a-d 10006 2.1.0.5a-d + 1.0.5e-r 10100 2.1.0.5e-r + 1.0.5s-v 10006 2.1.0.5s-v + 1.0.6 (+ 3 patches) 10006 2.1.0.6 + 1.0.6d-g 10007 2.1.0.6d-g + 1.0.6h 10007 10.6h + 1.0.6i 10007 10.6i + 1.0.6j 10007 2.1.0.6j + 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 + 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 + 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 + 1.0.7 1 10007 2.1.0.7 + 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + 1.0.8rc1 1 10008 2.1.0.8rc1 + 1.0.8 1 10008 2.1.0.8 + 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + 1.0.9rc1 1 10009 2.1.0.9rc1 + 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + 1.0.9rc2 1 10009 2.1.0.9rc2 + 1.0.9 1 10009 2.1.0.9 + 1.0.10beta1 1 10010 2.1.0.10beta1 + 1.0.10rc1 1 10010 2.1.0.10rc1 + 1.0.10 1 10010 2.1.0.10 + 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + 1.0.11rc1 1 10011 2.1.0.11rc1 + 1.0.11 1 10011 2.1.0.11 + 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 + 1.0.12rc1 2 10012 2.1.0.12rc1 + 1.0.12 2 10012 2.1.0.12 + 1.1.0a-f - 10100 2.1.1.0a-f abandoned + 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 + 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 + 1.2.0rc1 3 10200 3.1.2.0rc1 + 1.2.0 3 10200 3.1.2.0 + 1.2.1beta-4 3 10201 3.1.2.1beta1-4 + 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 + 1.2.1 3 10201 3.1.2.1 + 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 + 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 + 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 + 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 + 1.0.13 10 10013 10.so.0.1.0.13 + 1.2.2 12 10202 12.so.0.1.2.2 + 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 + 1.2.3 12 10203 12.so.0.1.2.3 + 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 + 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 + 1.0.14 10 10014 10.so.0.1.0.14 + 1.2.4 13 10204 12.so.0.1.2.4 + 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 + 1.0.15rc1 10 10015 10.so.0.1.0.15rc1 + 1.0.15 10 10015 10.so.0.1.0.15 + 1.2.5 13 10205 12.so.0.1.2.5 + 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 + 1.2.6rc1-5 13 10206 12.so.0.1.2.6rc1-5 + 1.0.16 10 10016 10.so.0.1.0.16 + 1.2.6 13 10206 12.so.0.1.2.6 + 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 + 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 + 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + 1.0.17 10 10017 12.so.0.1.0.17 + 1.2.7 13 10207 12.so.0.1.2.7 + +Henceforth the source version will match the shared-library minor +and patch numbers; the shared-library major version number will be +used for changes in backward compatibility, as it is intended. The +PNG_PNGLIB_VER macro, which is not used within libpng but is available +for applications, is an unsigned integer of the form xyyzz corresponding +to the source version x.y.z (leading zeros in y and z). Beta versions +were given the previous public release number plus a letter, until +version 1.0.6j; from then on they were given the upcoming public +release number plus "betaNN" or "rcN". + +.SH "SEE ALSO" +libpngpf(3), png(5) +.LP +.IR libpng : +.IP +http://libpng.sourceforge.net (follow the [DOWNLOAD] link) +http://www.libpng.org/pub/png + +.LP +.IR zlib : +.IP +(generally) at the same location as +.I libpng +or at +.br +ftp://ftp.info-zip.org/pub/infozip/zlib + +.LP +.IR PNG specification: RFC 2083 +.IP +(generally) at the same location as +.I libpng +or at +.br +ftp://ds.internic.net/rfc/rfc2083.txt +.br +or (as a W3C Recommendation) at +.br +http://www.w3.org/TR/REC-png.html + +.LP +In the case of any inconsistency between the PNG specification +and this library, the specification takes precedence. + +.SH AUTHORS +This man page: Glenn Randers-Pehrson +<glennrp@users.sourceforge.net> + +The contributing authors would like to thank all those who helped +with testing, bug fixes, and patience. This wouldn't have been +possible without all of you. + +Thanks to Frank J. T. Wojcik for helping with the documentation. + +Libpng version 1.2.7 - September 12, 2004: +Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc. +Currently maintained by Glenn Randers-Pehrson (glennrp@users.sourceforge.net). + +Supported by the PNG development group +.br +png-implement@ccrc.wustl.edu (subscription required; write to +majordomo@ccrc.wustl.edu with "subscribe png-implement" in the message). + +.SH COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + +(This copy of the libpng notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file png.h that is +included in the libpng distribution, the latter shall prevail.) + +If you modify libpng you may insert additional notices immediately following +this sentence. + +libpng version 1.2.6, September 12, 2004, is +Copyright (c) 2004 Glenn Randers-Pehrson, and is +distributed according to the same disclaimer and license as libpng-1.2.5 +with the following individual added to the list of Contributing Authors + + Cosmin Truta + +libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are +Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.0.6 +with the following individuals added to the list of Contributing Authors + + Simon-Pierre Cadieux + Eric S. Raymond + Gilles Vollant + +and with the following additions to the disclaimer: + + There is no warranty against interference with your + enjoyment of the library or against infringement. + There is no warranty that our efforts or the library + will fulfill any of your particular purposes or needs. + This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and + effort is with the user. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998, 1999 Glenn Randers-Pehrson +Distributed according to the same disclaimer and license as libpng-0.96, +with the following individuals added to the list of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996, 1997 Andreas Dilger +Distributed according to the same disclaimer and license as libpng-0.88, +with the following individuals added to the list of Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing Authors +and Group 42, Inc. disclaim all warranties, expressed or implied, +including, without limitation, the warranties of merchantability and of +fitness for any purpose. The Contributing Authors and Group 42, Inc. +assume no liability for direct, indirect, incidental, special, exemplary, +or consequential damages, which may result from the use of the PNG +Reference Library, even if advised of the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + +1. The origin of this source code must not be misrepresented. + +2. Altered versions must be plainly marked as such and + must not be misrepresented as being the original source. + +3. This Copyright notice may not be removed or altered from + any source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, without +fee, and encourage the use of this source code as a component to +supporting the PNG file format in commercial products. If you use this +source code in a product, acknowledgment is not required but would be +appreciated. + + +A "png_get_copyright" function is available, for convenient use in "about" +boxes and the like: + + printf("%s",png_get_copyright(NULL)); + +Also, the PNG logo (in PNG format, of course) is supplied in the +files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + +Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a +certification mark of the Open Source Initiative. + +Glenn Randers-Pehrson +glennrp@users.sourceforge.net +September 12, 2004 + +.\" end of man page + diff --git a/Utilities/FLTK/png/libpng.txt b/Utilities/FLTK/png/libpng.txt new file mode 100644 index 0000000000..4dec2dd3ae --- /dev/null +++ b/Utilities/FLTK/png/libpng.txt @@ -0,0 +1,2958 @@ +libpng.txt - A description on how to use and modify libpng + + libpng version 1.2.7 - September 12, 2004 + Updated and distributed by Glenn Randers-Pehrson + <glennrp@users.sourceforge.net> + Copyright (c) 1998-2004 Glenn Randers-Pehrson + For conditions of distribution and use, see copyright + notice in png.h. + + based on: + + libpng 1.0 beta 6 version 0.96 May 28, 1997 + Updated and distributed by Andreas Dilger + Copyright (c) 1996, 1997 Andreas Dilger + + libpng 1.0 beta 2 - version 0.88 January 26, 1996 + For conditions of distribution and use, see copyright + notice in png.h. Copyright (c) 1995, 1996 Guy Eric + Schalnat, Group 42, Inc. + + Updated/rewritten per request in the libpng FAQ + Copyright (c) 1995, 1996 Frank J. T. Wojcik + December 18, 1995 & January 20, 1996 + +I. Introduction + +This file describes how to use and modify the PNG reference library +(known as libpng) for your own use. There are five sections to this +file: introduction, structures, reading, writing, and modification and +configuration notes for various special platforms. In addition to this +file, example.c is a good starting point for using the library, as +it is heavily commented and should include everything most people +will need. We assume that libpng is already installed; see the +INSTALL file for instructions on how to install libpng. + +Libpng was written as a companion to the PNG specification, as a way +of reducing the amount of time and effort it takes to support the PNG +file format in application programs. + +The PNG specification (second edition), November 2003, is available as +a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2003 (E)) at +<http://www.w3.org/TR/2003/REC-PNG-20031110/ +The W3C and ISO documents have identical technical content. + +The PNG-1.2 specification is available at +<http://www.libpng.org/pub/png/documents/> + +The PNG-1.0 specification is available +as RFC 2083 <http://www.libpng.org/pub/png/documents/> and as a +W3C Recommendation <http://www.w3.org/TR/REC.png.html>. Some +additional chunks are described in the special-purpose public chunks +documents at <http://www.libpng.org/pub/png/documents/>. + +Other information +about PNG, and the latest version of libpng, can be found at the PNG home +page, <http://www.libpng.org/pub/png/>. + +Most users will not have to modify the library significantly; advanced +users may want to modify it more. All attempts were made to make it as +complete as possible, while keeping the code easy to understand. +Currently, this library only supports C. Support for other languages +is being considered. + +Libpng has been designed to handle multiple sessions at one time, +to be easily modifiable, to be portable to the vast majority of +machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy +to use. The ultimate goal of libpng is to promote the acceptance of +the PNG file format in whatever way possible. While there is still +work to be done (see the TODO file), libpng should cover the +majority of the needs of its users. + +Libpng uses zlib for its compression and decompression of PNG files. +Further information about zlib, and the latest version of zlib, can +be found at the zlib home page, <http://www.info-zip.org/pub/infozip/zlib/>. +The zlib compression utility is a general purpose utility that is +useful for more than PNG files, and can be used without libpng. +See the documentation delivered with zlib for more details. +You can usually find the source files for the zlib utility wherever you +find the libpng source files. + +Libpng is thread safe, provided the threads are using different +instances of the structures. Each thread should have its own +png_struct and png_info instances, and thus its own image. +Libpng does not protect itself against two threads using the +same instance of a structure. Note: thread safety may be defeated +by use of some of the MMX assembler code in pnggccrd.c, which is only +compiled when the user defines PNG_THREAD_UNSAFE_OK. + +II. Structures + +There are two main structures that are important to libpng, png_struct +and png_info. The first, png_struct, is an internal structure that +will not, for the most part, be used by a user except as the first +variable passed to every libpng function call. + +The png_info structure is designed to provide information about the +PNG file. At one time, the fields of png_info were intended to be +directly accessible to the user. However, this tended to cause problems +with applications using dynamically loaded libraries, and as a result +a set of interface functions for png_info (the png_get_*() and png_set_*() +functions) was developed. The fields of png_info are still available for +older applications, but it is suggested that applications use the new +interfaces if at all possible. + +Applications that do make direct access to the members of png_struct (except +for png_ptr->jmpbuf) must be recompiled whenever the library is updated, +and applications that make direct access to the members of png_info must +be recompiled if they were compiled or loaded with libpng version 1.0.6, +in which the members were in a different order. In version 1.0.7, the +members of the png_info structure reverted to the old order, as they were +in versions 0.97c through 1.0.5. Starting with version 2.0.0, both +structures are going to be hidden, and the contents of the structures will +only be accessible through the png_get/png_set functions. + +The png.h header file is an invaluable reference for programming with libpng. +And while I'm on the topic, make sure you include the libpng header file: + +#include <png.h> + +III. Reading + +We'll now walk you through the possible functions to call when reading +in a PNG file sequentially, briefly explaining the syntax and purpose +of each one. See example.c and png.h for more detail. While +progressive reading is covered in the next section, you will still +need some of the functions discussed in this section to read a PNG +file. + +Setup + +You will want to do the I/O initialization(*) before you get into libpng, +so if it doesn't work, you don't have much to undo. Of course, you +will also want to insure that you are, in fact, dealing with a PNG +file. Libpng provides a simple check to see if a file is a PNG file. +To use it, pass in the first 1 to 8 bytes of the file to the function +png_sig_cmp(), and it will return 0 if the bytes match the corresponding +bytes of the PNG signature, or nonzero otherwise. Of course, the more bytes +you pass in, the greater the accuracy of the prediction. + +If you are intending to keep the file pointer open for use in libpng, +you must ensure you don't read more than 8 bytes from the beginning +of the file, and you also have to make a call to png_set_sig_bytes_read() +with the number of bytes you read from the beginning. Libpng will +then only check the bytes (if any) that your program didn't read. + +(*): If you are not using the standard I/O functions, you will need +to replace them with custom functions. See the discussion under +Customizing libpng. + + + FILE *fp = fopen(file_name, "rb"); + if (!fp) + { + return (ERROR); + } + fread(header, 1, number, fp); + is_png = !png_sig_cmp(header, 0, number); + if (!is_png) + { + return (NOT_PNG); + } + + +Next, png_struct and png_info need to be allocated and initialized. In +order to ensure that the size of these structures is correct even with a +dynamically linked libpng, there are functions to initialize and +allocate the structures. We also pass the library version, optional +pointers to error handling functions, and a pointer to a data struct for +use by the error functions, if necessary (the pointer and functions can +be NULL if the default error handlers are to be used). See the section +on Changes to Libpng below regarding the old initialization functions. +The structure allocation functions quietly return NULL if they fail to +create the structure, so your application should check for that. + + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + if (!png_ptr) + return (ERROR); + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + return (ERROR); + } + + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + +If you want to use your own memory allocation routines, +define PNG_USER_MEM_SUPPORTED and use +png_create_read_struct_2() instead of png_create_read_struct(): + + png_structp png_ptr = png_create_read_struct_2 + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn, (png_voidp) + user_mem_ptr, user_malloc_fn, user_free_fn); + +The error handling routines passed to png_create_read_struct() +and the memory alloc/free routines passed to png_create_struct_2() +are only necessary if you are not using the libpng supplied error +handling and memory alloc/free functions. + +When libpng encounters an error, it expects to longjmp back +to your routine. Therefore, you will need to call setjmp and pass +your png_jmpbuf(png_ptr). If you read the file from different +routines, you will need to update the jmpbuf field every time you enter +a new routine that will call a png_*() function. + +See your documentation of setjmp/longjmp for your compiler for more +information on setjmp/longjmp. See the discussion on libpng error +handling in the Customizing Libpng section below for more information +on the libpng error handling. If an error occurs, and libpng longjmp's +back to your setjmp, you will want to call png_destroy_read_struct() to +free any memory. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + fclose(fp); + return (ERROR); + } + +If you would rather avoid the complexity of setjmp/longjmp issues, +you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +Now you need to set up the input code. The default for libpng is to +use the C function fread(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. If you wish to handle reading data in another +way, you need not call the png_init_io() function, but you must then +implement the libpng I/O methods discussed in the Customizing Libpng +section below. + + png_init_io(png_ptr, fp); + +If you had previously opened the file and read any of the signature from +the beginning in order to see if this was a PNG file, you need to let +libpng know that there are some bytes missing from the start of the file. + + png_set_sig_bytes(png_ptr, number); + +Setting up callback code + +You can set up a callback function to handle any unknown chunks in the +input stream. You must supply the function + + read_chunk_callback(png_ptr ptr, + png_unknown_chunkp chunk); + { + /* The unknown chunk structure contains your + chunk data: */ + png_byte name[5]; + png_byte *data; + png_size_t size; + /* Note that libpng has already taken care of + the CRC handling */ + + /* put your code here. Return one of the + following: */ + + return (-n); /* chunk had an error */ + return (0); /* did not recognize */ + return (n); /* success */ + } + +(You can give your function another name that you like instead of +"read_chunk_callback") + +To inform libpng about your function, use + + png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, + read_chunk_callback); + +This names not only the callback function, but also a user pointer that +you can retrieve with + + png_get_user_chunk_ptr(png_ptr); + +At this point, you can set up a callback function that will be +called after each row has been read, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void read_row_callback(png_ptr ptr, png_uint_32 row, + int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "read_row_callback") + +To inform libpng about your function, use + + png_set_read_status_fn(png_ptr, read_row_callback); + +Width and height limits + +The PNG specification allows the width and height of an image to be as +large as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns. +Since very few applications really need to process such large images, +we have imposed an arbitrary 1-million limit on rows and columns. +Larger images will be rejected immediately with a png_error() call. If +you wish to override this limit, you can use + + png_set_user_limits(png_ptr, width_max, height_max); + +to set your own limits, or use width_max = height_max = 0x7fffffffL +to allow all valid dimensions (libpng may reject some very large images +anyway because of potential buffer overflow conditions). + +You should put this statement after you create the PNG structure and +before calling png_read_info(), png_read_png(), or png_process_data(). +If you need to retrieve the limits that are being applied, use + + width_max = png_get_user_width_max(png_ptr); + height_max = png_get_user_height_max(png_ptr); + +Unknown-chunk handling + +Now you get to set the way the library processes unknown chunks in the +input PNG stream. Both known and unknown chunks will be read. Normal +behavior is that known chunks will be parsed into information in +various info_ptr members; unknown chunks will be discarded. To change +this, you can call: + + png_set_keep_unknown_chunks(png_ptr, keep, + chunk_list, num_chunks); + keep - 0: do not handle as unknown + 1: do not keep + 2: keep only if safe-to-copy + 3: keep even if unsafe-to-copy + You can use these definitions: + PNG_HANDLE_CHUNK_AS_DEFAULT 0 + PNG_HANDLE_CHUNK_NEVER 1 + PNG_HANDLE_CHUNK_IF_SAFE 2 + PNG_HANDLE_CHUNK_ALWAYS 3 + chunk_list - list of chunks affected (a byte string, + five bytes per chunk, NULL or '\0' if + num_chunks is 0) + num_chunks - number of chunks affected; if 0, all + unknown chunks are affected. If nonzero, + only the chunks in the list are affected + +Unknown chunks declared in this way will be saved as raw data onto a +list of png_unknown_chunk structures. If a chunk that is normally +known to libpng is named in the list, it will be handled as unknown, +according to the "keep" directive. If a chunk is named in successive +instances of png_set_keep_unknown_chunks(), the final instance will +take precedence. The IHDR and IEND chunks should not be named in +chunk_list; if they are, libpng will process them normally anyway. + +The high-level read interface + +At this point there are two ways to proceed; through the high-level +read interface, or through a sequence of low-level read operations. +You can use the high-level interface if (a) you are willing to read +the entire image into memory, and (b) the input transformations +you want to do are limited to the following set: + + PNG_TRANSFORM_IDENTITY No transformation + PNG_TRANSFORM_STRIP_16 Strip 16-bit samples to + 8 bits + PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel + PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit + samples to bytes + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_EXPAND Perform set_expand() + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + +(This excludes setting a background color, doing gamma transformation, +dithering, and setting filler.) If this is the case, simply do this: + + png_read_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the logical OR of +some set of transformation flags. This call is equivalent to png_read_info(), +followed the set of transformations indicated by the transform mask, +then png_read_image(), and finally png_read_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future input transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_read_png(). + +After you have called png_read_png(), you can retrieve the image data +with + + row_pointers = png_get_rows(png_ptr, info_ptr); + +where row_pointers is an array of pointers to the pixel data for each row: + + png_bytep row_pointers[height]; + +If you know your image size and pixel size ahead of time, you can allocate +row_pointers prior to calling png_read_png() with + + if (height > PNG_UINT_32_MAX/png_sizeof(png_byte)) + png_error (png_ptr, + "Image is too tall to process in memory"); + if (width > PNG_UINT_32_MAX/pixel_size) + png_error (png_ptr, + "Image is too wide to process in memory"); + row_pointers = png_malloc(png_ptr, + height*png_sizeof(png_bytep)); + for (int i=0; i<height, i++) + row_pointers[i]=png_malloc(png_ptr, + width*pixel_size); + png_set_rows(png_ptr, info_ptr, &row_pointers); + +Alternatively you could allocate your image in one big block and define +row_pointers[i] to point into the proper places in your block. + +If you use png_set_rows(), the application is responsible for freeing +row_pointers (and row_pointers[i], if they were separately allocated). + +If you don't allocate row_pointers ahead of time, png_read_png() will +do it, and it'll be free'ed when you call png_destroy_*(). + +The low-level read interface + +If you are going the low-level route, you are now ready to read all +the file information up to the actual image data. You do this with a +call to png_read_info(). + + png_read_info(png_ptr, info_ptr); + +This will process all chunks up to but not including the image data. + +Querying the info structure + +Functions are used to get the information from the info_ptr once it +has been read. Note that these fields may not be completely filled +in until png_read_end() has read the chunk data following the image. + + png_get_IHDR(png_ptr, info_ptr, &width, &height, + &bit_depth, &color_type, &interlace_type, + &compression_type, &filter_method); + + width - holds the width of the image + in pixels (up to 2^31). + height - holds the height of the image + in pixels (up to 2^31). + bit_depth - holds the bit depth of one of the + image channels. (valid values are + 1, 2, 4, 8, 16 and depend also on + the color_type. See also + significant bits (sBIT) below). + color_type - describes which color/alpha channels + are present. + PNG_COLOR_TYPE_GRAY + (bit depths 1, 2, 4, 8, 16) + PNG_COLOR_TYPE_GRAY_ALPHA + (bit depths 8, 16) + PNG_COLOR_TYPE_PALETTE + (bit depths 1, 2, 4, 8) + PNG_COLOR_TYPE_RGB + (bit_depths 8, 16) + PNG_COLOR_TYPE_RGB_ALPHA + (bit_depths 8, 16) + + PNG_COLOR_MASK_PALETTE + PNG_COLOR_MASK_COLOR + PNG_COLOR_MASK_ALPHA + + filter_method - (must be PNG_FILTER_TYPE_BASE + for PNG 1.0, and can also be + PNG_INTRAPIXEL_DIFFERENCING if + the PNG datastream is embedded in + a MNG-1.0 datastream) + compression_type - (must be PNG_COMPRESSION_TYPE_BASE + for PNG 1.0) + interlace_type - (PNG_INTERLACE_NONE or + PNG_INTERLACE_ADAM7) + Any or all of interlace_type, compression_type, of + filter_method can be NULL if you are + not interested in their values. + + channels = png_get_channels(png_ptr, info_ptr); + channels - number of channels of info for the + color type (valid values are 1 (GRAY, + PALETTE), 2 (GRAY_ALPHA), 3 (RGB), + 4 (RGB_ALPHA or RGB + filler byte)) + rowbytes = png_get_rowbytes(png_ptr, info_ptr); + rowbytes - number of bytes needed to hold a row + + signature = png_get_signature(png_ptr, info_ptr); + signature - holds the signature read from the + file (if any). The data is kept in + the same offset it would be if the + whole signature were read (i.e. if an + application had already read in 4 + bytes of signature before starting + libpng, the remaining 4 bytes would + be in signature[4] through signature[7] + (see png_set_sig_bytes())). + + + width = png_get_image_width(png_ptr, + info_ptr); + height = png_get_image_height(png_ptr, + info_ptr); + bit_depth = png_get_bit_depth(png_ptr, + info_ptr); + color_type = png_get_color_type(png_ptr, + info_ptr); + filter_method = png_get_filter_type(png_ptr, + info_ptr); + compression_type = png_get_compression_type(png_ptr, + info_ptr); + interlace_type = png_get_interlace_type(png_ptr, + info_ptr); + + +These are also important, but their validity depends on whether the chunk +has been read. The png_get_valid(png_ptr, info_ptr, PNG_INFO_<chunk>) and +png_get_<chunk>(png_ptr, info_ptr, ...) functions return non-zero if the +data has been read, or zero if it is missing. The parameters to the +png_get_<chunk> are set directly if they are simple data types, or a pointer +into the info_ptr is returned for any complex types. + + png_get_PLTE(png_ptr, info_ptr, &palette, + &num_palette); + palette - the palette for the file + (array of png_color) + num_palette - number of entries in the palette + + png_get_gAMA(png_ptr, info_ptr, &gamma); + gamma - the gamma the file is written + at (PNG_INFO_gAMA) + + png_get_sRGB(png_ptr, info_ptr, &srgb_intent); + srgb_intent - the rendering intent (PNG_INFO_sRGB) + The presence of the sRGB chunk + means that the pixel data is in the + sRGB color space. This chunk also + implies specific values of gAMA and + cHRM. + + png_get_iCCP(png_ptr, info_ptr, &name, + &compression_type, &profile, &proflen); + name - The profile name. + compression - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + profile - International Color Consortium color + profile data. May contain NULs. + proflen - length of profile data in bytes. + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, + red, green, and blue channels, + whichever are appropriate for the + given color type (png_color_16) + + png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, + &trans_values); + trans - array of transparent entries for + palette (PNG_INFO_tRNS) + trans_values - graylevel or color sample values of + the single transparent color for + non-paletted images (PNG_INFO_tRNS) + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + png_get_hIST(png_ptr, info_ptr, &hist); + (PNG_INFO_hIST) + hist - histogram of palette (array of + png_uint_16) + + png_get_tIME(png_ptr, info_ptr, &mod_time); + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_get_bKGD(png_ptr, info_ptr, &background); + background - background color (PNG_VALID_bKGD) + valid 16-bit red, green and blue + values, regardless of color_type + + num_comments = png_get_text(png_ptr, info_ptr, + &text_ptr, &num_text); + num_comments - number of comments + text_ptr - array of png_text holding image + comments + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + text_ptr[i].text - text comments for current + keyword. Can be empty. + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + text_ptr[i].lang - language of comment (empty + string for unknown). + text_ptr[i].lang_key - keyword in UTF-8 + (empty string for unknown). + num_text - number of comments (same as + num_comments; you can put NULL here + to avoid the duplication) + Note while png_set_text() will accept text, language, + and translated keywords that can be NULL pointers, the + structure returned by png_get_text will always contain + regular zero-terminated C strings. They might be + empty strings but they will never be NULL pointers. + + num_spalettes = png_get_sPLT(png_ptr, info_ptr, + &palette_ptr); + palette_ptr - array of palette structures holding + contents of one or more sPLT chunks + read. + num_spalettes - number of sPLT chunks read. + + png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, + &unit_type); + offset_x - positive offset from the left edge + of the screen + offset_y - positive offset from the top edge + of the screen + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, + &unit_type); + res_x - pixels/unit physical resolution in + x direction + res_y - pixels/unit physical resolution in + x direction + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_get_sCAL(png_ptr, info_ptr, &unit, &width, + &height) + unit - physical scale units (an integer) + width - width of a pixel in physical scale units + height - height of a pixel in physical scale units + (width and height are doubles) + + png_get_sCAL_s(png_ptr, info_ptr, &unit, &width, + &height) + unit - physical scale units (an integer) + width - width of a pixel in physical scale units + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + num_unknown_chunks = png_get_unknown_chunks(png_ptr, + info_ptr, &unknowns) + unknowns - array of png_unknown_chunk + structures holding unknown chunks + unknowns[i].name - name of unknown chunk + unknowns[i].data - data of unknown chunk + unknowns[i].size - size of unknown chunk's data + unknowns[i].location - position of chunk in file + + The value of "i" corresponds to the order in which the + chunks were read from the PNG file or inserted with the + png_set_unknown_chunks() function. + +The data from the pHYs chunk can be retrieved in several convenient +forms: + + res_x = png_get_x_pixels_per_meter(png_ptr, + info_ptr) + res_y = png_get_y_pixels_per_meter(png_ptr, + info_ptr) + res_x_and_y = png_get_pixels_per_meter(png_ptr, + info_ptr) + res_x = png_get_x_pixels_per_inch(png_ptr, + info_ptr) + res_y = png_get_y_pixels_per_inch(png_ptr, + info_ptr) + res_x_and_y = png_get_pixels_per_inch(png_ptr, + info_ptr) + aspect_ratio = png_get_pixel_aspect_ratio(png_ptr, + info_ptr) + + (Each of these returns 0 [signifying "unknown"] if + the data is not present or if res_x is 0; + res_x_and_y is 0 if res_x != res_y) + +The data from the oFFs chunk can be retrieved in several convenient +forms: + + x_offset = png_get_x_offset_microns(png_ptr, info_ptr); + y_offset = png_get_y_offset_microns(png_ptr, info_ptr); + x_offset = png_get_x_offset_inches(png_ptr, info_ptr); + y_offset = png_get_y_offset_inches(png_ptr, info_ptr); + + (Each of these returns 0 [signifying "unknown" if both + x and y are 0] if the data is not present or if the + chunk is present but the unit is the pixel) + +For more information, see the png_info definition in png.h and the +PNG specification for chunk contents. Be careful with trusting +rowbytes, as some of the transformations could increase the space +needed to hold a row (expand, filler, gray_to_rgb, etc.). +See png_read_update_info(), below. + +A quick word about text_ptr and num_text. PNG stores comments in +keyword/text pairs, one pair per chunk, with no limit on the number +of text chunks, and a 2^31 byte limit on their size. While there are +suggested keywords, there is no requirement to restrict the use to these +strings. It is strongly suggested that keywords and text be sensible +to humans (that's the point), so don't use abbreviations. Non-printing +symbols are not allowed. See the PNG specification for more details. +There is also no requirement to have text after the keyword. + +Keywords should be limited to 79 Latin-1 characters without leading or +trailing spaces, but non-consecutive spaces are allowed within the +keyword. It is possible to have the same keyword any number of times. +The text_ptr is an array of png_text structures, each holding a +pointer to a language string, a pointer to a keyword and a pointer to +a text string. The text string, language code, and translated +keyword may be empty or NULL pointers. The keyword/text +pairs are put into the array in the order that they are received. +However, some or all of the text chunks may be after the image, so, to +make sure you have read all the text chunks, don't mess with these +until after you read the stuff after the image. This will be +mentioned again below in the discussion that goes with png_read_end(). + +Input transformations + +After you've read the header information, you can set up the library +to handle any special transformations of the image data. The various +ways to transform the data will be described in the order that they +should occur. This is important, as some of these change the color +type and/or bit depth of the data, and some others only work on +certain color types and bit depths. Even though each transformation +checks to see if it has data that it can do something with, you should +make sure to only enable a transformation if it will be valid for the +data. For example, don't swap red and blue on grayscale data. + +The colors used for the background and transparency values should be +supplied in the same format/depth as the current image data. They +are stored in the same format/depth as the image data in a bKGD or tRNS +chunk, so this is what libpng expects for this data. The colors are +transformed to keep in sync with the image data when an application +calls the png_read_update_info() routine (see below). + +Data will be decoded into the supplied row buffers packed into bytes +unless the library has been told to transform it into another format. +For example, 4 bit/pixel paletted or grayscale data will be returned +2 pixels/byte with the leftmost pixel in the high-order bits of the +byte, unless png_set_packing() is called. 8-bit RGB data will be stored +in RGB RGB RGB format unless png_set_filler() or png_set_add_alpha() +is called to insert filler bytes, either before or after each RGB triplet. +16-bit RGB data will be returned RRGGBB RRGGBB, with the most significant +byte of the color value first, unless png_set_strip_16() is called to +transform it to regular RGB RGB triplets, or png_set_filler|add alpha() +is called to insert filler bytes, either before or after each RRGGBB +triplet. Similarly, 8-bit or 16-bit grayscale data can be modified with +png_set_filler(), png_set_add_alpha(), or png_set_strip_16(). + +The following code transforms grayscale images of less than 8 to 8 bits, +changes paletted images to RGB, and adds a full alpha channel if there is +transparency information in a tRNS chunk. This is most useful on +grayscale images with bit depths of 2 or 4 or if there is a multiple-image +viewing application that wishes to treat all images in the same way. + + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png_ptr); + + if (color_type == PNG_COLOR_TYPE_GRAY && + bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr); + + if (png_get_valid(png_ptr, info_ptr, + PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); + +These three functions are actually aliases for png_set_expand(), added +in libpng version 1.0.4, with the function names expanded to improve code +readability. In some future version they may actually do different +things. + +PNG can have files with 16 bits per channel. If you only can handle +8 bits per channel, this will strip the pixels down to 8 bit. + + if (bit_depth == 16) + png_set_strip_16(png_ptr); + +If, for some reason, you don't need the alpha channel on an image, +and you want to remove it rather than combining it with the background +(but the image author certainly had in mind that you *would* combine +it with the background, so that's what you should probably do): + + if (color_type & PNG_COLOR_MASK_ALPHA) + png_set_strip_alpha(png_ptr); + +In PNG files, the alpha channel in an image +is the level of opacity. If you need the alpha channel in an image to +be the level of transparency instead of opacity, you can invert the +alpha channel (or the tRNS chunk data) after it's read, so that 0 is +fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit +images) is fully transparent, with + + png_set_invert_alpha(png_ptr); + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit +files. This code expands to 1 pixel per byte without changing the +values of the pixels: + + if (bit_depth < 8) + png_set_packing(png_ptr); + +PNG files have possible bit depths of 1, 2, 4, 8, and 16. All pixels +stored in a PNG image have been "scaled" or "shifted" up to the next +higher possible bit depth (e.g. from 5 bits/sample in the range [0,31] to +8 bits/sample in the range [0, 255]). However, it is also possible to +convert the PNG pixel data back to the original bit depth of the image. +This call reduces the pixels back down to the original bit depth: + + png_color_8p sig_bit; + + if (png_get_sBIT(png_ptr, info_ptr, &sig_bit)) + png_set_shift(png_ptr, sig_bit); + +PNG files store 3-color pixels in red, green, blue order. This code +changes the storage of the pixels to blue, green, red: + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_bgr(png_ptr); + +PNG files store RGB pixels packed into 3 or 6 bytes. This code expands them +into 4 or 8 bytes for windowing systems that need them in this format: + + if (color_type == PNG_COLOR_TYPE_RGB) + png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE); + +where "filler" is the 8 or 16-bit number to fill with, and the location is +either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether +you want the filler before the RGB or after. This transformation +does not affect images that already have full alpha channels. To add an +opaque alpha channel, use filler=0xff or 0xffff and PNG_FILLER_AFTER which +will generate RGBA pixels. + +Note that png_set_filler() does not change the color type. If you want +to do that, you can add a true alpha channel with + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY) + png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER); + +where "filler" contains the alpha value to assign to each pixel. +This function became available in libpng-1.2.7. + +If you are reading an image with an alpha channel, and you need the +data as ARGB instead of the normal PNG format RGBA: + + if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_swap_alpha(png_ptr); + +For some uses, you may want a grayscale image to be represented as +RGB. This code will do that conversion: + + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + +Conversely, you can convert an RGB or RGBA image to grayscale or grayscale +with alpha. + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_rgb_to_gray_fixed(png_ptr, error_action, + int red_weight, int green_weight); + + error_action = 1: silently do the conversion + error_action = 2: issue a warning if the original + image has any pixel where + red != green or red != blue + error_action = 3: issue an error and abort the + conversion if the original + image has any pixel where + red != green or red != blue + + red_weight: weight of red component times 100000 + green_weight: weight of green component times 100000 + If either weight is negative, default + weights (21268, 71514) are used. + +If you have set error_action = 1 or 2, you can +later check whether the image really was gray, after processing +the image rows, with the png_get_rgb_to_gray_status(png_ptr) function. +It will return a png_byte that is zero if the image was gray or +1 if there were any non-gray pixels. bKGD and sBIT data +will be silently converted to grayscale, using the green channel +data, regardless of the error_action setting. + +With red_weight+green_weight<=100000, +the normalized graylevel is computed: + + int rw = red_weight * 65536; + int gw = green_weight * 65536; + int bw = 65536 - (rw + gw); + gray = (rw*red + gw*green + bw*blue)/65536; + +The default values approximate those recommended in the Charles +Poynton's Color FAQ, <http://www.inforamp.net/~poynton/> +Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net + + Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + +Libpng approximates this with + + Y = 0.21268 * R + 0.7151 * G + 0.07217 * B + +which can be expressed with integers as + + Y = (6969 * R + 23434 * G + 2365 * B)/32768 + +The calculation is done in a linear colorspace, if the image gamma +is known. + +If you have a grayscale and you are using png_set_expand_depth(), +png_set_expand(), or png_set_gray_to_rgb to change to truecolor or to +a higher bit-depth, you must either supply the background color as a gray +value at the original file bit-depth (need_expand = 1) or else supply the +background color as an RGB triplet at the final, expanded bit depth +(need_expand = 0). Similarly, if you are reading a paletted image, you +must either supply the background color as a palette index (need_expand = 1) +or as an RGB triplet that may or may not be in the palette (need_expand = 0). + + png_color_16 my_background; + png_color_16p image_background; + + if (png_get_bKGD(png_ptr, info_ptr, &image_background)) + png_set_background(png_ptr, image_background, + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + else + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + +The png_set_background() function tells libpng to composite images +with alpha or simple transparency against the supplied background +color. If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid), +you may use this color, or supply another color more suitable for +the current display (e.g., the background color from a web page). You +need to tell libpng whether the color is in the gamma space of the +display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file +(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one +that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't +know why anyone would use this, but it's here). + +To properly display PNG images on any kind of system, the application needs +to know what the display gamma is. Ideally, the user will know this, and +the application will allow them to set it. One method of allowing the user +to set the display gamma separately for each system is to check for a +SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be +correctly set. + +Note that display_gamma is the overall gamma correction required to produce +pleasing results, which depends on the lighting conditions in the surrounding +environment. In a dim or brightly lit room, no compensation other than +the physical gamma exponent of the monitor is needed, while in a dark room +a slightly smaller exponent is better. + + double gamma, screen_gamma; + + if (/* We have a user-defined screen + gamma value */) + { + screen_gamma = user_defined_screen_gamma; + } + /* One way that applications can share the same + screen gamma value */ + else if ((gamma_str = getenv("SCREEN_GAMMA")) + != NULL) + { + screen_gamma = (double)atof(gamma_str); + } + /* If we don't have another value */ + else + { + screen_gamma = 2.2; /* A good guess for a + PC monitor in a bright office or a dim room */ + screen_gamma = 2.0; /* A good guess for a + PC monitor in a dark room */ + screen_gamma = 1.7 or 1.0; /* A good + guess for Mac systems */ + } + +The png_set_gamma() function handles gamma transformations of the data. +Pass both the file gamma and the current screen_gamma. If the file does +not have a gamma value, you can pass one anyway if you have an idea what +it is (usually 0.45455 is a good guess for GIF images on PCs). Note +that file gammas are inverted from screen gammas. See the discussions +on gamma in the PNG specification for an excellent description of what +gamma is, and why all applications should support it. It is strongly +recommended that PNG viewers support gamma correction. + + if (png_get_gAMA(png_ptr, info_ptr, &gamma)) + png_set_gamma(png_ptr, screen_gamma, gamma); + else + png_set_gamma(png_ptr, screen_gamma, 0.45455); + +If you need to reduce an RGB file to a paletted file, or if a paletted +file has more entries then will fit on your screen, png_set_dither() +will do that. Note that this is a simple match dither that merely +finds the closest color available. This should work fairly well with +optimized palettes, and fairly badly with linear color cubes. If you +pass a palette that is larger then maximum_colors, the file will +reduce the number of colors in the palette so it will fit into +maximum_colors. If there is a histogram, it will use it to make +more intelligent choices when reducing the palette. If there is no +histogram, it may not do as good a job. + + if (color_type & PNG_COLOR_MASK_COLOR) + { + if (png_get_valid(png_ptr, info_ptr, + PNG_INFO_PLTE)) + { + png_uint_16p histogram = NULL; + + png_get_hIST(png_ptr, info_ptr, + &histogram); + png_set_dither(png_ptr, palette, num_palette, + max_screen_colors, histogram, 1); + } + else + { + png_color std_color_cube[MAX_SCREEN_COLORS] = + { ... colors ... }; + + png_set_dither(png_ptr, std_color_cube, + MAX_SCREEN_COLORS, MAX_SCREEN_COLORS, + NULL,0); + } + } + +PNG files describe monochrome as black being zero and white being one. +The following code will reverse this (make black be one and white be +zero): + + if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY) + png_set_invert_mono(png_ptr); + +This function can also be used to invert grayscale and gray-alpha images: + + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_invert_mono(png_ptr); + +PNG files store 16 bit pixels in network byte order (big-endian, +ie. most significant bits first). This code changes the storage to the +other way (little-endian, i.e. least significant bits first, the +way PCs store them): + + if (bit_depth == 16) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_read_user_transform_fn(png_ptr, + read_transform_fn); + +You must supply the function + + void read_transform_fn(png_ptr ptr, row_info_ptr + row_info, png_bytep data) + +See pngtest.c for a working example. Your function will be called +after all of the other transformations have been processed. + +You can also set up a pointer to a user structure for use by your +callback function, and you can inform libpng that your transform +function will change the number of channels or bit depth with the +function + + png_set_user_transform_info(png_ptr, user_ptr, + user_depth, user_channels); + +The user's application, not libpng, is responsible for allocating and +freeing any memory required for the user structure. + +You can retrieve the pointer via the function +png_get_user_transform_ptr(). For example: + + voidp read_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +The last thing to handle is interlacing; this is covered in detail below, +but you must call the function here if you want libpng to handle expansion +of the interlaced image. + + number_of_passes = png_set_interlace_handling(png_ptr); + +After setting the transformations, libpng can update your png_info +structure to reflect any transformations you've requested with this +call. This is most useful to update the info structure's rowbytes +field so you can use it to allocate your image memory. This function +will also update your palette with the correct screen_gamma and +background if these have been given with the calls above. + + png_read_update_info(png_ptr, info_ptr); + +After you call png_read_update_info(), you can allocate any +memory you need to hold the image. The row data is simply +raw byte data for all forms of images. As the actual allocation +varies among applications, no example will be given. If you +are allocating one large chunk, you will need to build an +array of pointers to each row, as it will be needed for some +of the functions below. + +Reading image data + +After you've allocated memory, you can read the image data. +The simplest way to do this is in one function call. If you are +allocating enough memory to hold the whole image, you can just +call png_read_image() and libpng will read in all the image data +and put it in the memory area supplied. You will need to pass in +an array of pointers to each row. + +This function automatically handles interlacing, so you don't need +to call png_set_interlace_handling() or call this function multiple +times, or any of that other stuff necessary with png_read_rows(). + + png_read_image(png_ptr, row_pointers); + +where row_pointers is: + + png_bytep row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to read in the whole image at once, you can +use png_read_rows() instead. If there is no interlacing (check +interlace_type == PNG_INTERLACE_NONE), this is simple: + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + +where row_pointers is the same as in the png_read_image() call. + +If you are doing this just one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + png_read_row(png_ptr, row_pointer, NULL); + +If the file is interlaced (interlace_type != 0 in the IHDR chunk), things +get somewhat harder. The only current (PNG Specification version 1.2) +interlacing type for PNG is (interlace_type == PNG_INTERLACE_ADAM7) +is a somewhat complicated 2D interlace scheme, known as Adam7, that +breaks down an image into seven smaller images of varying size, based +on an 8x8 grid. + +libpng can fill out those images or it can give them to you "as is". +If you want them filled out, there are two ways to do that. The one +mentioned in the PNG specification is to expand each pixel to cover +those pixels that have not been read yet (the "rectangle" method). +This results in a blocky image for the first pass, which gradually +smooths out as more pixels are read. The other method is the "sparkle" +method, where pixels are drawn only in their final locations, with the +rest of the image remaining whatever colors they were initialized to +before the start of the read. The first method usually looks better, +but tends to be slower, as there are more pixels to put in the rows. + +If you don't want libpng to handle the interlacing details, just call +png_read_rows() seven times to read in all seven images. Each of the +images is a valid image by itself, or they can all be combined on an +8x8 grid to form a single image (although if you intend to combine them +you would be far better off using the libpng interlace handling). + +The first pass will return an image 1/8 as wide as the entire image +(every 8th column starting in column 0) and 1/8 as high as the original +(every 8th row starting in row 0), the second will be 1/8 as wide +(starting in column 4) and 1/8 as high (also starting in row 0). The +third pass will be 1/4 as wide (every 4th pixel starting in column 0) and +1/8 as high (every 8th row starting in row 4), and the fourth pass will +be 1/4 as wide and 1/4 as high (every 4th column starting in column 2, +and every 4th row starting in row 0). The fifth pass will return an +image 1/2 as wide, and 1/4 as high (starting at column 0 and row 2), +while the sixth pass will be 1/2 as wide and 1/2 as high as the original +(starting in column 1 and row 0). The seventh and final pass will be as +wide as the original, and 1/2 as high, containing all of the odd +numbered scanlines. Phew! + +If you want libpng to expand the images, call this before calling +png_start_read_image() or png_read_update_info(): + + if (interlace_type == PNG_INTERLACE_ADAM7) + number_of_passes + = png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this +is seven, but may change if another interlace type is added. +This function can be called even if the file is not interlaced, +where it will return one pass. + +If you are not going to display the image after each pass, but are +going to wait until the entire image is read in, use the sparkle +effect. This effect is faster and the end result of either method +is exactly the same. If you are planning on displaying the image +after each pass, the "rectangle" effect is generally considered the +better looking one. + +If you only want the "sparkle" effect, just call png_read_rows() as +normal, with the third parameter NULL. Make sure you make pass over +the image number_of_passes times, and you don't change the data in the +rows between calls. You can change the locations of the data, just +not the data. Each pass only writes the pixels appropriate for that +pass, and assumes the data from previous passes is still valid. + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + +If you only want the first effect (the rectangles), do the same as +before except pass the row buffer in the third parameter, and leave +the second parameter NULL. + + png_read_rows(png_ptr, NULL, row_pointers, + number_of_rows); + +Finishing a sequential read + +After you are finished reading the image through either the high- or +low-level interfaces, you can finish reading the file. If you are +interested in comments or time, which may be stored either before or +after the image data, you should pass the separate png_info struct if +you want to keep the comments from before and after the image +separate. If you are not interested, you can pass NULL. + + png_read_end(png_ptr, end_info); + +When you are done, you can free all memory allocated by libpng like this: + + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + mask - identifies data to be freed, a mask + containing the logical OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + seq - sequence number of item to be freed + (-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those +cases do nothing. The "seq" parameter is ignored if only one item +of the selected data type, such as PLTE, is allowed. If "seq" is not +-1, and multiple items are allowed for the data type identified in +the mask, such as text or sPLT, only the n'th item in the structure +is freed, where n is "seq". + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_zalloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + mask - which data elements are affected + same choices as in png_free_data() + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + +This function only affects data that has already been allocated. +You can call this function after reading the PNG data but before calling +any png_set_*() functions, to control whether the user or the png_set_*() +function is responsible for freeing any existing data that might be present, +and again after the png_set_*() functions to control whether the user +or png_destroy_*() is supposed to free the data. When the user assumes +responsibility for libpng-allocated data, the application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_zalloc() to allocate it. + +If you allocated your row_pointers in a single block, as suggested above in +the description of the high level read interface, you must not transfer +responsibility for freeing it to the png_set_rows or png_read_destroy function, +because they would also try to free the individual row_pointers[i]. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. + +The png_free_data() function will turn off the "valid" flag for anything +it frees. If you need to turn the flag off for a chunk that was freed by your +application instead of by libpng, you can use + + png_set_invalid(png_ptr, info_ptr, mask); + mask - identifies the chunks to be made invalid, + containing the logical OR of one or + more of + PNG_INFO_gAMA, PNG_INFO_sBIT, + PNG_INFO_cHRM, PNG_INFO_PLTE, + PNG_INFO_tRNS, PNG_INFO_bKGD, + PNG_INFO_hIST, PNG_INFO_pHYs, + PNG_INFO_oFFs, PNG_INFO_tIME, + PNG_INFO_pCAL, PNG_INFO_sRGB, + PNG_INFO_iCCP, PNG_INFO_sPLT, + PNG_INFO_sCAL, PNG_INFO_IDAT + +For a more compact example of reading a PNG image, see the file example.c. + +Reading PNG files progressively + +The progressive reader is slightly different then the non-progressive +reader. Instead of calling png_read_info(), png_read_rows(), and +png_read_end(), you make one call to png_process_data(), which calls +callbacks when it has the info, a row, or the end of the image. You +set up these callbacks with png_set_progressive_read_fn(). You don't +have to worry about the input/output functions of libpng, as you are +giving the library the data directly in png_process_data(). I will +assume that you have read the section on reading PNG files above, +so I will only highlight the differences (although I will show +all of the code). + +png_structp png_ptr; +png_infop info_ptr; + + /* An example code fragment of how you would + initialize the progressive reader in your + application. */ + int + initialize_png_reader() + { + png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + if (!png_ptr) + return (ERROR); + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, (png_infopp)NULL, + (png_infopp)NULL); + return (ERROR); + } + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + + /* This one's new. You can provide functions + to be called when the header info is valid, + when each row is completed, and when the image + is finished. If you aren't using all functions, + you can specify NULL parameters. Even when all + three functions are NULL, you need to call + png_set_progressive_read_fn(). You can use + any struct as the user_ptr (cast to a void pointer + for the function call), and retrieve the pointer + from inside the callbacks using the function + + png_get_progressive_ptr(png_ptr); + + which will return a void pointer, which you have + to cast appropriately. + */ + png_set_progressive_read_fn(png_ptr, (void *)user_ptr, + info_callback, row_callback, end_callback); + + return 0; + } + + /* A code fragment that you call as you receive blocks + of data */ + int + process_data(png_bytep buffer, png_uint_32 length) + { + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + + /* This one's new also. Simply give it a chunk + of data from the file stream (in order, of + course). On machines with segmented memory + models machines, don't give it any more than + 64K. The library seems to run fine with sizes + of 4K. Although you can give it much less if + necessary (I assume you can give it chunks of + 1 byte, I haven't tried less then 256 bytes + yet). When this function returns, you may + want to display any rows that were generated + in the row callback if you don't already do + so there. + */ + png_process_data(png_ptr, info_ptr, buffer, length); + return 0; + } + + /* This function is called (as set by + png_set_progressive_read_fn() above) when enough data + has been supplied so all of the header has been + read. + */ + void + info_callback(png_structp png_ptr, png_infop info) + { + /* Do any setup here, including setting any of + the transformations mentioned in the Reading + PNG files section. For now, you _must_ call + either png_start_read_image() or + png_read_update_info() after all the + transformations are set (even if you don't set + any). You may start getting rows before + png_process_data() returns, so this is your + last chance to prepare for that. + */ + } + + /* This function is called when each row of image + data is complete */ + void + row_callback(png_structp png_ptr, png_bytep new_row, + png_uint_32 row_num, int pass) + { + /* If the image is interlaced, and you turned + on the interlace handler, this function will + be called for every row in every pass. Some + of these rows will not be changed from the + previous pass. When the row is not changed, + the new_row variable will be NULL. The rows + and passes are called in order, so you don't + really need the row_num and pass, but I'm + supplying them because it may make your life + easier. + + For the non-NULL rows of interlaced images, + you must call png_progressive_combine_row() + passing in the row and the old row. You can + call this function for NULL rows (it will just + return) and for non-interlaced images (it just + does the memcpy for you) if it will make the + code easier. Thus, you can just do this for + all cases: + */ + + png_progressive_combine_row(png_ptr, old_row, + new_row); + + /* where old_row is what was displayed for + previously for the row. Note that the first + pass (pass == 0, really) will completely cover + the old row, so the rows do not have to be + initialized. After the first pass (and only + for interlaced images), you will have to pass + the current row, and the function will combine + the old row and the new row. + */ + } + + void + end_callback(png_structp png_ptr, png_infop info) + { + /* This function is called after the whole image + has been read, including any chunks after the + image (up to and including the IEND). You + will usually have the same info chunk as you + had in the header, although some data may have + been added to the comments and time fields. + + Most people won't do much here, perhaps setting + a flag that marks the image as finished. + */ + } + + + +IV. Writing + +Much of this is very similar to reading. However, everything of +importance is repeated here, so you won't have to constantly look +back up in the reading section to understand writing. + +Setup + +You will want to do the I/O initialization before you get into libpng, +so if it doesn't work, you don't have anything to undo. If you are not +using the standard I/O functions, you will need to replace them with +custom writing functions. See the discussion under Customizing libpng. + + FILE *fp = fopen(file_name, "wb"); + if (!fp) + { + return (ERROR); + } + +Next, png_struct and png_info need to be allocated and initialized. +As these can be both relatively large, you may not want to store these +on the stack, unless you have stack space to spare. Of course, you +will want to check if they return NULL. If you are also reading, +you won't want to name your read structure and your write structure +both "png_ptr"; you can call them anything you like, such as +"read_ptr" and "write_ptr". Look at pngtest.c, for example. + + png_structp png_ptr = png_create_write_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + if (!png_ptr) + return (ERROR); + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, + (png_infopp)NULL); + return (ERROR); + } + +If you want to use your own memory allocation routines, +define PNG_USER_MEM_SUPPORTED and use +png_create_write_struct_2() instead of png_create_write_struct(): + + png_structp png_ptr = png_create_write_struct_2 + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn, (png_voidp) + user_mem_ptr, user_malloc_fn, user_free_fn); + +After you have these structures, you will need to set up the +error handling. When libpng encounters an error, it expects to +longjmp() back to your routine. Therefore, you will need to call +setjmp() and pass the png_jmpbuf(png_ptr). If you +write the file from different routines, you will need to update +the png_jmpbuf(png_ptr) every time you enter a new routine that will +call a png_*() function. See your documentation of setjmp/longjmp +for your compiler for more information on setjmp/longjmp. See +the discussion on libpng error handling in the Customizing Libpng +section below for more information on the libpng error handling. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + return (ERROR); + } + ... + return; + +If you would rather avoid the complexity of setjmp/longjmp issues, +you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +Now you need to set up the output code. The default for libpng is to +use the C function fwrite(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. Again, if you wish to handle writing data in +another way, see the discussion on libpng I/O handling in the Customizing +Libpng section below. + + png_init_io(png_ptr, fp); + +Write callbacks + +At this point, you can set up a callback function that will be +called after each row has been written, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void write_row_callback(png_ptr, png_uint_32 row, + int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "write_row_callback") + +To inform libpng about your function, use + + png_set_write_status_fn(png_ptr, write_row_callback); + +You now have the option of modifying how the compression library will +run. The following functions are mainly for testing, but may be useful +in some cases, like if you need to write PNG files extremely fast and +are willing to give up some compression, or if you want to get the +maximum possible compression at the expense of slower writing. If you +have no special needs in this area, let the library do what it wants by +not calling this function at all, as it has been tuned to deliver a good +speed/compression ratio. The second parameter to png_set_filter() is +the filter method, for which the only valid values are 0 (as of the +July 1999 PNG specification, version 1.2) or 64 (if you are writing +a PNG datastream that is to be embedded in a MNG datastream). The third +parameter is a flag that indicates which filter type(s) are to be tested +for each scanline. See the PNG specification for details on the specific filter +types. + + + /* turn on or off filtering, and/or choose + specific filters. You can use either a single + PNG_FILTER_VALUE_NAME or the logical OR of one + or more PNG_FILTER_NAME masks. */ + png_set_filter(png_ptr, 0, + PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | + PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | + PNG_FILTER_UP | PNG_FILTER_VALUE_UP | + PNG_FILTER_AVE | PNG_FILTER_VALUE_AVE | + PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH| + PNG_ALL_FILTERS); + +If an application +wants to start and stop using particular filters during compression, +it should start out with all of the filters (to ensure that the previous +row of pixels will be stored in case it's needed later), and then add +and remove them after the start of compression. + +If you are writing a PNG datastream that is to be embedded in a MNG +datastream, the second parameter can be either 0 or 64. + +The png_set_compression_*() functions interface to the zlib compression +library, and should mostly be ignored unless you really know what you are +doing. The only generally useful call is png_set_compression_level() +which changes how much time zlib spends on trying to compress the image +data. See the Compression Library (zlib.h and algorithm.txt, distributed +with zlib) for details on the compression levels. + + /* set the zlib compression level */ + png_set_compression_level(png_ptr, + Z_BEST_COMPRESSION); + + /* set other zlib parameters */ + png_set_compression_mem_level(png_ptr, 8); + png_set_compression_strategy(png_ptr, + Z_DEFAULT_STRATEGY); + png_set_compression_window_bits(png_ptr, 15); + png_set_compression_method(png_ptr, 8); + png_set_compression_buffer_size(png_ptr, 8192) + +extern PNG_EXPORT(void,png_set_zbuf_size) + +Setting the contents of info for output + +You now need to fill in the png_info structure with all the data you +wish to write before the actual image. Note that the only thing you +are allowed to write after the image is the text chunks and the time +chunk (as of PNG Specification 1.2, anyway). See png_write_end() and +the latest PNG specification for more information on that. If you +wish to write them before the image, fill them in now, and flag that +data as being valid. If you want to wait until after the data, don't +fill them until png_write_end(). For all the fields in png_info and +their data types, see png.h. For explanations of what the fields +contain, see the PNG specification. + +Some of the more important parts of the png_info are: + + png_set_IHDR(png_ptr, info_ptr, width, height, + bit_depth, color_type, interlace_type, + compression_type, filter_method) + width - holds the width of the image + in pixels (up to 2^31). + height - holds the height of the image + in pixels (up to 2^31). + bit_depth - holds the bit depth of one of the + image channels. + (valid values are 1, 2, 4, 8, 16 + and depend also on the + color_type. See also significant + bits (sBIT) below). + color_type - describes which color/alpha + channels are present. + PNG_COLOR_TYPE_GRAY + (bit depths 1, 2, 4, 8, 16) + PNG_COLOR_TYPE_GRAY_ALPHA + (bit depths 8, 16) + PNG_COLOR_TYPE_PALETTE + (bit depths 1, 2, 4, 8) + PNG_COLOR_TYPE_RGB + (bit_depths 8, 16) + PNG_COLOR_TYPE_RGB_ALPHA + (bit_depths 8, 16) + + PNG_COLOR_MASK_PALETTE + PNG_COLOR_MASK_COLOR + PNG_COLOR_MASK_ALPHA + + interlace_type - PNG_INTERLACE_NONE or + PNG_INTERLACE_ADAM7 + compression_type - (must be + PNG_COMPRESSION_TYPE_DEFAULT) + filter_method - (must be PNG_FILTER_TYPE_DEFAULT + or, if you are writing a PNG to + be embedded in a MNG datastream, + can also be + PNG_INTRAPIXEL_DIFFERENCING) + + png_set_PLTE(png_ptr, info_ptr, palette, + num_palette); + palette - the palette for the file + (array of png_color) + num_palette - number of entries in the palette + + png_set_gAMA(png_ptr, info_ptr, gamma); + gamma - the gamma the image was created + at (PNG_INFO_gAMA) + + png_set_sRGB(png_ptr, info_ptr, srgb_intent); + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of + the sRGB chunk means that the pixel + data is in the sRGB color space. + This chunk also implies specific + values of gAMA and cHRM. Rendering + intent is the CSS-1 property that + has been defined by the International + Color Consortium + (http://www.color.org). + It can be one of + PNG_sRGB_INTENT_SATURATION, + PNG_sRGB_INTENT_PERCEPTUAL, + PNG_sRGB_INTENT_ABSOLUTE, or + PNG_sRGB_INTENT_RELATIVE. + + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, + srgb_intent); + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of the + sRGB chunk means that the pixel + data is in the sRGB color space. + This function also causes gAMA and + cHRM chunks with the specific values + that are consistent with sRGB to be + written. + + png_set_iCCP(png_ptr, info_ptr, name, compression_type, + profile, proflen); + name - The profile name. + compression - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + profile - International Color Consortium color + profile data. May contain NULs. + proflen - length of profile data in bytes. + + png_set_sBIT(png_ptr, info_ptr, sig_bit); + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, red, + green, and blue channels, whichever are + appropriate for the given color type + (png_color_16) + + png_set_tRNS(png_ptr, info_ptr, trans, num_trans, + trans_values); + trans - array of transparent entries for + palette (PNG_INFO_tRNS) + trans_values - graylevel or color sample values of + the single transparent color for + non-paletted images (PNG_INFO_tRNS) + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + png_set_hIST(png_ptr, info_ptr, hist); + (PNG_INFO_hIST) + hist - histogram of palette (array of + png_uint_16) + + png_set_tIME(png_ptr, info_ptr, mod_time); + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_set_bKGD(png_ptr, info_ptr, background); + background - background color (PNG_VALID_bKGD) + + png_set_text(png_ptr, info_ptr, text_ptr, num_text); + text_ptr - array of png_text holding image + comments + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + text_ptr[i].text - text comments for current + keyword. Can be NULL or empty. + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + text_ptr[i].lang - language of comment (NULL or + empty for unknown). + text_ptr[i].translated_keyword - keyword in UTF-8 (NULL + or empty for unknown). + num_text - number of comments + + png_set_sPLT(png_ptr, info_ptr, &palette_ptr, + num_spalettes); + palette_ptr - array of png_sPLT_struct structures + to be added to the list of palettes + in the info structure. + num_spalettes - number of palette structures to be + added. + + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, + unit_type); + offset_x - positive offset from the left + edge of the screen + offset_y - positive offset from the top + edge of the screen + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, + unit_type); + res_x - pixels/unit physical resolution + in x direction + res_y - pixels/unit physical resolution + in y direction + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_set_sCAL(png_ptr, info_ptr, unit, width, height) + unit - physical scale units (an integer) + width - width of a pixel in physical scale units + height - height of a pixel in physical scale units + (width and height are doubles) + + png_set_sCAL_s(png_ptr, info_ptr, unit, width, height) + unit - physical scale units (an integer) + width - width of a pixel in physical scale units + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + png_set_unknown_chunks(png_ptr, info_ptr, &unknowns, + num_unknowns) + unknowns - array of png_unknown_chunk + structures holding unknown chunks + unknowns[i].name - name of unknown chunk + unknowns[i].data - data of unknown chunk + unknowns[i].size - size of unknown chunk's data + unknowns[i].location - position to write chunk in file + 0: do not write chunk + PNG_HAVE_IHDR: before PLTE + PNG_HAVE_PLTE: before IDAT + PNG_AFTER_IDAT: after IDAT + +The "location" member is set automatically according to +what part of the output file has already been written. +You can change its value after calling png_set_unknown_chunks() +as demonstrated in pngtest.c. Within each of the "locations", +the chunks are sequenced according to their position in the +structure (that is, the value of "i", which is the order in which +the chunk was either read from the input file or defined with +png_set_unknown_chunks). + +A quick word about text and num_text. text is an array of png_text +structures. num_text is the number of valid structures in the array. +Each png_text structure holds a language code, a keyword, a text value, +and a compression type. + +The compression types have the same valid numbers as the compression +types of the image data. Currently, the only valid number is zero. +However, you can store text either compressed or uncompressed, unlike +images, which always have to be compressed. So if you don't want the +text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE. +Because tEXt and zTXt chunks don't have a language field, if you +specify PNG_TEXT_COMPRESSION_NONE or PNG_TEXT_COMPRESSION_zTXt +any language code or translated keyword will not be written out. + +Until text gets around 1000 bytes, it is not worth compressing it. +After the text has been written out to the file, the compression type +is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR, +so that it isn't written out again at the end (in case you are calling +png_write_end() with the same struct. + +The keywords that are given in the PNG Specification are: + + Title Short (one line) title or + caption for image + Author Name of image's creator + Description Description of image (possibly long) + Copyright Copyright notice + Creation Time Time of original image creation + (usually RFC 1123 format, see below) + Software Software used to create the image + Disclaimer Legal disclaimer + Warning Warning of nature of content + Source Device used to create the image + Comment Miscellaneous comment; conversion + from other image format + +The keyword-text pairs work like this. Keywords should be short +simple descriptions of what the comment is about. Some typical +keywords are found in the PNG specification, as is some recommendations +on keywords. You can repeat keywords in a file. You can even write +some text before the image and some after. For example, you may want +to put a description of the image before the image, but leave the +disclaimer until after, so viewers working over modem connections +don't have to wait for the disclaimer to go over the modem before +they start seeing the image. Finally, keywords should be full +words, not abbreviations. Keywords and text are in the ISO 8859-1 +(Latin-1) character set (a superset of regular ASCII) and can not +contain NUL characters, and should not contain control or other +unprintable characters. To make the comments widely readable, stick +with basic ASCII, and avoid machine specific character set extensions +like the IBM-PC character set. The keyword must be present, but +you can leave off the text string on non-compressed pairs. +Compressed pairs must have a text string, as only the text string +is compressed anyway, so the compression would be meaningless. + +PNG supports modification time via the png_time structure. Two +conversion routines are provided, png_convert_from_time_t() for +time_t and png_convert_from_struct_tm() for struct tm. The +time_t routine uses gmtime(). You don't have to use either of +these, but if you wish to fill in the png_time structure directly, +you should provide the time in universal time (GMT) if possible +instead of your local time. Note that the year number is the full +year (e.g. 1998, rather than 98 - PNG is year 2000 compliant!), and +that months start with 1. + +If you want to store the time of the original image creation, you should +use a plain tEXt chunk with the "Creation Time" keyword. This is +necessary because the "creation time" of a PNG image is somewhat vague, +depending on whether you mean the PNG file, the time the image was +created in a non-PNG format, a still photo from which the image was +scanned, or possibly the subject matter itself. In order to facilitate +machine-readable dates, it is recommended that the "Creation Time" +tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"), +although this isn't a requirement. Unlike the tIME chunk, the +"Creation Time" tEXt chunk is not expected to be automatically changed +by the software. To facilitate the use of RFC 1123 dates, a function +png_convert_to_rfc1123(png_timep) is provided to convert from PNG +time to an RFC 1123 format string. + +Writing unknown chunks + +You can use the png_set_unknown_chunks function to queue up chunks +for writing. You give it a chunk name, raw data, and a size; that's +all there is to it. The chunks will be written by the next following +png_write_info_before_PLTE, png_write_info, or png_write_end function. +Any chunks previously read into the info structure's unknown-chunk +list will also be written out in a sequence that satisfies the PNG +specification's ordering rules. + +The high-level write interface + +At this point there are two ways to proceed; through the high-level +write interface, or through a sequence of low-level write operations. +You can use the high-level interface if your image data is present +in the info structure. All defined output +transformations are permitted, enabled by the following masks. + + PNG_TRANSFORM_IDENTITY No transformation + PNG_TRANSFORM_PACKING Pack 1, 2 and 4-bit samples + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + PNG_TRANSFORM_STRIP_FILLER Strip out filler bytes. + +If you have valid image data in the info structure (you can use +png_set_rows() to put image data in the info structure), simply do this: + + png_write_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the logical OR of some set of +transformation flags. This call is equivalent to png_write_info(), +followed the set of transformations indicated by the transform mask, +then png_write_image(), and finally png_write_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future output transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_write_png(). + +The low-level write interface + +If you are going the low-level route instead, you are now ready to +write all the file information up to the actual image data. You do +this with a call to png_write_info(). + + png_write_info(png_ptr, info_ptr); + +Note that there is one transformation you may need to do before +png_write_info(). In PNG files, the alpha channel in an image is the +level of opacity. If your data is supplied as a level of +transparency, you can invert the alpha channel before you write it, so +that 0 is fully transparent and 255 (in 8-bit or paletted images) or +65535 (in 16-bit images) is fully opaque, with + + png_set_invert_alpha(png_ptr); + +This must appear before png_write_info() instead of later with the +other transformations because in the case of paletted images the tRNS +chunk data has to be inverted before the tRNS chunk is written. If +your image is not a paletted image, the tRNS data (which in such cases +represents a single color to be rendered as transparent) won't need to +be changed, and you can safely do this transformation after your +png_write_info() call. + +If you need to write a private chunk that you want to appear before +the PLTE chunk when PLTE is present, you can write the PNG info in +two steps, and insert code to write your own chunk between them: + + png_write_info_before_PLTE(png_ptr, info_ptr); + png_set_unknown_chunks(png_ptr, info_ptr, ...); + png_write_info(png_ptr, info_ptr); + +After you've written the file information, you can set up the library +to handle any special transformations of the image data. The various +ways to transform the data will be described in the order that they +should occur. This is important, as some of these change the color +type and/or bit depth of the data, and some others only work on +certain color types and bit depths. Even though each transformation +checks to see if it has data that it can do something with, you should +make sure to only enable a transformation if it will be valid for the +data. For example, don't swap red and blue on grayscale data. + +PNG files store RGB pixels packed into 3 or 6 bytes. This code tells +the library to strip input data that has 4 or 8 bytes per pixel down +to 3 or 6 bytes (or strip 2 or 4-byte grayscale+filler data to 1 or 2 +bytes per pixel). + + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); + +where the 0 is unused, and the location is either PNG_FILLER_BEFORE or +PNG_FILLER_AFTER, depending upon whether the filler byte in the pixel +is stored XRGB or RGBX. + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit files. +If the data is supplied at 1 pixel per byte, use this code, which will +correctly pack the pixels into a single byte: + + png_set_packing(png_ptr); + +PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. If your +data is of another bit depth, you can write an sBIT chunk into the +file so that decoders can recover the original data if desired. + + /* Set the true bit depth of the image data */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit.red = true_bit_depth; + sig_bit.green = true_bit_depth; + sig_bit.blue = true_bit_depth; + } + else + { + sig_bit.gray = true_bit_depth; + } + if (color_type & PNG_COLOR_MASK_ALPHA) + { + sig_bit.alpha = true_bit_depth; + } + + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + +If the data is stored in the row buffer in a bit depth other than +one supported by PNG (e.g. 3 bit data in the range 0-7 for a 4-bit PNG), +this will scale the values to appear to be the correct bit depth as +is required by PNG. + + png_set_shift(png_ptr, &sig_bit); + +PNG files store 16 bit pixels in network byte order (big-endian, +ie. most significant bits first). This code would be used if they are +supplied the other way (little-endian, i.e. least significant bits +first, the way PCs store them): + + if (bit_depth > 8) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +PNG files store 3 color pixels in red, green, blue order. This code +would be used if they are supplied as blue, green, red: + + png_set_bgr(png_ptr); + +PNG files describe monochrome as black being zero and white being +one. This code would be used if the pixels are supplied with this reversed +(black being one and white being zero): + + png_set_invert_mono(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_write_user_transform_fn(png_ptr, + write_transform_fn); + +You must supply the function + + void write_transform_fn(png_ptr ptr, row_info_ptr + row_info, png_bytep data) + +See pngtest.c for a working example. Your function will be called +before any of the other transformations are processed. + +You can also set up a pointer to a user structure for use by your +callback function. + + png_set_user_transform_info(png_ptr, user_ptr, 0, 0); + +The user_channels and user_depth parameters of this function are ignored +when writing; you can set them to zero as shown. + +You can retrieve the pointer via the function png_get_user_transform_ptr(). +For example: + + voidp write_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +It is possible to have libpng flush any pending output, either manually, +or automatically after a certain number of lines have been written. To +flush the output stream a single time call: + + png_write_flush(png_ptr); + +and to have libpng flush the output stream periodically after a certain +number of scanlines have been written, call: + + png_set_flush(png_ptr, nrows); + +Note that the distance between rows is from the last time png_write_flush() +was called, or the first row of the image if it has never been called. +So if you write 50 lines, and then png_set_flush 25, it will flush the +output on the next scanline, and every 25 lines thereafter, unless +png_write_flush() is called before 25 more lines have been written. +If nrows is too small (less than about 10 lines for a 640 pixel wide +RGB image) the image compression may decrease noticeably (although this +may be acceptable for real-time applications). Infrequent flushing will +only degrade the compression performance by a few percent over images +that do not use flushing. + +Writing the image data + +That's it for the transformations. Now you can write the image data. +The simplest way to do this is in one function call. If you have the +whole image in memory, you can just call png_write_image() and libpng +will write the image. You will need to pass in an array of pointers to +each row. This function automatically handles interlacing, so you don't +need to call png_set_interlace_handling() or call this function multiple +times, or any of that other stuff necessary with png_write_rows(). + + png_write_image(png_ptr, row_pointers); + +where row_pointers is: + + png_byte *row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to write the whole image at once, you can +use png_write_rows() instead. If the file is not interlaced, +this is simple: + + png_write_rows(png_ptr, row_pointers, + number_of_rows); + +row_pointers is the same as in the png_write_image() call. + +If you are just writing one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + + png_write_row(png_ptr, row_pointer); + +When the file is interlaced, things can get a good deal more +complicated. The only currently (as of the PNG Specification +version 1.2, dated July 1999) defined interlacing scheme for PNG files +is the "Adam7" interlace scheme, that breaks down an +image into seven smaller images of varying size. libpng will build +these images for you, or you can do them yourself. If you want to +build them yourself, see the PNG specification for details of which +pixels to write when. + +If you don't want libpng to handle the interlacing details, just +use png_set_interlace_handling() and call png_write_rows() the +correct number of times to write all seven sub-images. + +If you want libpng to build the sub-images, call this before you start +writing any rows: + + number_of_passes = + png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this +is seven, but may change if another interlace type is added. + +Then write the complete image number_of_passes times. + + png_write_rows(png_ptr, row_pointers, + number_of_rows); + +As some of these rows are not used, and thus return immediately, +you may want to read about interlacing in the PNG specification, +and only update the rows that are actually used. + +Finishing a sequential write + +After you are finished writing the image, you should finish writing +the file. If you are interested in writing comments or time, you should +pass an appropriately filled png_info pointer. If you are not interested, +you can pass NULL. + + png_write_end(png_ptr, info_ptr); + +When you are done, you can free all memory used by libpng like this: + + png_destroy_write_struct(&png_ptr, &info_ptr); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + mask - identifies data to be freed, a mask + containing the logical OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + seq - sequence number of item to be freed + (-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those +cases do nothing. The "seq" parameter is ignored if only one item +of the selected data type, such as PLTE, is allowed. If "seq" is not +-1, and multiple items are allowed for the data type identified in +the mask, such as text or sPLT, only the n'th item in the structure +is freed, where n is "seq". + +If you allocated data such as a palette that you passed +in to libpng with png_set_*, you must not free it until just before the call to +png_destroy_write_struct(). + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_zalloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + mask - which data elements are affected + same choices as in png_free_data() + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + +For example, to transfer responsibility for some data from a read structure +to a write structure, you could use + + png_data_freer(read_ptr, read_info_ptr, + PNG_USER_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + png_data_freer(write_ptr, write_info_ptr, + PNG_DESTROY_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + +thereby briefly reassigning responsibility for freeing to the user but +immediately afterwards reassigning it once more to the write_destroy +function. Having done this, it would then be safe to destroy the read +structure and continue to use the PLTE, tRNS, and hIST data in the write +structure. + +This function only affects data that has already been allocated. +You can call this function before calling after the png_set_*() functions +to control whether the user or png_destroy_*() is supposed to free the data. +When the user assumes responsibility for libpng-allocated data, the +application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_zalloc() to allocate it. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. +For a more compact example of writing a PNG image, see the file example.c. + +V. Modifying/Customizing libpng: + +There are three issues here. The first is changing how libpng does +standard things like memory allocation, input/output, and error handling. +The second deals with more complicated things like adding new chunks, +adding new transformations, and generally changing how libpng works. +Both of those are compile-time issues; that is, they are generally +determined at the time the code is written, and there is rarely a need +to provide the user with a means of changing them. The third is a +run-time issue: choosing between and/or tuning one or more alternate +versions of computationally intensive routines; specifically, optimized +assembly-language (and therefore compiler- and platform-dependent) +versions. + +Memory allocation, input/output, and error handling + +All of the memory allocation, input/output, and error handling in libpng +goes through callbacks that are user-settable. The default routines are +in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively. To change +these functions, call the appropriate png_set_*_fn() function. + +Memory allocation is done through the functions png_malloc() +and png_free(). These currently just call the standard C functions. If +your pointers can't access more then 64K at a time, you will want to set +MAXSEG_64K in zlib.h. Since it is unlikely that the method of handling +memory allocation on a platform will change between applications, these +functions must be modified in the library at compile time. If you prefer +to use a different method of allocating and freeing data, you can use +png_create_read_struct_2() or png_create_write_struct_2() to register +your own functions as described above. +These functions also provide a void pointer that can be retrieved via + + mem_ptr=png_get_mem_ptr(png_ptr); + +Your replacement memory functions must have prototypes as follows: + + png_voidp malloc_fn(png_structp png_ptr, + png_size_t size); + void free_fn(png_structp png_ptr, png_voidp ptr); + +Your malloc_fn() must return NULL in case of failure. The png_malloc() +function will normally call png_error() if it receives a NULL from the +system memory allocator or from your replacement malloc_fn(). + +Input/Output in libpng is done through png_read() and png_write(), +which currently just call fread() and fwrite(). The FILE * is stored in +png_struct and is initialized via png_init_io(). If you wish to change +the method of I/O, the library supplies callbacks that you can set +through the function png_set_read_fn() and png_set_write_fn() at run +time, instead of calling the png_init_io() function. These functions +also provide a void pointer that can be retrieved via the function +png_get_io_ptr(). For example: + + png_set_read_fn(png_structp read_ptr, + voidp read_io_ptr, png_rw_ptr read_data_fn) + + png_set_write_fn(png_structp write_ptr, + voidp write_io_ptr, png_rw_ptr write_data_fn, + png_flush_ptr output_flush_fn); + + voidp read_io_ptr = png_get_io_ptr(read_ptr); + voidp write_io_ptr = png_get_io_ptr(write_ptr); + +The replacement I/O functions must have prototypes as follows: + + void user_read_data(png_structp png_ptr, + png_bytep data, png_size_t length); + void user_write_data(png_structp png_ptr, + png_bytep data, png_size_t length); + void user_flush_data(png_structp png_ptr); + +Supplying NULL for the read, write, or flush functions sets them back +to using the default C stream functions. It is an error to read from +a write stream, and vice versa. + +Error handling in libpng is done through png_error() and png_warning(). +Errors handled through png_error() are fatal, meaning that png_error() +should never return to its caller. Currently, this is handled via +setjmp() and longjmp() (unless you have compiled libpng with +PNG_SETJMP_NOT_SUPPORTED, in which case it is handled via PNG_ABORT()), +but you could change this to do things like exit() if you should wish. + +On non-fatal errors, png_warning() is called +to print a warning message, and then control returns to the calling code. +By default png_error() and png_warning() print a message on stderr via +fprintf() unless the library is compiled with PNG_NO_CONSOLE_IO defined +(because you don't want the messages) or PNG_NO_STDIO defined (because +fprintf() isn't available). If you wish to change the behavior of the error +functions, you will need to set up your own message callbacks. These +functions are normally supplied at the time that the png_struct is created. +It is also possible to redirect errors and warnings to your own replacement +functions after png_create_*_struct() has been called by calling: + + png_set_error_fn(png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warning_fn); + + png_voidp error_ptr = png_get_error_ptr(png_ptr); + +If NULL is supplied for either error_fn or warning_fn, then the libpng +default function will be used, calling fprintf() and/or longjmp() if a +problem is encountered. The replacement error functions should have +parameters as follows: + + void user_error_fn(png_structp png_ptr, + png_const_charp error_msg); + void user_warning_fn(png_structp png_ptr, + png_const_charp warning_msg); + +The motivation behind using setjmp() and longjmp() is the C++ throw and +catch exception handling methods. This makes the code much easier to write, +as there is no need to check every return code of every function call. +However, there are some uncertainties about the status of local variables +after a longjmp, so the user may want to be careful about doing anything after +setjmp returns non-zero besides returning itself. Consult your compiler +documentation for more details. For an alternative approach, you may wish +to use the "cexcept" facility (see http://cexcept.sourceforge.net). + +Custom chunks + +If you need to read or write custom chunks, you may need to get deeper +into the libpng code. The library now has mechanisms for storing +and writing chunks of unknown type; you can even declare callbacks +for custom chunks. Hoewver, this may not be good enough if the +library code itself needs to know about interactions between your +chunk and existing `intrinsic' chunks. + +If you need to write a new intrinsic chunk, first read the PNG +specification. Acquire a first level of +understanding of how it works. Pay particular attention to the +sections that describe chunk names, and look at how other chunks were +designed, so you can do things similarly. Second, check out the +sections of libpng that read and write chunks. Try to find a chunk +that is similar to yours and use it as a template. More details can +be found in the comments inside the code. It is best to handle unknown +chunks in a generic method, via callback functions, instead of by +modifying libpng functions. + +If you wish to write your own transformation for the data, look through +the part of the code that does the transformations, and check out some of +the simpler ones to get an idea of how they work. Try to find a similar +transformation to the one you want to add and copy off of it. More details +can be found in the comments inside the code itself. + +Configuring for 16 bit platforms + +You will want to look into zconf.h to tell zlib (and thus libpng) that +it cannot allocate more then 64K at a time. Even if you can, the memory +won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K. + +Configuring for DOS + +For DOS users who only have access to the lower 640K, you will +have to limit zlib's memory usage via a png_set_compression_mem_level() +call. See zlib.h or zconf.h in the zlib library for more information. + +Configuring for Medium Model + +Libpng's support for medium model has been tested on most of the popular +compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets +defined, and FAR gets defined to far in pngconf.h, and you should be +all set. Everything in the library (except for zlib's structure) is +expecting far data. You must use the typedefs with the p or pp on +the end for pointers (or at least look at them and be careful). Make +note that the rows of data are defined as png_bytepp, which is an +unsigned char far * far *. + +Configuring for gui/windowing platforms: + +You will need to write new error and warning functions that use the GUI +interface, as described previously, and set them to be the error and +warning functions at the time that png_create_*_struct() is called, +in order to have them available during the structure initialization. +They can be changed later via png_set_error_fn(). On some compilers, +you may also have to change the memory allocators (png_malloc, etc.). + +Configuring for compiler xxx: + +All includes for libpng are in pngconf.h. If you need to add/change/delete +an include, this is the place to do it. The includes that are not +needed outside libpng are protected by the PNG_INTERNAL definition, +which is only defined for those routines inside libpng itself. The +files in libpng proper only include png.h, which includes pngconf.h. + +Configuring zlib: + +There are special functions to configure the compression. Perhaps the +most useful one changes the compression level, which currently uses +input compression values in the range 0 - 9. The library normally +uses the default compression level (Z_DEFAULT_COMPRESSION = 6). Tests +have shown that for a large majority of images, compression values in +the range 3-6 compress nearly as well as higher levels, and do so much +faster. For online applications it may be desirable to have maximum speed +(Z_BEST_SPEED = 1). With versions of zlib after v0.99, you can also +specify no compression (Z_NO_COMPRESSION = 0), but this would create +files larger than just storing the raw bitmap. You can specify the +compression level by calling: + + png_set_compression_level(png_ptr, level); + +Another useful one is to reduce the memory level used by the library. +The memory level defaults to 8, but it can be lowered if you are +short on memory (running DOS, for example, where you only have 640K). +Note that the memory level does have an effect on compression; among +other things, lower levels will result in sections of incompressible +data being emitted in smaller stored blocks, with a correspondingly +larger relative overhead of up to 15% in the worst case. + + png_set_compression_mem_level(png_ptr, level); + +The other functions are for configuring zlib. They are not recommended +for normal use and may result in writing an invalid PNG file. See +zlib.h for more information on what these mean. + + png_set_compression_strategy(png_ptr, + strategy); + png_set_compression_window_bits(png_ptr, + window_bits); + png_set_compression_method(png_ptr, method); + png_set_compression_buffer_size(png_ptr, size); + +Controlling row filtering + +If you want to control whether libpng uses filtering or not, which +filters are used, and how it goes about picking row filters, you +can call one of these functions. The selection and configuration +of row filters can have a significant impact on the size and +encoding speed and a somewhat lesser impact on the decoding speed +of an image. Filtering is enabled by default for RGB and grayscale +images (with and without alpha), but not for paletted images nor +for any images with bit depths less than 8 bits/pixel. + +The 'method' parameter sets the main filtering method, which is +currently only '0' in the PNG 1.2 specification. The 'filters' +parameter sets which filter(s), if any, should be used for each +scanline. Possible values are PNG_ALL_FILTERS and PNG_NO_FILTERS +to turn filtering on and off, respectively. + +Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB, +PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise +ORed together with '|' to specify one or more filters to use. +These filters are described in more detail in the PNG specification. +If you intend to change the filter type during the course of writing +the image, you should start with flags set for all of the filters +you intend to use so that libpng can initialize its internal +structures appropriately for all of the filter types. (Note that this +means the first row must always be adaptively filtered, because libpng +currently does not allocate the filter buffers until png_write_row() +is called for the first time.) + + filters = PNG_FILTER_NONE | PNG_FILTER_SUB + PNG_FILTER_UP | PNG_FILTER_AVE | + PNG_FILTER_PAETH | PNG_ALL_FILTERS; + + png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, + filters); + The second parameter can also be + PNG_INTRAPIXEL_DIFFERENCING if you are + writing a PNG to be embedded in a MNG + datastream. This parameter must be the + same as the value of filter_method used + in png_set_IHDR(). + +It is also possible to influence how libpng chooses from among the +available filters. This is done in one or both of two ways - by +telling it how important it is to keep the same filter for successive +rows, and by telling it the relative computational costs of the filters. + + double weights[3] = {1.5, 1.3, 1.1}, + costs[PNG_FILTER_VALUE_LAST] = + {1.0, 1.3, 1.3, 1.5, 1.7}; + + png_set_filter_heuristics(png_ptr, + PNG_FILTER_HEURISTIC_WEIGHTED, 3, + weights, costs); + +The weights are multiplying factors that indicate to libpng that the +row filter should be the same for successive rows unless another row filter +is that many times better than the previous filter. In the above example, +if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a +"sum of absolute differences" 1.5 x 1.3 times higher than other filters +and still be chosen, while the NONE filter could have a sum 1.1 times +higher than other filters and still be chosen. Unspecified weights are +taken to be 1.0, and the specified weights should probably be declining +like those above in order to emphasize recent filters over older filters. + +The filter costs specify for each filter type a relative decoding cost +to be considered when selecting row filters. This means that filters +with higher costs are less likely to be chosen over filters with lower +costs, unless their "sum of absolute differences" is that much smaller. +The costs do not necessarily reflect the exact computational speeds of +the various filters, since this would unduly influence the final image +size. + +Note that the numbers above were invented purely for this example and +are given only to help explain the function usage. Little testing has +been done to find optimum values for either the costs or the weights. + +Removing unwanted object code + +There are a bunch of #define's in pngconf.h that control what parts of +libpng are compiled. All the defines end in _SUPPORTED. If you are +never going to use a capability, you can change the #define to #undef +before recompiling libpng and save yourself code and data space, or +you can turn off individual capabilities with defines that begin with +PNG_NO_. + +You can also turn all of the transforms and ancillary chunk capabilities +off en masse with compiler directives that define +PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS, +or all four, +along with directives to turn on any of the capabilities that you do +want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable +the extra transformations but still leave the library fully capable of reading +and writing PNG files with all known public chunks +Use of the PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive +produces a library that is incapable of reading or writing ancillary chunks. +If you are not using the progressive reading capability, you can +turn that off with PNG_NO_PROGRESSIVE_READ (don't confuse +this with the INTERLACING capability, which you'll still have). + +All the reading and writing specific code are in separate files, so the +linker should only grab the files it needs. However, if you want to +make sure, or if you are building a stand alone library, all the +reading files start with pngr and all the writing files start with +pngw. The files that don't match either (like png.c, pngtrans.c, etc.) +are used for both reading and writing, and always need to be included. +The progressive reader is in pngpread.c + +If you are creating or distributing a dynamically linked library (a .so +or DLL file), you should not remove or disable any parts of the library, +as this will cause applications linked with different versions of the +library to fail if they call functions not available in your library. +The size of the library itself should not be an issue, because only +those sections that are actually used will be loaded into memory. + +Requesting debug printout + +The macro definition PNG_DEBUG can be used to request debugging +printout. Set it to an integer value in the range 0 to 3. Higher +numbers result in increasing amounts of debugging information. The +information is printed to the "stderr" file, unless another file +name is specified in the PNG_DEBUG_FILE macro definition. + +When PNG_DEBUG > 0, the following functions (macros) become available: + + png_debug(level, message) + png_debug1(level, message, p1) + png_debug2(level, message, p1, p2) + +in which "level" is compared to PNG_DEBUG to decide whether to print +the message, "message" is the formatted string to be printed, +and p1 and p2 are parameters that are to be embedded in the string +according to printf-style formatting directives. For example, + + png_debug1(2, "foo=%d\n", foo); + +is expanded to + + if(PNG_DEBUG > 2) + fprintf(PNG_DEBUG_FILE, "foo=%d\n", foo); + +When PNG_DEBUG is defined but is zero, the macros aren't defined, but you +can still use PNG_DEBUG to control your own debugging: + + #ifdef PNG_DEBUG + fprintf(stderr, ... + #endif + +When PNG_DEBUG = 1, the macros are defined, but only png_debug statements +having level = 0 will be printed. There aren't any such statements in +this version of libpng, but if you insert some they will be printed. + +VI. Runtime optimization + +A new feature in libpng 1.2.0 is the ability to dynamically switch between +standard and optimized versions of some routines. Currently these are +limited to three computationally intensive tasks when reading PNG files: +decoding row filters, expanding interlacing, and combining interlaced or +transparent row data with previous row data. Currently the optimized +versions are available only for x86 (Intel, AMD, etc.) platforms with +MMX support, though this may change in future versions. (For example, +the non-MMX assembler optimizations for zlib might become similarly +runtime-selectable in future releases, in which case libpng could be +extended to support them. Alternatively, the compile-time choice of +floating-point versus integer routines for gamma correction might become +runtime-selectable.) + +Because such optimizations tend to be very platform- and compiler-dependent, +both in how they are written and in how they perform, the new runtime code +in libpng has been written to allow programs to query, enable, and disable +either specific optimizations or all such optimizations. For example, to +enable all possible optimizations (bearing in mind that some "optimizations" +may actually run more slowly in rare cases): + + #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) + png_uint_32 mask, flags; + + flags = png_get_asm_flags(png_ptr); + mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE); + png_set_asm_flags(png_ptr, flags | mask); + #endif + +To enable only optimizations relevant to reading PNGs, use PNG_SELECT_READ +by itself when calling png_get_asm_flagmask(); similarly for optimizing +only writing. To disable all optimizations: + + #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) + flags = png_get_asm_flags(png_ptr); + mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE); + png_set_asm_flags(png_ptr, flags & ~mask); + #endif + +To enable or disable only MMX-related features, use png_get_mmx_flagmask() +in place of png_get_asm_flagmask(). The mmx version takes one additional +parameter: + + #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) + int selection = PNG_SELECT_READ | PNG_SELECT_WRITE; + int compilerID; + + mask = png_get_mmx_flagmask(selection, &compilerID); + #endif + +On return, compilerID will indicate which version of the MMX assembler +optimizations was compiled. Currently two flavors exist: Microsoft +Visual C++ (compilerID == 1) and GNU C (a.k.a. gcc/gas, compilerID == 2). +On non-x86 platforms or on systems compiled without MMX optimizations, a +value of -1 is used. + +Note that both png_get_asm_flagmask() and png_get_mmx_flagmask() return +all valid, settable optimization bits for the version of the library that's +currently in use. In the case of shared (dynamically linked) libraries, +this may include optimizations that did not exist at the time the code was +written and compiled. It is also possible, of course, to enable only known, +specific optimizations; for example: + + #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) + flags = PNG_ASM_FLAG_MMX_READ_COMBINE_ROW \ + | PNG_ASM_FLAG_MMX_READ_INTERLACE \ + | PNG_ASM_FLAG_MMX_READ_FILTER_SUB \ + | PNG_ASM_FLAG_MMX_READ_FILTER_UP \ + | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \ + | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ; + png_set_asm_flags(png_ptr, flags); + #endif + +This method would enable only the MMX read-optimizations available at the +time of libpng 1.2.0's release, regardless of whether a later version of +the DLL were actually being used. (Also note that these functions did not +exist in versions older than 1.2.0, so any attempt to run a dynamically +linked app on such an older version would fail.) + +To determine whether the processor supports MMX instructions at all, use +the png_mmx_support() function: + + #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) + mmxsupport = png_mmx_support(); + #endif + +It returns -1 if MMX support is not compiled into libpng, 0 if MMX code +is compiled but MMX is not supported by the processor, or 1 if MMX support +is fully available. Note that png_mmx_support(), png_get_mmx_flagmask(), +and png_get_asm_flagmask() all may be called without allocating and ini- +tializing any PNG structures (for example, as part of a usage screen or +"about" box). + +The following code can be used to prevent an application from using the +thread_unsafe features, even if libpng was built with PNG_THREAD_UNSAFE_OK +defined: + +#if defined(PNG_USE_PNGGCCRD) && defined(PNG_ASSEMBLER_CODE_SUPPORTED) \ + && defined(PNG_THREAD_UNSAFE_OK) + /* Disable thread-unsafe features of pnggccrd */ + if (png_access_version() >= 10200) + { + png_uint_32 mmx_disable_mask = 0; + png_uint_32 asm_flags; + + mmx_disable_mask |= ( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW \ + | PNG_ASM_FLAG_MMX_READ_FILTER_SUB \ + | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \ + | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ); + asm_flags = png_get_asm_flags(png_ptr); + png_set_asm_flags(png_ptr, asm_flags & ~mmx_disable_mask); + } +#endif + +For more extensive examples of runtime querying, enabling and disabling +of optimized features, see contrib/gregbook/readpng2.c in the libpng +source-code distribution. + +VII. MNG support + +The MNG specification (available at http://www.libpng.org/pub/mng) allows +certain extensions to PNG for PNG images that are embedded in MNG datastreams. +Libpng can support some of these extensions. To enable them, use the +png_permit_mng_features() function: + + feature_set = png_permit_mng_features(png_ptr, mask) + mask is a png_uint_32 containing the logical OR of the + features you want to enable. These include + PNG_FLAG_MNG_EMPTY_PLTE + PNG_FLAG_MNG_FILTER_64 + PNG_ALL_MNG_FEATURES + feature_set is a png_uint_32 that is the logical AND of + your mask with the set of MNG features that is + supported by the version of libpng that you are using. + +It is an error to use this function when reading or writing a standalone +PNG file with the PNG 8-byte signature. The PNG datastream must be wrapped +in a MNG datastream. As a minimum, it must have the MNG 8-byte signature +and the MHDR and MEND chunks. Libpng does not provide support for these +or any other MNG chunks; your application must provide its own support for +them. You may wish to consider using libmng (available at +http://www.libmng.com) instead. + +VIII. Changes to Libpng from version 0.88 + +It should be noted that versions of libpng later than 0.96 are not +distributed by the original libpng author, Guy Schalnat, nor by +Andreas Dilger, who had taken over from Guy during 1996 and 1997, and +distributed versions 0.89 through 0.96, but rather by another member +of the original PNG Group, Glenn Randers-Pehrson. Guy and Andreas are +still alive and well, but they have moved on to other things. + +The old libpng functions png_read_init(), png_write_init(), +png_info_init(), png_read_destroy(), and png_write_destroy() have been +moved to PNG_INTERNAL in version 0.95 to discourage their use. These +functions will be removed from libpng version 2.0.0. + +The preferred method of creating and initializing the libpng structures is +via the png_create_read_struct(), png_create_write_struct(), and +png_create_info_struct() because they isolate the size of the structures +from the application, allow version error checking, and also allow the +use of custom error handling routines during the initialization, which +the old functions do not. The functions png_read_destroy() and +png_write_destroy() do not actually free the memory that libpng +allocated for these structs, but just reset the data structures, so they +can be used instead of png_destroy_read_struct() and +png_destroy_write_struct() if you feel there is too much system overhead +allocating and freeing the png_struct for each image read. + +Setting the error callbacks via png_set_message_fn() before +png_read_init() as was suggested in libpng-0.88 is no longer supported +because this caused applications that do not use custom error functions +to fail if the png_ptr was not initialized to zero. It is still possible +to set the error callbacks AFTER png_read_init(), or to change them with +png_set_error_fn(), which is essentially the same function, but with a new +name to force compilation errors with applications that try to use the old +method. + +Starting with version 1.0.7, you can find out which version of the library +you are using at run-time: + + png_uint_32 libpng_vn = png_access_version_number(); + +The number libpng_vn is constructed from the major version, minor +version with leading zero, and release number with leading zero, +(e.g., libpng_vn for version 1.0.7 is 10007). + +You can also check which version of png.h you used when compiling your +application: + + png_uint_32 application_vn = PNG_LIBPNG_VER; + +IX. Y2K Compliance in libpng + +September 12, 2004 + +Since the PNG Development group is an ad-hoc body, we can't make +an official declaration. + +This is your unofficial assurance that libpng from version 0.71 and +upward through 1.2.7 are Y2K compliant. It is my belief that earlier +versions were also Y2K compliant. + +Libpng only has three year fields. One is a 2-byte unsigned integer that +will hold years up to 65535. The other two hold the date in text +format, and will hold years up to 9999. + +The integer is + "png_uint_16 year" in png_time_struct. + +The strings are + "png_charp time_buffer" in png_struct and + "near_time_buffer", which is a local character string in png.c. + +There are seven time-related functions: + + png_convert_to_rfc_1123() in png.c + (formerly png_convert_to_rfc_1152() in error) + png_convert_from_struct_tm() in pngwrite.c, called + in pngwrite.c + png_convert_from_time_t() in pngwrite.c + png_get_tIME() in pngget.c + png_handle_tIME() in pngrutil.c, called in pngread.c + png_set_tIME() in pngset.c + png_write_tIME() in pngwutil.c, called in pngwrite.c + +All appear to handle dates properly in a Y2K environment. The +png_convert_from_time_t() function calls gmtime() to convert from system +clock time, which returns (year - 1900), which we properly convert to +the full 4-digit year. There is a possibility that applications using +libpng are not passing 4-digit years into the png_convert_to_rfc_1123() +function, or that they are incorrectly passing only a 2-digit year +instead of "year - 1900" into the png_convert_from_struct_tm() function, +but this is not under our control. The libpng documentation has always +stated that it works with 4-digit years, and the APIs have been +documented as such. + +The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned +integer to hold the year, and can hold years as large as 65535. + +zlib, upon which libpng depends, is also Y2K compliant. It contains +no date-related code. + + + Glenn Randers-Pehrson + libpng maintainer + PNG Development Group diff --git a/Utilities/FLTK/png/libpngpf.3 b/Utilities/FLTK/png/libpngpf.3 new file mode 100644 index 0000000000..9914fcfd40 --- /dev/null +++ b/Utilities/FLTK/png/libpngpf.3 @@ -0,0 +1,1096 @@ +.TH LIBPNGPF 3 "September 12, 2004" +.SH NAME +libpng \- Portable Network Graphics (PNG) Reference Library 1.2.7 +(private functions) +.SH SYNOPSIS +\fB\fB#include <png.h>\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_build_gamma_table (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_build_grayscale_palette (int \fP\fI\fP\fIbit_depth\fP\fB\fP\fB, png_colorp \fI\fIpalette\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_calculate_crc (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIptr\fP\fB\fP\fB, png_size_t \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_check_chunk_name (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_bytep \fI\fIchunk_name\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBpng_size_t png_check_keyword (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_charp \fP\fI\fP\fIkey\fP\fB\fP\fB, png_charpp \fI\fInew_key\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_combine_row (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIrow\fP\fB\fP\fB, int \fI\fImask\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_correct_palette (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_colorp \fP\fI\fP\fIpalette\fP\fB\fP\fB, int \fI\fInum_palette\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBint png_crc_error (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBint png_crc_finish (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIskip\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_crc_read (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIbuf\fP\fB\fP\fB, png_size_t \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBpng_voidp png_create_struct (int \fI\fItype\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBpng_voidp png_create_struct_2 (int \fP\fI\fP\fItype\fP\fB\fP\fB, png_malloc_ptr \fP\fI\fP\fImalloc_fn\fP\fB\fP\fB, png_voidp \fI\fImem_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBpng_charp png_decompress_chunk (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, int \fP\fI\fP\fIcomp_type\fP\fB\fP\fB, png_charp \fP\fI\fP\fIchunkdata\fP\fB\fP\fB, png_size_t \fP\fI\fP\fIchunklength\fP\fB\fP\fB, png_size_t \fP\fI\fP\fIprefix_length\fP\fB\fP\fB, png_size_t \fI\fI*data_length\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_destroy_struct (png_voidp \fI\fIstruct_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_destroy_struct_2 (png_voidp \fP\fI\fP\fIstruct_ptr\fP\fB\fP\fB, png_free_ptr \fP\fI\fP\fIfree_fn\fP\fB\fP\fB, png_voidp \fI\fImem_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_background (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIrow\fP\fB\fP\fB, png_color_16p \fP\fI\fP\fItrans_values\fP\fB\fP\fB, png_color_16p \fP\fI\fP\fIbackground\fP\fB\fP\fB, png_color_16p \fP\fI\fP\fIbackground_1\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIgamma_table\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIgamma_from_1\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIgamma_to_1\fP\fB\fP\fB, png_uint_16pp \fP\fI\fP\fIgamma_16\fP\fB\fP\fB, png_uint_16pp \fP\fI\fP\fIgamma_16_from_1\fP\fB\fP\fB, png_uint_16pp \fP\fI\fP\fIgamma_16_to_1\fP\fB\fP\fB, int \fI\fIgamma_shift\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_bgr (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fI\fIrow\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_chop (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fI\fIrow\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_dither (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIrow\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIpalette_lookup\fP\fB\fP\fB, png_bytep \fI\fIdither_lookup\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_expand (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIrow\fP\fB\fP\fB, png_color_16p \fI\fItrans_value\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_expand_palette (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIrow\fP\fB\fP\fB, png_colorp \fP\fI\fP\fIpalette\fP\fB\fP\fB, png_bytep \fP\fI\fP\fItrans\fP\fB\fP\fB, int \fI\fInum_trans\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_gamma (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIrow\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIgamma_table\fP\fB\fP\fB, png_uint_16pp \fP\fI\fP\fIgamma_16_table\fP\fB\fP\fB, int \fI\fIgamma_shift\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_gray_to_rgb (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fI\fIrow\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_invert (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fI\fIrow\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_pack (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIrow\fP\fB\fP\fB, png_uint_32 \fI\fIbit_depth\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_packswap (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fI\fIrow\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_read_filler (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIrow\fP\fB\fP\fB, png_uint_32 \fP\fI\fP\fIfiller\fP\fB\fP\fB, png_uint_32 \fI\fIflags\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_read_interlace (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIrow\fP\fB\fP\fB, int \fP\fI\fP\fIpass\fP\fB\fP\fB, png_uint_32 \fI\fItransformations\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_read_invert_alpha (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fI\fIrow\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_read_swap_alpha (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fI\fIrow\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_read_transformations (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBint png_do_rgb_to_gray (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fI\fIrow\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_shift (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIrow\fP\fB\fP\fB, png_color_8p \fI\fIbit_depth\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_strip_filler (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIrow\fP\fB\fP\fB, png_uint_32 \fI\fIflags\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_swap (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fI\fIrow\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_unpack (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fI\fIrow\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_unshift (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIrow\fP\fB\fP\fB, png_color_8p \fI\fIsig_bits\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_write_interlace (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIrow\fP\fB\fP\fB, int \fI\fIpass\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_write_invert_alpha (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fI\fIrow\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_write_swap_alpha (png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fI\fIrow\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_do_write_transformations (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid *png_far_to_near (png_structp png_ptr,png_voidp \fP\fI\fP\fIptr\fP\fB\fP\fB, int \fI\fIcheck\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_flush (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBpng_int_32 png_get_int_32 (png_bytep \fI\fIbuf\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBpng_uint_16 png_get_uint_16 (png_bytep \fI\fIbuf\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBpng_uint_32 png_get_uint_31 (png_bytep \fI\fIbuf\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBpng_uint_32 png_get_uint_32 (png_bytep \fI\fIbuf\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_bKGD (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_cHRM (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_gAMA (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_hIST (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_IEND (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_IHDR (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_iCCP (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_iTXt (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_oFFs (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_pCAL (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_pHYs (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_PLTE (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_sBIT (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_sCAL (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_sPLT (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_sRGB (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_tEXt (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_tIME (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_tRNS (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_unknown (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_handle_zTXt (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_info_destroy (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fI\fIinfo_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_init_mmx_flags (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_init_read_transformations (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_process_IDAT_data (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIbuffer\fP\fB\fP\fB, png_size_t \fI\fIbuffer_length\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_process_some_data (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fI\fIinfo_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_check_crc (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_crc_finish (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_crc_skip (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_fill_buffer (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIbuffer\fP\fB\fP\fB, png_size_t \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_handle_tEXt (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_handle_unknown (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_handle_zTXt (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_have_end (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fI\fIinfo_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_have_info (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fI\fIinfo_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_have_row (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_bytep \fI\fIrow\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_process_row (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_read_chunk (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fI\fIinfo_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_read_end (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fI\fIinfo_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_read_IDAT (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_read_sig (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fI\fIinfo_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_read_tEXt (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fI\fIinfo_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_read_zTXt (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fI\fIinfo_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_restore_buffer (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIbuffer\fP\fB\fP\fB, png_size_t \fI\fIbuffer_length\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_push_save_buffer (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_read_data (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIdata\fP\fB\fP\fB, png_size_t \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_read_filter_row (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_row_infop \fP\fI\fP\fIrow_info\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIrow\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIprev_row\fP\fB\fP\fB, int \fI\fIfilter\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_read_finish_row (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_read_push_finish_row (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_read_start_row (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_read_transform_info (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fI\fIinfo_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_reset_crc (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_save_int_32 (png_bytep \fP\fI\fP\fIbuf\fP\fB\fP\fB, png_int_32 \fI\fIi\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_save_uint_16 (png_bytep \fP\fI\fP\fIbuf\fP\fB\fP\fB, unsigned int \fI\fIi\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_save_uint_32 (png_bytep \fP\fI\fP\fIbuf\fP\fB\fP\fB, png_uint_32 \fI\fIi\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBint png_set_text_2 (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_infop \fP\fI\fP\fIinfo_ptr\fP\fB\fP\fB, png_textp \fP\fI\fP\fItext_ptr\fP\fB\fP\fB, int \fI\fInum_text)\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_cHRM (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, double \fP\fI\fP\fIwhite_x\fP\fB\fP\fB, double \fP\fI\fP\fIwhite_y\fP\fB\fP\fB, double \fP\fI\fP\fIred_x\fP\fB\fP\fB, double \fP\fI\fP\fIred_y\fP\fB\fP\fB, double \fP\fI\fP\fIgreen_x\fP\fB\fP\fB, double \fP\fI\fP\fIgreen_y\fP\fB\fP\fB, double \fP\fI\fP\fIblue_x\fP\fB\fP\fB, double \fI\fIblue_y\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_cHRM_fixed (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_uint_32 \fP\fI\fP\fIwhite_x\fP\fB\fP\fB, png_uint_32 \fP\fI\fP\fIwhite_y\fP\fB\fP\fB, png_uint_32 \fP\fI\fP\fIred_x\fP\fB\fP\fB, png_uint_32 \fP\fI\fP\fIred_y\fP\fB\fP\fB, png_uint_32 \fP\fI\fP\fIgreen_x\fP\fB\fP\fB, png_uint_32 \fP\fI\fP\fIgreen_y\fP\fB\fP\fB, png_uint_32 \fP\fI\fP\fIblue_x\fP\fB\fP\fB, png_uint_32 \fI\fIblue_y\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_data (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIdata\fP\fB\fP\fB, png_size_t \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_filtered_row (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_bytep \fI\fIfiltered_row\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_find_filter (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_row_infop \fI\fIrow_info\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_finish_row (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_gAMA (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, double \fI\fIfile_gamma\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_gAMA_fixed (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_uint_32 \fI\fIint_file_gamma\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_hIST (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_uint_16p \fP\fI\fP\fIhist\fP\fB\fP\fB, int \fI\fInum_hist\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_iCCP (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_charp \fP\fI\fP\fIname\fP\fB\fP\fB, int \fP\fI\fP\fIcompression_type\fP\fB\fP\fB, png_charp \fP\fI\fP\fIprofile\fP\fB\fP\fB, int \fI\fIproflen\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_IDAT (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_bytep \fP\fI\fP\fIdata\fP\fB\fP\fB, png_size_t \fI\fIlength\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_IEND (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_IHDR (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_uint_32 \fP\fI\fP\fIwidth\fP\fB\fP\fB, png_uint_32 \fP\fI\fP\fIheight\fP\fB\fP\fB, int \fP\fI\fP\fIbit_depth\fP\fB\fP\fB, int \fP\fI\fP\fIcolor_type\fP\fB\fP\fB, int \fP\fI\fP\fIcompression_type\fP\fB\fP\fB, int \fP\fI\fP\fIfilter_type\fP\fB\fP\fB, int \fI\fIinterlace_type\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_iTXt (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, int \fP\fI\fP\fIcompression\fP\fB\fP\fB, png_charp \fP\fI\fP\fIkey\fP\fB\fP\fB, png_charp \fP\fI\fP\fIlang\fP\fB\fP\fB, png_charp \fP\fI\fP\fItranslated_key\fP\fB\fP\fB, png_charp \fI\fItext)\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_oFFs (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_uint_32 \fP\fI\fP\fIx_offset\fP\fB\fP\fB, png_uint_32 \fP\fI\fP\fIy_offset\fP\fB\fP\fB, int \fI\fIunit_type\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_pCAL (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_charp \fP\fI\fP\fIpurpose\fP\fB\fP\fB, png_int_32 \fP\fI\fP\fIX0\fP\fB\fP\fB, png_int_32 \fP\fI\fP\fIX1\fP\fB\fP\fB, int \fP\fI\fP\fItype\fP\fB\fP\fB, int \fP\fI\fP\fInparams\fP\fB\fP\fB, png_charp \fP\fI\fP\fIunits\fP\fB\fP\fB, png_charpp \fI\fIparams\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_pHYs (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_uint_32 \fP\fI\fP\fIx_pixels_per_unit\fP\fB\fP\fB, png_uint_32 \fP\fI\fP\fIy_pixels_per_unit\fP\fB\fP\fB, int \fI\fIunit_type\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_PLTE (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_colorp \fP\fI\fP\fIpalette\fP\fB\fP\fB, png_uint_32 \fI\fInum_pal\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_sBIT (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_color_8p \fP\fI\fP\fIsbit\fP\fB\fP\fB, int \fI\fIcolor_type\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_sCAL (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_charp \fP\fI\fP\fIunit\fP\fB\fP\fB, double \fP\fI\fP\fIwidth\fP\fB\fP\fB, double \fI\fIheight\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_sCAL_s (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_charp \fP\fI\fP\fIunit\fP\fB\fP\fB, png_charp \fP\fI\fP\fIwidth\fP\fB\fP\fB, png_charp \fI\fIheight\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_sig (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_sRGB (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, int \fI\fIintent\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_sPLT (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_spalette_p \fI\fIpalette\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_start_row (png_structp \fI\fIpng_ptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_tEXt (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_charp \fP\fI\fP\fIkey\fP\fB\fP\fB, png_charp \fP\fI\fP\fItext\fP\fB\fP\fB, png_size_t \fI\fItext_len\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_tIME (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_timep \fI\fImod_time\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_tRNS (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_bytep \fP\fI\fP\fItrans\fP\fB\fP\fB, png_color_16p \fP\fI\fP\fIvalues\fP\fB\fP\fB, int \fP\fI\fP\fInumber\fP\fB\fP\fB, int \fI\fIcolor_type\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_write_zTXt (png_structp \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, png_charp \fP\fI\fP\fIkey\fP\fB\fP\fB, png_charp \fP\fI\fP\fItext\fP\fB\fP\fB, png_size_t \fP\fI\fP\fItext_len\fP\fB\fP\fB, int \fI\fIcompression\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoidpf png_zalloc (voidpf \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, uInt \fP\fI\fP\fIitems\fP\fB\fP\fB, uInt \fI\fIsize\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +\fB\fBvoid png_zfree (voidpf \fP\fI\fP\fIpng_ptr\fP\fB\fP\fB, voidpf \fI\fIptr\fP\fB\fP\fB);\fP\fP + +\fI\fB + +\fI\fB\fI\fB + +\fI\fB + +.SH DESCRIPTION +The functions listed above are used privately by libpng +and are not recommended for use by applications. They are +not "exported" to applications using shared libraries. They +are listed alphabetically here as an aid to libpng maintainers. +See png.h for more information on these functions. + +.SH SEE ALSO +libpng(3), png(5) +.SH AUTHOR +Glenn Randers-Pehrson diff --git a/Utilities/FLTK/png/makedepend b/Utilities/FLTK/png/makedepend new file mode 100644 index 0000000000..bbb12e487c --- /dev/null +++ b/Utilities/FLTK/png/makedepend @@ -0,0 +1,17 @@ +# DO NOT DELETE + +png.o: png.h pngconf.h +pngset.o: png.h pngconf.h +pngget.o: png.h pngconf.h +pngrutil.o: png.h pngconf.h +pngtrans.o: png.h pngconf.h +pngwutil.o: png.h pngconf.h +pngread.o: png.h pngconf.h +pngrio.o: png.h pngconf.h +pngwio.o: png.h pngconf.h +pngwrite.o: png.h pngconf.h +pngrtran.o: png.h pngconf.h +pngwtran.o: png.h pngconf.h +pngmem.o: png.h pngconf.h +pngerror.o: png.h pngconf.h +pngpread.o: png.h pngconf.h diff --git a/Utilities/FLTK/png/makefile.wat b/Utilities/FLTK/png/makefile.wat new file mode 100644 index 0000000000..b1b9e334e6 --- /dev/null +++ b/Utilities/FLTK/png/makefile.wat @@ -0,0 +1,64 @@ +# +# "$Id: makefile.wat 4359 2005-05-19 16:07:13Z mike $" +# +# PNG library makefile for the Fast Light Toolkit (FLTK). +# +# Copyright 1997-2004 by Easy Software Products. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. +# +# Please report all bugs and problems to "fltk-bugs@fltk.org". +# + +LIBNAMEROOT=ftlk_png +# I ought to be able to do "EXTRA_INCLUDE_DIRS += ;../zlib" but it doesn't work for me (OW1.3) +!undef EXTRA_INCLUDE_DIRS +EXTRA_INCLUDE_DIRS=$(ROOT);../zlib + +!include ../watcom.mif + + +# +# Object files... +# + +LIBOBJS = png.obj pngset.obj pngget.obj pngrutil.obj pngtrans.obj pngwutil.obj & + pngread.obj pngrio.obj pngwio.obj pngwrite.obj pngrtran.obj & + pngwtran.obj pngmem.obj pngerror.obj pngpread.obj + + +# +# Make all targets... +# + +all: $(LIBNAME) + +$(LIBNAME): $(LIBOBJS) + $(LIB) $(LIBOPTS) $@ $< + +# +# Clean all directories +# +clean : .SYMBOLIC + @echo Cleaning up. +CLEANEXTS = obj + @for %a in ($(CLEANEXTS)) do -rm -f $(ODIR)\*.%a + -rm -f *.err + -rm -f $(LIBNAME) + +# +# End of "$Id: makefile.wat 4359 2005-05-19 16:07:13Z mike $". +# diff --git a/Utilities/FLTK/png/png.5 b/Utilities/FLTK/png/png.5 new file mode 100644 index 0000000000..1cc5ef4f99 --- /dev/null +++ b/Utilities/FLTK/png/png.5 @@ -0,0 +1,74 @@ +.TH PNG 5 "September 12, 2004" +.SH NAME +png \- Portable Network Graphics (PNG) format +.SH DESCRIPTION +PNG (Portable Network Graphics) is an extensible file format for the +lossless, portable, well-compressed storage of raster images. PNG provides +a patent-free replacement for GIF and can also replace many +common uses of TIFF. Indexed-color, grayscale, and truecolor images are +supported, plus an optional alpha channel. Sample depths range from +1 to 16 bits. +.br + +PNG is designed to work well in online viewing applications, such as the +World Wide Web, so it is fully streamable with a progressive display +option. PNG is robust, providing both full file integrity checking and +fast, simple detection of common transmission errors. Also, PNG can store +gamma and chromaticity data for improved color matching on heterogeneous +platforms. + +.SH "SEE ALSO" +.IR libpng(3), zlib(3), deflate(5), and zlib(5) +.LP +PNG specification (second edition), November 2003: +.IP +.br + <http://www.w3.org/TR/2003/REC-PNG-20031110/ +PNG 1.2 specification, July 1999: +.IP +.br +http://www.libpng.org/pub/png +.LP +PNG 1.0 specification, October 1996: +.IP +.br +RFC 2083 +.IP +.br +ftp://ds.internic.net/rfc/rfc2083.txt +.br +or (as a W3C Recommendation) at +.br +http://www.w3.org/TR/REC-png.html +.SH AUTHORS +This man page: Glenn Randers-Pehrson +.LP +Portable Network Graphics (PNG) Specification (Second Edition) +Information technology - Computer graphics and image processing - +Portable Network Graphics (PNG): Functional specification. +ISO/IEC 15948:2003 (E) (November 10, 2003): David Duce and others. +.LP +Portable Network Graphics (PNG) Specification Version 1.2 (July 8, 1999): +Glenn Randers-Pehrson and others (png-list). +.LP +Portable Network Graphics (PNG) Specification Version 1.0 (October 1, 1996): +Thomas Boutell and others (png-list). +.LP + + +.SH COPYRIGHT NOTICE +.LP +This man page is Copyright (c) 1998-2004 Glenn Randers-Pehrson. See png.h +for conditions of use and distribution. +.LP +The PNG Specification (Second Edition) is +Copyright (c) 2003 W3C. (MIT, ERCIM, Keio), All Rights Reserved. +.LP +The PNG-1.2 specification is copyright (c) 1999 Glenn Randers-Pehrson. +See the specification for conditions of use and distribution. +.LP +The PNG-1.0 specification is copyright (c) 1996 Massachusetts Institute of +Technology. See the specification for conditions of use and distribution. +.LP +.\" end of man page + diff --git a/Utilities/FLTK/png/png.c b/Utilities/FLTK/png/png.c new file mode 100644 index 0000000000..75099d5ed2 --- /dev/null +++ b/Utilities/FLTK/png/png.c @@ -0,0 +1,826 @@ + +/* png.c - location for general purpose libpng functions + * + * libpng version 1.2.7 - September 12, 2004 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#define PNG_NO_EXTERN +#include "png.h" + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef version_1_2_7 Your_png_h_is_not_version_1_2_7; + +/* Version information for C files. This had better match the version + * string defined in png.h. */ + +#ifdef PNG_USE_GLOBAL_ARRAYS +/* png_libpng_ver was changed to a function in version 1.0.5c */ +const char png_libpng_ver[18] = PNG_LIBPNG_VER_STRING; + +/* png_sig was changed to a function in version 1.0.5c */ +/* Place to hold the signature string for a PNG file. */ +const png_byte FARDATA png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + +/* Invoke global declarations for constant strings for known chunk types */ +PNG_IHDR; +PNG_IDAT; +PNG_IEND; +PNG_PLTE; +PNG_bKGD; +PNG_cHRM; +PNG_gAMA; +PNG_hIST; +PNG_iCCP; +PNG_iTXt; +PNG_oFFs; +PNG_pCAL; +PNG_sCAL; +PNG_pHYs; +PNG_sBIT; +PNG_sPLT; +PNG_sRGB; +PNG_tEXt; +PNG_tIME; +PNG_tRNS; +PNG_zTXt; + +/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + +/* start of interlace block */ +const int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + +/* offset to next interlace block */ +const int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + +/* start of interlace block in the y direction */ +const int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + +/* offset to next interlace block in the y direction */ +const int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + +/* width of interlace block (used in assembler routines only) */ +#ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW +const int FARDATA png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; +#endif + +/* Height of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h +const int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; +*/ + +/* Mask to determine which pixels are valid in a pass */ +const int FARDATA png_pass_mask[] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; + +/* Mask to determine which pixels to overwrite while displaying */ +const int FARDATA png_pass_dsp_mask[] + = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; + +#endif + +/* Tells libpng that we have already handled the first "num_bytes" bytes + * of the PNG file signature. If the PNG data is embedded into another + * stream we can set num_bytes = 8 so that libpng will not attempt to read + * or write any of the magic bytes before it starts on the IHDR. + */ + +void PNGAPI +png_set_sig_bytes(png_structp png_ptr, int num_bytes) +{ + png_debug(1, "in png_set_sig_bytes\n"); + if (num_bytes > 8) + png_error(png_ptr, "Too many bytes for PNG signature."); + + png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes); +} + +/* Checks whether the supplied bytes match the PNG signature. We allow + * checking less than the full 8-byte signature so that those apps that + * already read the first few bytes of a file to determine the file type + * can simply check the remaining bytes for extra assurance. Returns + * an integer less than, equal to, or greater than zero if sig is found, + * respectively, to be less than, to match, or be greater than the correct + * PNG signature (this is the same behaviour as strcmp, memcmp, etc). + */ +int PNGAPI +png_sig_cmp(png_bytep sig, png_size_t start, png_size_t num_to_check) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + if (num_to_check > 8) + num_to_check = 8; + else if (num_to_check < 1) + return (0); + + if (start > 7) + return (0); + + if (start + num_to_check > 8) + num_to_check = 8 - start; + + return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check))); +} + +/* (Obsolete) function to check signature bytes. It does not allow one + * to check a partial signature. This function might be removed in the + * future - use png_sig_cmp(). Returns true (nonzero) if the file is a PNG. + */ +int PNGAPI +png_check_sig(png_bytep sig, int num) +{ + return ((int)!png_sig_cmp(sig, (png_size_t)0, (png_size_t)num)); +} + +/* Function to allocate memory for zlib and clear it to 0. */ +#ifdef PNG_1_0_X +voidpf PNGAPI +#else +voidpf /* private */ +#endif +png_zalloc(voidpf png_ptr, uInt items, uInt size) +{ + png_voidp ptr; + png_structp p=png_ptr; + png_uint_32 save_flags=p->flags; + png_uint_32 num_bytes; + + if (items > PNG_UINT_32_MAX/size) + { + png_warning (png_ptr, "Potential overflow in png_zalloc()"); + return (NULL); + } + num_bytes = (png_uint_32)items * size; + + p->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; + ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes); + p->flags=save_flags; + +#if defined(PNG_1_0_X) && !defined(PNG_NO_ZALLOC_ZERO) + if (ptr == NULL) + return ((voidpf)ptr); + + if (num_bytes > (png_uint_32)0x8000L) + { + png_memset(ptr, 0, (png_size_t)0x8000L); + png_memset((png_bytep)ptr + (png_size_t)0x8000L, 0, + (png_size_t)(num_bytes - (png_uint_32)0x8000L)); + } + else + { + png_memset(ptr, 0, (png_size_t)num_bytes); + } +#endif + return ((voidpf)ptr); +} + +/* function to free memory for zlib */ +#ifdef PNG_1_0_X +void PNGAPI +#else +void /* private */ +#endif +png_zfree(voidpf png_ptr, voidpf ptr) +{ + png_free((png_structp)png_ptr, (png_voidp)ptr); +} + +/* Reset the CRC variable to 32 bits of 1's. Care must be taken + * in case CRC is > 32 bits to leave the top bits 0. + */ +void /* PRIVATE */ +png_reset_crc(png_structp png_ptr) +{ + png_ptr->crc = crc32(0, Z_NULL, 0); +} + +/* Calculate the CRC over a section of data. We can only pass as + * much data to this routine as the largest single buffer size. We + * also check that this data will actually be used before going to the + * trouble of calculating it. + */ +void /* PRIVATE */ +png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length) +{ + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + + if (need_crc) + png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length); +} + +/* Allocate the memory for an info_struct for the application. We don't + * really need the png_ptr, but it could potentially be useful in the + * future. This should be used in favour of malloc(png_sizeof(png_info)) + * and png_info_init() so that applications that want to use a shared + * libpng don't have to be recompiled if png_info changes size. + */ +png_infop PNGAPI +png_create_info_struct(png_structp png_ptr) +{ + png_infop info_ptr; + + png_debug(1, "in png_create_info_struct\n"); + if(png_ptr == NULL) return (NULL); +#ifdef PNG_USER_MEM_SUPPORTED + info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO, + png_ptr->malloc_fn, png_ptr->mem_ptr); +#else + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); +#endif + if (info_ptr != NULL) + png_info_init_3(&info_ptr, png_sizeof(png_info)); + + return (info_ptr); +} + +/* This function frees the memory associated with a single info struct. + * Normally, one would use either png_destroy_read_struct() or + * png_destroy_write_struct() to free an info struct, but this may be + * useful for some applications. + */ +void PNGAPI +png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr) +{ + png_infop info_ptr = NULL; + + png_debug(1, "in png_destroy_info_struct\n"); + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + png_info_destroy(png_ptr, info_ptr); + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn, + png_ptr->mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } +} + +/* Initialize the info structure. This is now an internal function (0.89) + * and applications using it are urged to use png_create_info_struct() + * instead. + */ +#undef png_info_init +void PNGAPI +png_info_init(png_infop info_ptr) +{ + /* We only come here via pre-1.0.12-compiled applications */ + png_info_init_3(&info_ptr, 0); +} + +void PNGAPI +png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size) +{ + png_infop info_ptr = *ptr_ptr; + + png_debug(1, "in png_info_init_3\n"); + + if(png_sizeof(png_info) > png_info_struct_size) + { + png_destroy_struct(info_ptr); + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); + *ptr_ptr = info_ptr; + } + + /* set everything to 0 */ + png_memset(info_ptr, 0, png_sizeof (png_info)); +} + +#ifdef PNG_FREE_ME_SUPPORTED +void PNGAPI +png_data_freer(png_structp png_ptr, png_infop info_ptr, + int freer, png_uint_32 mask) +{ + png_debug(1, "in png_data_freer\n"); + if (png_ptr == NULL || info_ptr == NULL) + return; + if(freer == PNG_DESTROY_WILL_FREE_DATA) + info_ptr->free_me |= mask; + else if(freer == PNG_USER_WILL_FREE_DATA) + info_ptr->free_me &= ~mask; + else + png_warning(png_ptr, + "Unknown freer parameter in png_data_freer."); +} +#endif + +void PNGAPI +png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask, + int num) +{ + png_debug(1, "in png_free_data\n"); + if (png_ptr == NULL || info_ptr == NULL) + return; + +#if defined(PNG_TEXT_SUPPORTED) +/* free text item num or (if num == -1) all text items */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_TEXT) & info_ptr->free_me) +#else +if (mask & PNG_FREE_TEXT) +#endif +{ + if (num != -1) + { + if (info_ptr->text && info_ptr->text[num].key) + { + png_free(png_ptr, info_ptr->text[num].key); + info_ptr->text[num].key = NULL; + } + } + else + { + int i; + for (i = 0; i < info_ptr->num_text; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i); + png_free(png_ptr, info_ptr->text); + info_ptr->text = NULL; + info_ptr->num_text=0; + } +} +#endif + +#if defined(PNG_tRNS_SUPPORTED) +/* free any tRNS entry */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_TRNS) & info_ptr->free_me) +#else +if ((mask & PNG_FREE_TRNS) && (png_ptr->flags & PNG_FLAG_FREE_TRNS)) +#endif +{ + png_free(png_ptr, info_ptr->trans); + info_ptr->valid &= ~PNG_INFO_tRNS; +#ifndef PNG_FREE_ME_SUPPORTED + png_ptr->flags &= ~PNG_FLAG_FREE_TRNS; +#endif + info_ptr->trans = NULL; +} +#endif + +#if defined(PNG_sCAL_SUPPORTED) +/* free any sCAL entry */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_SCAL) & info_ptr->free_me) +#else +if (mask & PNG_FREE_SCAL) +#endif +{ +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, info_ptr->scal_s_width); + png_free(png_ptr, info_ptr->scal_s_height); + info_ptr->scal_s_width = NULL; + info_ptr->scal_s_height = NULL; +#endif + info_ptr->valid &= ~PNG_INFO_sCAL; +} +#endif + +#if defined(PNG_pCAL_SUPPORTED) +/* free any pCAL entry */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_PCAL) & info_ptr->free_me) +#else +if (mask & PNG_FREE_PCAL) +#endif +{ + png_free(png_ptr, info_ptr->pcal_purpose); + png_free(png_ptr, info_ptr->pcal_units); + info_ptr->pcal_purpose = NULL; + info_ptr->pcal_units = NULL; + if (info_ptr->pcal_params != NULL) + { + int i; + for (i = 0; i < (int)info_ptr->pcal_nparams; i++) + { + png_free(png_ptr, info_ptr->pcal_params[i]); + info_ptr->pcal_params[i]=NULL; + } + png_free(png_ptr, info_ptr->pcal_params); + info_ptr->pcal_params = NULL; + } + info_ptr->valid &= ~PNG_INFO_pCAL; +} +#endif + +#if defined(PNG_iCCP_SUPPORTED) +/* free any iCCP entry */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_ICCP) & info_ptr->free_me) +#else +if (mask & PNG_FREE_ICCP) +#endif +{ + png_free(png_ptr, info_ptr->iccp_name); + png_free(png_ptr, info_ptr->iccp_profile); + info_ptr->iccp_name = NULL; + info_ptr->iccp_profile = NULL; + info_ptr->valid &= ~PNG_INFO_iCCP; +} +#endif + +#if defined(PNG_sPLT_SUPPORTED) +/* free a given sPLT entry, or (if num == -1) all sPLT entries */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_SPLT) & info_ptr->free_me) +#else +if (mask & PNG_FREE_SPLT) +#endif +{ + if (num != -1) + { + if(info_ptr->splt_palettes) + { + png_free(png_ptr, info_ptr->splt_palettes[num].name); + png_free(png_ptr, info_ptr->splt_palettes[num].entries); + info_ptr->splt_palettes[num].name = NULL; + info_ptr->splt_palettes[num].entries = NULL; + } + } + else + { + if(info_ptr->splt_palettes_num) + { + int i; + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i); + + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes = NULL; + info_ptr->splt_palettes_num = 0; + } + info_ptr->valid &= ~PNG_INFO_sPLT; + } +} +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_UNKN) & info_ptr->free_me) +#else +if (mask & PNG_FREE_UNKN) +#endif +{ + if (num != -1) + { + if(info_ptr->unknown_chunks) + { + png_free(png_ptr, info_ptr->unknown_chunks[num].data); + info_ptr->unknown_chunks[num].data = NULL; + } + } + else + { + int i; + + if(info_ptr->unknown_chunks_num) + { + for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i); + + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = NULL; + info_ptr->unknown_chunks_num = 0; + } + } +} +#endif + +#if defined(PNG_hIST_SUPPORTED) +/* free any hIST entry */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_HIST) & info_ptr->free_me) +#else +if ((mask & PNG_FREE_HIST) && (png_ptr->flags & PNG_FLAG_FREE_HIST)) +#endif +{ + png_free(png_ptr, info_ptr->hist); + info_ptr->hist = NULL; + info_ptr->valid &= ~PNG_INFO_hIST; +#ifndef PNG_FREE_ME_SUPPORTED + png_ptr->flags &= ~PNG_FLAG_FREE_HIST; +#endif +} +#endif + +/* free any PLTE entry that was internally allocated */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_PLTE) & info_ptr->free_me) +#else +if ((mask & PNG_FREE_PLTE) && (png_ptr->flags & PNG_FLAG_FREE_PLTE)) +#endif +{ + png_zfree(png_ptr, info_ptr->palette); + info_ptr->palette = NULL; + info_ptr->valid &= ~PNG_INFO_PLTE; +#ifndef PNG_FREE_ME_SUPPORTED + png_ptr->flags &= ~PNG_FLAG_FREE_PLTE; +#endif + info_ptr->num_palette = 0; +} + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +/* free any image bits attached to the info structure */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_ROWS) & info_ptr->free_me) +#else +if (mask & PNG_FREE_ROWS) +#endif +{ + if(info_ptr->row_pointers) + { + int row; + for (row = 0; row < (int)info_ptr->height; row++) + { + png_free(png_ptr, info_ptr->row_pointers[row]); + info_ptr->row_pointers[row]=NULL; + } + png_free(png_ptr, info_ptr->row_pointers); + info_ptr->row_pointers=NULL; + } + info_ptr->valid &= ~PNG_INFO_IDAT; +} +#endif + +#ifdef PNG_FREE_ME_SUPPORTED + if(num == -1) + info_ptr->free_me &= ~mask; + else + info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL); +#endif +} + +/* This is an internal routine to free any memory that the info struct is + * pointing to before re-using it or freeing the struct itself. Recall + * that png_free() checks for NULL pointers for us. + */ +void /* PRIVATE */ +png_info_destroy(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_info_destroy\n"); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + png_ptr->num_chunk_list=0; + } +#endif + + png_info_init_3(&info_ptr, png_sizeof(png_info)); +} + +/* This function returns a pointer to the io_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy() or png_read_destroy() are called. + */ +png_voidp PNGAPI +png_get_io_ptr(png_structp png_ptr) +{ + return (png_ptr->io_ptr); +} + +#if !defined(PNG_NO_STDIO) +/* Initialize the default input/output functions for the PNG file. If you + * use your own read or write routines, you can call either png_set_read_fn() + * or png_set_write_fn() instead of png_init_io(). If you have defined + * PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't + * necessarily available. + */ +void PNGAPI +png_init_io(png_structp png_ptr, png_FILE_p fp) +{ + png_debug(1, "in png_init_io\n"); + png_ptr->io_ptr = (png_voidp)fp; +} +#endif + +#if defined(PNG_TIME_RFC1123_SUPPORTED) +/* Convert the supplied time into an RFC 1123 string suitable for use in + * a "Creation Time" or other text-based time string. + */ +png_charp PNGAPI +png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime) +{ + static PNG_CONST char short_months[12][4] = + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + if (png_ptr->time_buffer == NULL) + { + png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29* + png_sizeof(char))); + } + +#if defined(_WIN32_WCE) + { + wchar_t time_buf[29]; + wsprintf(time_buf, TEXT("%d %S %d %02d:%02d:%02d +0000"), + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); + WideCharToMultiByte(CP_ACP, 0, time_buf, -1, png_ptr->time_buffer, 29, + NULL, NULL); + } +#else +#ifdef USE_FAR_KEYWORD + { + char near_time_buf[29]; + sprintf(near_time_buf, "%d %s %d %02d:%02d:%02d +0000", + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); + png_memcpy(png_ptr->time_buffer, near_time_buf, + 29*png_sizeof(char)); + } +#else + sprintf(png_ptr->time_buffer, "%d %s %d %02d:%02d:%02d +0000", + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); +#endif +#endif /* _WIN32_WCE */ + return ((png_charp)png_ptr->time_buffer); +} +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + +#if 0 +/* Signature string for a PNG file. */ +png_bytep PNGAPI +png_sig_bytes(void) +{ + return ((png_bytep)"\211\120\116\107\015\012\032\012"); +} +#endif + +png_charp PNGAPI +png_get_copyright(png_structp png_ptr) +{ + if (&png_ptr != NULL) /* silence compiler warning about unused png_ptr */ + return ((png_charp) "\n libpng version 1.2.7 - September 12, 2004\n\ + Copyright (c) 1998-2005 Glenn Randers-Pehrson\n\ + Copyright (c) 1996-1997 Andreas Dilger\n\ + Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\n"); + return ((png_charp) ""); +} + +/* The following return the library version as a short string in the + * format 1.0.0 through 99.99.99zz. To get the version of *.h files + * used with your application, print out PNG_LIBPNG_VER_STRING, which + * is defined in png.h. + * Note: now there is no difference between png_get_libpng_ver() and + * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard, + * it is guaranteed that png.c uses the correct version of png.h. + */ +png_charp PNGAPI +png_get_libpng_ver(png_structp png_ptr) +{ + /* Version of *.c files used when building libpng */ + if (&png_ptr != NULL) /* silence compiler warning about unused png_ptr */ + return ((png_charp) PNG_LIBPNG_VER_STRING); + return ((png_charp) ""); +} + +png_charp PNGAPI +png_get_header_ver(png_structp png_ptr) +{ + /* Version of *.h files used when building libpng */ + if (&png_ptr != NULL) /* silence compiler warning about unused png_ptr */ + return ((png_charp) PNG_LIBPNG_VER_STRING); + return ((png_charp) ""); +} + +png_charp PNGAPI +png_get_header_version(png_structp png_ptr) +{ + /* Returns longer string containing both version and date */ + if (&png_ptr != NULL) /* silence compiler warning about unused png_ptr */ + return ((png_charp) PNG_HEADER_VERSION_STRING); + return ((png_charp) ""); +} + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +int PNGAPI +png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name) +{ + /* check chunk_name and return "keep" value if it's on the list, else 0 */ + int i; + png_bytep p; + if((png_ptr == NULL && chunk_name == NULL) || png_ptr->num_chunk_list<=0) + return 0; + p=png_ptr->chunk_list+png_ptr->num_chunk_list*5-5; + for (i = png_ptr->num_chunk_list; i; i--, p-=5) + if (!png_memcmp(chunk_name, p, 4)) + return ((int)*(p+4)); + return 0; +} +#endif + +/* This function, added to libpng-1.0.6g, is untested. */ +int PNGAPI +png_reset_zstream(png_structp png_ptr) +{ + return (inflateReset(&png_ptr->zstream)); +} + +/* This function was added to libpng-1.0.7 */ +png_uint_32 PNGAPI +png_access_version_number(void) +{ + /* Version of *.c files used when building libpng */ + return((png_uint_32) PNG_LIBPNG_VER); +} + + +#if !defined(PNG_1_0_X) +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) + /* GRR: could add this: && defined(PNG_MMX_CODE_SUPPORTED) */ +/* this INTERNAL function was added to libpng 1.2.0 */ +void /* PRIVATE */ +png_init_mmx_flags (png_structp png_ptr) +{ + png_ptr->mmx_rowbytes_threshold = 0; + png_ptr->mmx_bitdepth_threshold = 0; + +# if (defined(PNG_USE_PNGVCRD) || defined(PNG_USE_PNGGCCRD)) + + png_ptr->asm_flags |= PNG_ASM_FLAG_MMX_SUPPORT_COMPILED; + + if (png_mmx_support() > 0) { + png_ptr->asm_flags |= PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU +# ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW + | PNG_ASM_FLAG_MMX_READ_COMBINE_ROW +# endif +# ifdef PNG_HAVE_ASSEMBLER_READ_INTERLACE + | PNG_ASM_FLAG_MMX_READ_INTERLACE +# endif +# ifndef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW + ; +# else + | PNG_ASM_FLAG_MMX_READ_FILTER_SUB + | PNG_ASM_FLAG_MMX_READ_FILTER_UP + | PNG_ASM_FLAG_MMX_READ_FILTER_AVG + | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ; + + png_ptr->mmx_rowbytes_threshold = PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT; + png_ptr->mmx_bitdepth_threshold = PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT; +# endif + } else { + png_ptr->asm_flags &= ~( PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU + | PNG_MMX_READ_FLAGS + | PNG_MMX_WRITE_FLAGS ); + } + +# else /* !((PNGVCRD || PNGGCCRD) && PNG_ASSEMBLER_CODE_SUPPORTED)) */ + + /* clear all MMX flags; no support is compiled in */ + png_ptr->asm_flags &= ~( PNG_MMX_FLAGS ); + +# endif /* ?(PNGVCRD || PNGGCCRD) */ +} + +#endif /* !(PNG_ASSEMBLER_CODE_SUPPORTED) */ + +/* this function was added to libpng 1.2.0 */ +#if !defined(PNG_USE_PNGGCCRD) && \ + !(defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_USE_PNGVCRD)) +int PNGAPI +png_mmx_support(void) +{ + return -1; +} +#endif +#endif /* PNG_1_0_X */ + +#ifdef PNG_SIZE_T +/* Added at libpng version 1.2.6 */ + PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); +png_size_t PNGAPI +png_convert_size(size_t size) +{ + if (size > (png_size_t)-1) + PNG_ABORT(); /* We haven't got access to png_ptr, so no png_error() */ + return ((png_size_t)size); +} +#endif /* PNG_SIZE_T */ diff --git a/Utilities/FLTK/png/png.h b/Utilities/FLTK/png/png.h new file mode 100644 index 0000000000..c5adadff5b --- /dev/null +++ b/Utilities/FLTK/png/png.h @@ -0,0 +1,3361 @@ +/* png.h - header file for PNG reference library + * + * libpng version 1.2.7 - September 12, 2004 + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.2.7 - September 12, 2004: Glenn + * See also "Contributing Authors", below. + * + * Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + * 1.0.8rc1 1 10008 2.1.0.8rc1 + * 1.0.8 1 10008 2.1.0.8 + * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + * 1.0.9rc1 1 10009 2.1.0.9rc1 + * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + * 1.0.9rc2 1 10009 2.1.0.9rc2 + * 1.0.9 1 10009 2.1.0.9 + * 1.0.10beta1 1 10010 2.1.0.10beta1 + * 1.0.10rc1 1 10010 2.1.0.10rc1 + * 1.0.10 1 10010 2.1.0.10 + * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + * 1.0.11rc1 1 10011 2.1.0.11rc1 + * 1.0.11 1 10011 2.1.0.11 + * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 + * 1.0.12rc1 2 10012 2.1.0.12rc1 + * 1.0.12 2 10012 2.1.0.12 + * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) + * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 + * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 + * 1.2.0rc1 3 10200 3.1.2.0rc1 + * 1.2.0 3 10200 3.1.2.0 + * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 + * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 + * 1.2.1 3 10201 3.1.2.1 + * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 + * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 + * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 + * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 + * 1.0.13 10 10013 10.so.0.1.0.13 + * 1.2.2 12 10202 12.so.0.1.2.2 + * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 + * 1.2.3 12 10203 12.so.0.1.2.3 + * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 + * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 + * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 + * 1.0.14 10 10014 10.so.0.1.0.14 + * 1.2.4 13 10204 12.so.0.1.2.4 + * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 + * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 + * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 + * 1.0.15 10 10015 10.so.0.1.0.15 + * 1.2.5 13 10205 12.so.0.1.2.5 + * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 + * 1.0.16 10 10016 10.so.0.1.0.16 + * 1.2.6 13 10206 12.so.0.1.2.6 + * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 + * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 + * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + * 1.0.17 10 10017 12.so.0.1.0.17 + * 1.2.7 13 10207 12.so.0.1.2.7 + * + * Henceforth the source version will match the shared-library major + * and minor numbers; the shared-library major version number will be + * used for changes in backward compatibility, as it is intended. The + * PNG_LIBPNG_VER macro, which is not used within libpng but is available + * for applications, is an unsigned integer of the form xyyzz corresponding + * to the source version x.y.z (leading zeros in y and z). Beta versions + * were given the previous public release number plus a letter, until + * version 1.0.6j; from then on they were given the upcoming public + * release number plus "betaNN" or "rcN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng.txt or libpng.3 for more information. The PNG specification + * is available as a W3C Recommendation and as an ISO Specification, + * <http://www.w3.org/TR/2003/REC-PNG-20031110/ + */ + +/* + * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + * + * If you modify libpng you may insert additional notices immediately following + * this sentence. + * + * libpng versions 1.2.6, August 15, 2004, through 1.2.7, September 12, 2004, are + * Copyright (c) 2004 Glenn Randers-Pehrson, and are + * distributed according to the same disclaimer and license as libpng-1.2.5 + * with the following individual added to the list of Contributing Authors: + * + * Cosmin Truta + * + * libpng versions 1.0.7, July 1, 2000, through 1.2.5, October 3, 2002, are + * Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are + * distributed according to the same disclaimer and license as libpng-1.0.6 + * with the following individuals added to the list of Contributing Authors: + * + * Simon-Pierre Cadieux + * Eric S. Raymond + * Gilles Vollant + * + * and with the following additions to the disclaimer: + * + * There is no warranty against interference with your enjoyment of the + * library or against infringement. There is no warranty that our + * efforts or the library will fulfill any of your particular purposes + * or needs. This library is provided with all faults, and the entire + * risk of satisfactory quality, performance, accuracy, and effort is with + * the user. + * + * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are + * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson, and are + * distributed according to the same disclaimer and license as libpng-0.96, + * with the following individuals added to the list of Contributing Authors: + * + * Tom Lane + * Glenn Randers-Pehrson + * Willem van Schaik + * + * libpng versions 0.89, June 1996, through 0.96, May 1997, are + * Copyright (c) 1996, 1997 Andreas Dilger + * Distributed according to the same disclaimer and license as libpng-0.88, + * with the following individuals added to the list of Contributing Authors: + * + * John Bowler + * Kevin Bracey + * Sam Bushell + * Magnus Holmgren + * Greg Roelofs + * Tom Tanner + * + * libpng versions 0.5, May 1995, through 0.88, January 1996, are + * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + * + * For the purposes of this copyright and license, "Contributing Authors" + * is defined as the following set of individuals: + * + * Andreas Dilger + * Dave Martindale + * Guy Eric Schalnat + * Paul Schmidt + * Tim Wegner + * + * The PNG Reference Library is supplied "AS IS". The Contributing Authors + * and Group 42, Inc. disclaim all warranties, expressed or implied, + * including, without limitation, the warranties of merchantability and of + * fitness for any purpose. The Contributing Authors and Group 42, Inc. + * assume no liability for direct, indirect, incidental, special, exemplary, + * or consequential damages, which may result from the use of the PNG + * Reference Library, even if advised of the possibility of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * source code, or portions hereof, for any purpose, without fee, subject + * to the following restrictions: + * + * 1. The origin of this source code must not be misrepresented. + * + * 2. Altered versions must be plainly marked as such and + * must not be misrepresented as being the original source. + * + * 3. This Copyright notice may not be removed or altered from + * any source or altered source distribution. + * + * The Contributing Authors and Group 42, Inc. specifically permit, without + * fee, and encourage the use of this source code as a component to + * supporting the PNG file format in commercial products. If you use this + * source code in a product, acknowledgment is not required but would be + * appreciated. + */ + +/* + * A "png_get_copyright" function is available, for convenient use in "about" + * boxes and the like: + * + * printf("%s",png_get_copyright(NULL)); + * + * Also, the PNG logo (in PNG format, of course) is supplied in the + * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + */ + +/* + * Libpng is OSI Certified Open Source Software. OSI Certified is a + * certification mark of the Open Source Initiative. + */ + +/* + * The contributing authors would like to thank all those who helped + * with testing, bug fixes, and patience. This wouldn't have been + * possible without all of you. + * + * Thanks to Frank J. T. Wojcik for helping with the documentation. + */ + +/* + * Y2K compliance in libpng: + * ========================= + * + * September 12, 2004 + * + * Since the PNG Development group is an ad-hoc body, we can't make + * an official declaration. + * + * This is your unofficial assurance that libpng from version 0.71 and + * upward through 1.2.7 are Y2K compliant. It is my belief that earlier + * versions were also Y2K compliant. + * + * Libpng only has three year fields. One is a 2-byte unsigned integer + * that will hold years up to 65535. The other two hold the date in text + * format, and will hold years up to 9999. + * + * The integer is + * "png_uint_16 year" in png_time_struct. + * + * The strings are + * "png_charp time_buffer" in png_struct and + * "near_time_buffer", which is a local character string in png.c. + * + * There are seven time-related functions: + * png.c: png_convert_to_rfc_1123() in png.c + * (formerly png_convert_to_rfc_1152() in error) + * png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c + * png_convert_from_time_t() in pngwrite.c + * png_get_tIME() in pngget.c + * png_handle_tIME() in pngrutil.c, called in pngread.c + * png_set_tIME() in pngset.c + * png_write_tIME() in pngwutil.c, called in pngwrite.c + * + * All handle dates properly in a Y2K environment. The + * png_convert_from_time_t() function calls gmtime() to convert from system + * clock time, which returns (year - 1900), which we properly convert to + * the full 4-digit year. There is a possibility that applications using + * libpng are not passing 4-digit years into the png_convert_to_rfc_1123() + * function, or that they are incorrectly passing only a 2-digit year + * instead of "year - 1900" into the png_convert_from_struct_tm() function, + * but this is not under our control. The libpng documentation has always + * stated that it works with 4-digit years, and the APIs have been + * documented as such. + * + * The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned + * integer to hold the year, and can hold years as large as 65535. + * + * zlib, upon which libpng depends, is also Y2K compliant. It contains + * no date-related code. + * + * Glenn Randers-Pehrson + * libpng maintainer + * PNG Development Group + */ + +#ifndef PNG_H +#define PNG_H + +/* This is not the place to learn how to use libpng. The file libpng.txt + * describes how to use libpng, and the file example.c summarizes it + * with some code on which to build. This file is useful for looking + * at the actual function definitions and structure components. + */ + +/* Version information for png.h - this should match the version in png.c */ +#define PNG_LIBPNG_VER_STRING "1.2.7" +#define PNG_HEADER_VERSION_STRING \ + " libpng version 1.2.7 - September 12, 2004 (header)\n" + +#define PNG_LIBPNG_VER_SONUM 0 +#define PNG_LIBPNG_VER_DLLNUM %DLLNUM% + +/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ +#define PNG_LIBPNG_VER_MAJOR 1 +#define PNG_LIBPNG_VER_MINOR 2 +#define PNG_LIBPNG_VER_RELEASE 7 +/* This should match the numeric part of the final component of + * PNG_LIBPNG_VER_STRING, omitting any leading zero: */ + +#define PNG_LIBPNG_VER_BUILD 0 + +#define PNG_LIBPNG_BUILD_ALPHA 1 +#define PNG_LIBPNG_BUILD_BETA 2 +#define PNG_LIBPNG_BUILD_RC 3 +#define PNG_LIBPNG_BUILD_STABLE 4 +#define PNG_LIBPNG_BUILD_TYPEMASK 7 +#define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with STABLE only */ +#define PNG_LIBPNG_BUILD_TYPE 4 + +/* Careful here. At one time, Guy wanted to use 082, but that would be octal. + * We must not include leading zeros. + * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only + * version 1.0.0 was mis-numbered 100 instead of 10000). From + * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release */ +#define PNG_LIBPNG_VER 10207 /* 1.2.7 */ + +#ifndef PNG_VERSION_INFO_ONLY + +/* include the compression library's header */ +#include "zlib.h" + +/* include all user configurable info, including optional assembler routines */ +#include "pngconf.h" + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* This file is arranged in several sections. The first section contains + * structure and type definitions. The second section contains the external + * library functions, while the third has the internal library functions, + * which applications aren't expected to use directly. + */ + +#ifndef PNG_NO_TYPECAST_NULL +#define int_p_NULL (int *)NULL +#define png_bytep_NULL (png_bytep)NULL +#define png_bytepp_NULL (png_bytepp)NULL +#define png_doublep_NULL (png_doublep)NULL +#define png_error_ptr_NULL (png_error_ptr)NULL +#define png_flush_ptr_NULL (png_flush_ptr)NULL +#define png_free_ptr_NULL (png_free_ptr)NULL +#define png_infopp_NULL (png_infopp)NULL +#define png_malloc_ptr_NULL (png_malloc_ptr)NULL +#define png_read_status_ptr_NULL (png_read_status_ptr)NULL +#define png_rw_ptr_NULL (png_rw_ptr)NULL +#define png_structp_NULL (png_structp)NULL +#define png_uint_16p_NULL (png_uint_16p)NULL +#define png_voidp_NULL (png_voidp)NULL +#define png_write_status_ptr_NULL (png_write_status_ptr)NULL +#else +#define int_p_NULL NULL +#define png_bytep_NULL NULL +#define png_bytepp_NULL NULL +#define png_doublep_NULL NULL +#define png_error_ptr_NULL NULL +#define png_flush_ptr_NULL NULL +#define png_free_ptr_NULL NULL +#define png_infopp_NULL NULL +#define png_malloc_ptr_NULL NULL +#define png_read_status_ptr_NULL NULL +#define png_rw_ptr_NULL NULL +#define png_structp_NULL NULL +#define png_uint_16p_NULL NULL +#define png_voidp_NULL NULL +#define png_write_status_ptr_NULL NULL +#endif + +/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */ +#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN) +/* Version information for C files, stored in png.c. This had better match + * the version above. + */ +#ifdef PNG_USE_GLOBAL_ARRAYS +PNG_EXPORT_VAR (const char) png_libpng_ver[18]; + /* need room for 99.99.99beta99z */ +#else +#define png_libpng_ver png_get_header_ver(NULL) +#endif + +#ifdef PNG_USE_GLOBAL_ARRAYS +/* This was removed in version 1.0.5c */ +/* Structures to facilitate easy interlacing. See png.c for more details */ +PNG_EXPORT_VAR (const int FARDATA) png_pass_start[7]; +PNG_EXPORT_VAR (const int FARDATA) png_pass_inc[7]; +PNG_EXPORT_VAR (const int FARDATA) png_pass_ystart[7]; +PNG_EXPORT_VAR (const int FARDATA) png_pass_yinc[7]; +PNG_EXPORT_VAR (const int FARDATA) png_pass_mask[7]; +PNG_EXPORT_VAR (const int FARDATA) png_pass_dsp_mask[7]; +#ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW +PNG_EXPORT_VAR (const int FARDATA) png_pass_width[7]; +#endif +/* This isn't currently used. If you need it, see png.c for more details. +PNG_EXPORT_VAR (const int FARDATA) png_pass_height[7]; +*/ +#endif + +#endif /* PNG_NO_EXTERN */ + +/* Three color definitions. The order of the red, green, and blue, (and the + * exact size) is not important, although the size of the fields need to + * be png_byte or png_uint_16 (as defined below). + */ +typedef struct png_color_struct +{ + png_byte red; + png_byte green; + png_byte blue; +} png_color; +typedef png_color FAR * png_colorp; +typedef png_color FAR * FAR * png_colorpp; + +typedef struct png_color_16_struct +{ + png_byte index; /* used for palette files */ + png_uint_16 red; /* for use in red green blue files */ + png_uint_16 green; + png_uint_16 blue; + png_uint_16 gray; /* for use in grayscale files */ +} png_color_16; +typedef png_color_16 FAR * png_color_16p; +typedef png_color_16 FAR * FAR * png_color_16pp; + +typedef struct png_color_8_struct +{ + png_byte red; /* for use in red green blue files */ + png_byte green; + png_byte blue; + png_byte gray; /* for use in grayscale files */ + png_byte alpha; /* for alpha channel files */ +} png_color_8; +typedef png_color_8 FAR * png_color_8p; +typedef png_color_8 FAR * FAR * png_color_8pp; + +/* + * The following two structures are used for the in-core representation + * of sPLT chunks. + */ +typedef struct png_sPLT_entry_struct +{ + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + png_uint_16 alpha; + png_uint_16 frequency; +} png_sPLT_entry; +typedef png_sPLT_entry FAR * png_sPLT_entryp; +typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp; + +/* When the depth of the sPLT palette is 8 bits, the color and alpha samples + * occupy the LSB of their respective members, and the MSB of each member + * is zero-filled. The frequency member always occupies the full 16 bits. + */ + +typedef struct png_sPLT_struct +{ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ + png_sPLT_entryp entries; /* palette entries */ + png_int_32 nentries; /* number of palette entries */ +} png_sPLT_t; +typedef png_sPLT_t FAR * png_sPLT_tp; +typedef png_sPLT_t FAR * FAR * png_sPLT_tpp; + +#ifdef PNG_TEXT_SUPPORTED +/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, + * and whether that contents is compressed or not. The "key" field + * points to a regular zero-terminated C string. The "text", "lang", and + * "lang_key" fields can be regular C strings, empty strings, or NULL pointers. + * However, the * structure returned by png_get_text() will always contain + * regular zero-terminated C strings (possibly empty), never NULL pointers, + * so they can be safely used in printf() and other string-handling functions. + */ +typedef struct png_text_struct +{ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ + png_charp key; /* keyword, 1-79 character description of "text" */ + png_charp text; /* comment, may be an empty string (ie "") + or a NULL pointer */ + png_size_t text_length; /* length of the text string */ +#ifdef PNG_iTXt_SUPPORTED + png_size_t itxt_length; /* length of the itxt string */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ +#endif +} png_text; +typedef png_text FAR * png_textp; +typedef png_text FAR * FAR * png_textpp; +#endif + +/* Supported compression types for text in PNG files (tEXt, and zTXt). + * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ +#define PNG_TEXT_COMPRESSION_NONE_WR -3 +#define PNG_TEXT_COMPRESSION_zTXt_WR -2 +#define PNG_TEXT_COMPRESSION_NONE -1 +#define PNG_TEXT_COMPRESSION_zTXt 0 +#define PNG_ITXT_COMPRESSION_NONE 1 +#define PNG_ITXT_COMPRESSION_zTXt 2 +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ + +/* png_time is a way to hold the time in an machine independent way. + * Two conversions are provided, both from time_t and struct tm. There + * is no portable way to convert to either of these structures, as far + * as I know. If you know of a portable way, send it to me. As a side + * note - PNG has always been Year 2000 compliant! + */ +typedef struct png_time_struct +{ + png_uint_16 year; /* full year, as in, 1995 */ + png_byte month; /* month of year, 1 - 12 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ + png_byte minute; /* minute of hour, 0 - 59 */ + png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ +} png_time; +typedef png_time FAR * png_timep; +typedef png_time FAR * FAR * png_timepp; + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +/* png_unknown_chunk is a structure to hold queued chunks for which there is + * no specific support. The idea is that we can use this to queue + * up private chunks for output even though the library doesn't actually + * know about their semantics. + */ +typedef struct png_unknown_chunk_t +{ + png_byte name[5]; + png_byte *data; + png_size_t size; + + /* libpng-using applications should NOT directly modify this byte. */ + png_byte location; /* mode of operation at read time */ +} +png_unknown_chunk; +typedef png_unknown_chunk FAR * png_unknown_chunkp; +typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp; +#endif + +/* png_info is a structure that holds the information in a PNG file so + * that the application can find out the characteristics of the image. + * If you are reading the file, this structure will tell you what is + * in the PNG file. If you are writing the file, fill in the information + * you want to put into the PNG file, then call png_write_info(). + * The names chosen should be very close to the PNG specification, so + * consult that document for information about the meaning of each field. + * + * With libpng < 0.95, it was only possible to directly set and read the + * the values in the png_info_struct, which meant that the contents and + * order of the values had to remain fixed. With libpng 0.95 and later, + * however, there are now functions that abstract the contents of + * png_info_struct from the application, so this makes it easier to use + * libpng with dynamic libraries, and even makes it possible to use + * libraries that don't have all of the libpng ancillary chunk-handing + * functionality. + * + * In any case, the order of the parameters in png_info_struct should NOT + * be changed for as long as possible to keep compatibility with applications + * that use the old direct-access method with png_info_struct. + * + * The following members may have allocated storage attached that should be + * cleaned up before the structure is discarded: palette, trans, text, + * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile, + * splt_palettes, scal_unit, row_pointers, and unknowns. By default, these + * are automatically freed when the info structure is deallocated, if they were + * allocated internally by libpng. This behavior can be changed by means + * of the png_data_freer() function. + * + * More allocation details: all the chunk-reading functions that + * change these members go through the corresponding png_set_* + * functions. A function to clear these members is available: see + * png_free_data(). The png_set_* functions do not depend on being + * able to point info structure members to any of the storage they are + * passed (they make their own copies), EXCEPT that the png_set_text + * functions use the same storage passed to them in the text_ptr or + * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns + * functions do not make their own copies. + */ +typedef struct png_info_struct +{ + /* the following are necessary for every PNG file */ + png_uint_32 width; /* width of image in pixels (from IHDR) */ + png_uint_32 height; /* height of image in pixels (from IHDR) */ + png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ + png_uint_32 rowbytes; /* bytes needed to hold an untransformed row */ + png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ + png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ + png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ + png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ + png_byte color_type; /* see PNG_COLOR_TYPE_ below (from IHDR) */ + /* The following three should have been named *_method not *_type */ + png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */ + png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */ + png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + + /* The following is informational only on read, and not used on writes. */ + png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte spare_byte; /* to align the data, and for future use */ + png_byte signature[8]; /* magic bytes read by libpng from start of file */ + + /* The rest of the data is optional. If you are reading, check the + * valid field to see if the information in these are valid. If you + * are writing, set the valid field to those chunks you want written, + * and initialize the appropriate fields below. + */ + +#if defined(PNG_gAMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) + /* The gAMA chunk describes the gamma characteristics of the system + * on which the image was created, normally in the range [1.0, 2.5]. + * Data is valid if (valid & PNG_INFO_gAMA) is non-zero. + */ + float gamma; /* gamma value of image, if (valid & PNG_INFO_gAMA) */ +#endif + +#if defined(PNG_sRGB_SUPPORTED) + /* GR-P, 0.96a */ + /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */ + png_byte srgb_intent; /* sRGB rendering intent [0, 1, 2, or 3] */ +#endif + +#if defined(PNG_TEXT_SUPPORTED) + /* The tEXt, and zTXt chunks contain human-readable textual data in + * uncompressed, compressed, and optionally compressed forms, respectively. + * The data in "text" is an array of pointers to uncompressed, + * null-terminated C strings. Each chunk has a keyword that describes the + * textual data contained in that chunk. Keywords are not required to be + * unique, and the text string may be empty. Any number of text chunks may + * be in an image. + */ + int num_text; /* number of comments read/to write */ + int max_text; /* current size of text array */ + png_textp text; /* array of comments read/to write */ +#endif /* PNG_TEXT_SUPPORTED */ + +#if defined(PNG_tIME_SUPPORTED) + /* The tIME chunk holds the last time the displayed image data was + * modified. See the png_time struct for the contents of this struct. + */ + png_time mod_time; +#endif + +#if defined(PNG_sBIT_SUPPORTED) + /* The sBIT chunk specifies the number of significant high-order bits + * in the pixel data. Values are in the range [1, bit_depth], and are + * only specified for the channels in the pixel data. The contents of + * the low-order bits is not specified. Data is valid if + * (valid & PNG_INFO_sBIT) is non-zero. + */ + png_color_8 sig_bit; /* significant bits in color channels */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \ +defined(PNG_READ_BACKGROUND_SUPPORTED) + /* The tRNS chunk supplies transparency data for paletted images and + * other image types that don't need a full alpha channel. There are + * "num_trans" transparency values for a paletted image, stored in the + * same order as the palette colors, starting from index 0. Values + * for the data are in the range [0, 255], ranging from fully transparent + * to fully opaque, respectively. For non-paletted images, there is a + * single color specified that should be treated as fully transparent. + * Data is valid if (valid & PNG_INFO_tRNS) is non-zero. + */ + png_bytep trans; /* transparent values for paletted image */ + png_color_16 trans_values; /* transparent color for non-palette image */ +#endif + +#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + /* The bKGD chunk gives the suggested image background color if the + * display program does not have its own background color and the image + * is needs to composited onto a background before display. The colors + * in "background" are normally in the same color space/depth as the + * pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero. + */ + png_color_16 background; +#endif + +#if defined(PNG_oFFs_SUPPORTED) + /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards + * and downwards from the top-left corner of the display, page, or other + * application-specific co-ordinate space. See the PNG_OFFSET_ defines + * below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero. + */ + png_int_32 x_offset; /* x offset on page */ + png_int_32 y_offset; /* y offset on page */ + png_byte offset_unit_type; /* offset units type */ +#endif + +#if defined(PNG_pHYs_SUPPORTED) + /* The pHYs chunk gives the physical pixel density of the image for + * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_ + * defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero. + */ + png_uint_32 x_pixels_per_unit; /* horizontal pixel density */ + png_uint_32 y_pixels_per_unit; /* vertical pixel density */ + png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */ +#endif + +#if defined(PNG_hIST_SUPPORTED) + /* The hIST chunk contains the relative frequency or importance of the + * various palette entries, so that a viewer can intelligently select a + * reduced-color palette, if required. Data is an array of "num_palette" + * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST) + * is non-zero. + */ + png_uint_16p hist; +#endif + +#ifdef PNG_cHRM_SUPPORTED + /* The cHRM chunk describes the CIE color characteristics of the monitor + * on which the PNG was created. This data allows the viewer to do gamut + * mapping of the input image to ensure that the viewer sees the same + * colors in the image as the creator. Values are in the range + * [0.0, 0.8]. Data valid if (valid & PNG_INFO_cHRM) non-zero. + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED + float x_white; + float y_white; + float x_red; + float y_red; + float x_green; + float y_green; + float x_blue; + float y_blue; +#endif +#endif + +#if defined(PNG_pCAL_SUPPORTED) + /* The pCAL chunk describes a transformation between the stored pixel + * values and original physical data values used to create the image. + * The integer range [0, 2^bit_depth - 1] maps to the floating-point + * range given by [pcal_X0, pcal_X1], and are further transformed by a + * (possibly non-linear) transformation function given by "pcal_type" + * and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_ + * defines below, and the PNG-Group's PNG extensions document for a + * complete description of the transformations and how they should be + * implemented, and for a description of the ASCII parameter strings. + * Data values are valid if (valid & PNG_INFO_pCAL) non-zero. + */ + png_charp pcal_purpose; /* pCAL chunk description string */ + png_int_32 pcal_X0; /* minimum value */ + png_int_32 pcal_X1; /* maximum value */ + png_charp pcal_units; /* Latin-1 string giving physical units */ + png_charpp pcal_params; /* ASCII strings containing parameter values */ + png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */ + png_byte pcal_nparams; /* number of parameters given in pcal_params */ +#endif + +/* New members added in libpng-1.0.6 */ +#ifdef PNG_FREE_ME_SUPPORTED + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + /* storage for unknown chunks that the library doesn't recognize. */ + png_unknown_chunkp unknown_chunks; + png_size_t unknown_chunks_num; +#endif + +#if defined(PNG_iCCP_SUPPORTED) + /* iCCP chunk data. */ + png_charp iccp_name; /* profile name */ + png_charp iccp_profile; /* International Color Consortium profile data */ + /* Note to maintainer: should be png_bytep */ + png_uint_32 iccp_proflen; /* ICC profile data length */ + png_byte iccp_compression; /* Always zero */ +#endif + +#if defined(PNG_sPLT_SUPPORTED) + /* data on sPLT chunks (there may be more than one). */ + png_sPLT_tp splt_palettes; + png_uint_32 splt_palettes_num; +#endif + +#if defined(PNG_sCAL_SUPPORTED) + /* The sCAL chunk describes the actual physical dimensions of the + * subject matter of the graphic. The chunk contains a unit specification + * a byte value, and two ASCII strings representing floating-point + * values. The values are width and height corresponsing to one pixel + * in the image. This external representation is converted to double + * here. Data values are valid if (valid & PNG_INFO_sCAL) is non-zero. + */ + png_byte scal_unit; /* unit of physical scale */ +#ifdef PNG_FLOATING_POINT_SUPPORTED + double scal_pixel_width; /* width of one pixel */ + double scal_pixel_height; /* height of one pixel */ +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_charp scal_s_width; /* string containing height */ + png_charp scal_s_height; /* string containing width */ +#endif +#endif + +#if defined(PNG_INFO_IMAGE_SUPPORTED) + /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) non-zero */ + /* Data valid if (valid & PNG_INFO_IDAT) non-zero */ + png_bytepp row_pointers; /* the image bits */ +#endif + +#if defined(PNG_FIXED_POINT_SUPPORTED) && defined(PNG_gAMA_SUPPORTED) + png_fixed_point int_gamma; /* gamma of image, if (valid & PNG_INFO_gAMA) */ +#endif + +#if defined(PNG_cHRM_SUPPORTED) && defined(PNG_FIXED_POINT_SUPPORTED) + png_fixed_point int_x_white; + png_fixed_point int_y_white; + png_fixed_point int_x_red; + png_fixed_point int_y_red; + png_fixed_point int_x_green; + png_fixed_point int_y_green; + png_fixed_point int_x_blue; + png_fixed_point int_y_blue; +#endif + +} png_info; + +typedef png_info FAR * png_infop; +typedef png_info FAR * FAR * png_infopp; + +/* Maximum positive integer used in PNG is (2^31)-1 */ +#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) +#define PNG_UINT_32_MAX (~((png_uint_32)0)) +#define PNG_SIZE_MAX (~((png_size_t)0)) +/* PNG_MAX_UINT is deprecated; use PNG_UINT_31_MAX instead. */ +#define PNG_MAX_UINT PNG_UINT_31_MAX + +/* These describe the color_type field in png_info. */ +/* color type masks */ +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 + +/* color types. Note that not all combinations are legal */ +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) +#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) +/* aliases */ +#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA +#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA + +/* This is for compression type. PNG 1.0-1.2 only define the single type. */ +#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ +#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE + +/* This is for filter type. PNG 1.0-1.2 only define the single type. */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ +#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE + +/* These are for the interlacing type. These values should NOT be changed. */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ + +/* These are for the oFFs chunk. These values should NOT be changed. */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ + +/* These are for the pCAL chunk. These values should NOT be changed. */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ + +/* These are for the sCAL chunk. These values should NOT be changed. */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ + +/* These are for the pHYs chunk. These values should NOT be changed. */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ + +/* These are for the sRGB chunk. These values should NOT be changed. */ +#define PNG_sRGB_INTENT_PERCEPTUAL 0 +#define PNG_sRGB_INTENT_RELATIVE 1 +#define PNG_sRGB_INTENT_SATURATION 2 +#define PNG_sRGB_INTENT_ABSOLUTE 3 +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ + +/* This is for text chunks */ +#define PNG_KEYWORD_MAX_LENGTH 79 + +/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ +#define PNG_MAX_PALETTE_LENGTH 256 + +/* These determine if an ancillary chunk's data has been successfully read + * from the PNG header, or if the application has filled in the corresponding + * data in the info_struct to be written into the output file. The values + * of the PNG_INFO_<chunk> defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001 +#define PNG_INFO_sBIT 0x0002 +#define PNG_INFO_cHRM 0x0004 +#define PNG_INFO_PLTE 0x0008 +#define PNG_INFO_tRNS 0x0010 +#define PNG_INFO_bKGD 0x0020 +#define PNG_INFO_hIST 0x0040 +#define PNG_INFO_pHYs 0x0080 +#define PNG_INFO_oFFs 0x0100 +#define PNG_INFO_tIME 0x0200 +#define PNG_INFO_pCAL 0x0400 +#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + png_uint_32 rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info FAR * png_row_infop; +typedef png_row_info FAR * FAR * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. + */ +typedef struct png_struct_def png_struct; +typedef png_struct FAR * png_structp; + +typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp)); +typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t)); +typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp)); +typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32, + int)); +typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, png_infop)); +typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop)); +typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp, + png_row_infop, png_bytep)); +#endif + +#if defined(PNG_USER_CHUNKS_SUPPORTED) +typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, png_unknown_chunkp)); +#endif +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp)); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* WRITE only */ + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_size_t)); +typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); + +/* The structure that holds the information to read and write PNG files. + * The only people who need to care about what is inside of this are the + * people who will be modifying the library for their own special needs. + * It should NOT be accessed directly by an application, except to store + * the jmp_buf. + */ + +struct png_struct_def +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf jmpbuf; /* used in png_error */ +#endif + png_error_ptr error_fn; /* function for printing errors and aborting */ + png_error_ptr warning_fn; /* function for printing warnings */ + png_voidp error_ptr; /* user supplied struct for error functions */ + png_rw_ptr write_data_fn; /* function for writing output data */ + png_rw_ptr read_data_fn; /* function for reading input data */ + png_voidp io_ptr; /* ptr to application struct for I/O functions */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + png_user_transform_ptr read_user_transform_fn; /* user read transform */ +#endif + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_user_transform_ptr write_user_transform_fn; /* user write transform */ +#endif + +/* These were added in libpng-1.0.2 */ +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_voidp user_transform_ptr; /* user supplied struct for user transform */ + png_byte user_transform_depth; /* bit depth of user transformed pixels */ + png_byte user_transform_channels; /* channels in user transformed pixels */ +#endif +#endif + + png_uint_32 mode; /* tells us where we are in the PNG file */ + png_uint_32 flags; /* flags indicating various things to libpng */ + png_uint_32 transformations; /* which transformations to perform */ + + z_stream zstream; /* pointer to decompression structure (below) */ + png_bytep zbuf; /* buffer for zlib */ + png_size_t zbuf_size; /* size of zbuf */ + int zlib_level; /* holds zlib compression level */ + int zlib_method; /* holds zlib compression method */ + int zlib_window_bits; /* holds zlib compression window bits */ + int zlib_mem_level; /* holds zlib compression memory level */ + int zlib_strategy; /* holds zlib compression strategy */ + + png_uint_32 width; /* width of image in pixels */ + png_uint_32 height; /* height of image in pixels */ + png_uint_32 num_rows; /* number of rows in current pass */ + png_uint_32 usr_width; /* width of row at start of write */ + png_uint_32 rowbytes; /* size of row in bytes */ + png_uint_32 irowbytes; /* size of current interlaced row in bytes */ + png_uint_32 iwidth; /* width of current interlaced row in pixels */ + png_uint_32 row_number; /* current row in interlace pass */ + png_bytep prev_row; /* buffer to save previous (unfiltered) row */ + png_bytep row_buf; /* buffer to save current (unfiltered) row */ + png_bytep sub_row; /* buffer to save "sub" row when filtering */ + png_bytep up_row; /* buffer to save "up" row when filtering */ + png_bytep avg_row; /* buffer to save "avg" row when filtering */ + png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ + png_row_info row_info; /* used for transformation routines */ + + png_uint_32 idat_size; /* current IDAT size for read */ + png_uint_32 crc; /* current chunk CRC value */ + png_colorp palette; /* palette from the input file */ + png_uint_16 num_palette; /* number of color entries in palette */ + png_uint_16 num_trans; /* number of transparency values */ + png_byte chunk_name[5]; /* null-terminated name of current chunk */ + png_byte compression; /* file compression type (always 0) */ + png_byte filter; /* file filter type (always 0) */ + png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + png_byte pass; /* current interlace pass (0 - 6) */ + png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ + png_byte color_type; /* color type of file */ + png_byte bit_depth; /* bit depth of file */ + png_byte usr_bit_depth; /* bit depth of users row */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte channels; /* number of channels in file */ + png_byte usr_channels; /* channels at start of write */ + png_byte sig_bytes; /* magic bytes read/written from start of file */ + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +#ifdef PNG_LEGACY_SUPPORTED + png_byte filler; /* filler byte for pixel expansion */ +#else + png_uint_16 filler; /* filler bytes for pixel expansion */ +#endif +#endif + +#if defined(PNG_bKGD_SUPPORTED) + png_byte background_gamma_type; +# ifdef PNG_FLOATING_POINT_SUPPORTED + float background_gamma; +# endif + png_color_16 background; /* background color in screen gamma space */ +#if defined(PNG_READ_GAMMA_SUPPORTED) + png_color_16 background_1; /* background normalized to gamma 1.0 */ +#endif +#endif /* PNG_bKGD_SUPPORTED */ + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) + png_flush_ptr output_flush_fn;/* Function for flushing output */ + png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ + png_uint_32 flush_rows; /* number of rows written since last flush */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + int gamma_shift; /* number of "insignificant" bits 16-bit gamma */ +#ifdef PNG_FLOATING_POINT_SUPPORTED + float gamma; /* file gamma value */ + float screen_gamma; /* screen gamma value (display_exponent) */ +#endif +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep gamma_table; /* gamma table for 8-bit depth files */ + png_bytep gamma_from_1; /* converts from 1.0 to screen */ + png_bytep gamma_to_1; /* converts from file to 1.0 */ + png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ + png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ + png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) + png_color_8 sig_bit; /* significant bits in each available channel */ +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) + png_color_8 shift; /* shift for significant bit tranformation */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ + || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep trans; /* transparency values for paletted files */ + png_color_16 trans_values; /* transparency values for non-paletted files */ +#endif + + png_read_status_ptr read_row_fn; /* called after each row is decoded */ + png_write_status_ptr write_row_fn; /* called after each row is encoded */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_progressive_info_ptr info_fn; /* called after header data fully read */ + png_progressive_row_ptr row_fn; /* called after each prog. row is decoded */ + png_progressive_end_ptr end_fn; /* called after image is complete */ + png_bytep save_buffer_ptr; /* current location in save_buffer */ + png_bytep save_buffer; /* buffer for previously read data */ + png_bytep current_buffer_ptr; /* current location in current_buffer */ + png_bytep current_buffer; /* buffer for recently used data */ + png_uint_32 push_length; /* size of current input chunk */ + png_uint_32 skip_length; /* bytes to skip in input data */ + png_size_t save_buffer_size; /* amount of data now in save_buffer */ + png_size_t save_buffer_max; /* total size of save_buffer */ + png_size_t buffer_size; /* total amount of available input data */ + png_size_t current_buffer_size; /* amount of data now in current_buffer */ + int process_mode; /* what push library is currently doing */ + int cur_palette; /* current push library palette index */ + +# if defined(PNG_TEXT_SUPPORTED) + png_size_t current_text_size; /* current size of text input data */ + png_size_t current_text_left; /* how much text left to read in input */ + png_charp current_text; /* current text chunk buffer */ + png_charp current_text_ptr; /* current location in current_text */ +# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */ + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* for the Borland special 64K segment handler */ + png_bytepp offset_table_ptr; + png_bytep offset_table; + png_uint_16 offset_table_number; + png_uint_16 offset_table_count; + png_uint_16 offset_table_count_free; +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) + png_bytep palette_lookup; /* lookup table for dithering */ + png_bytep dither_index; /* index translation for palette files */ +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_hIST_SUPPORTED) + png_uint_16p hist; /* histogram */ +#endif + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + png_byte heuristic_method; /* heuristic for row filter selection */ + png_byte num_prev_filters; /* number of weights for previous rows */ + png_bytep prev_filters; /* filter type(s) of previous row(s) */ + png_uint_16p filter_weights; /* weight(s) for previous line(s) */ + png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ + png_uint_16p filter_costs; /* relative filter calculation cost */ + png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ +#endif + +#if defined(PNG_TIME_RFC1123_SUPPORTED) + png_charp time_buffer; /* String to hold RFC 1123 time text */ +#endif + +/* New members added in libpng-1.0.6 */ + +#ifdef PNG_FREE_ME_SUPPORTED + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ +#endif + +#if defined(PNG_USER_CHUNKS_SUPPORTED) + png_voidp user_chunk_ptr; + png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + int num_chunk_list; + png_bytep chunk_list; +#endif + +/* New members added in libpng-1.0.3 */ +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + png_byte rgb_to_gray_status; + /* These were changed from png_byte in libpng-1.0.6 */ + png_uint_16 rgb_to_gray_red_coeff; + png_uint_16 rgb_to_gray_green_coeff; + png_uint_16 rgb_to_gray_blue_coeff; +#endif + +/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ + defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* changed from png_byte to png_uint_32 at version 1.2.0 */ +#ifdef PNG_1_0_X + png_byte mng_features_permitted; +#else + png_uint_32 mng_features_permitted; +#endif /* PNG_1_0_X */ +#endif + +/* New member added in libpng-1.0.7 */ +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_fixed_point int_gamma; +#endif + +/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) + png_byte filter_type; +#endif + +#if defined(PNG_1_0_X) || (defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD)) +/* New member added in libpng-1.0.10, ifdef'ed out in 1.2.0 */ + png_uint_32 row_buf_size; +#endif + +/* New members added in libpng-1.2.0 */ +#if !defined(PNG_1_0_X) && defined(PNG_ASSEMBLER_CODE_SUPPORTED) + png_byte mmx_bitdepth_threshold; + png_uint_32 mmx_rowbytes_threshold; + png_uint_32 asm_flags; +#endif + +/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ +#ifdef PNG_USER_MEM_SUPPORTED + png_voidp mem_ptr; /* user supplied struct for mem functions */ + png_malloc_ptr malloc_fn; /* function for allocating memory */ + png_free_ptr free_fn; /* function for freeing memory */ +#endif + +/* New member added in libpng-1.0.13 and 1.2.0 */ + png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ + +#if defined(PNG_READ_DITHER_SUPPORTED) +/* The following three members were added at version 1.0.14 and 1.2.4 */ + png_bytep dither_sort; /* working sort array */ + png_bytep index_to_palette; /* where the original index currently is */ + /* in the palette */ + png_bytep palette_to_index; /* which original index points to this */ + /* palette color */ +#endif + +/* New members added in libpng-1.0.16 and 1.2.6 */ + png_byte compression_type; + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_uint_32 user_width_max; + png_uint_32 user_height_max; +#endif + +}; + + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef png_structp version_1_2_7; + +typedef png_struct FAR * FAR * png_structpp; + +/* Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + */ + +/* Returns the version number of the library */ +extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void)); + +/* Tell lib we have already handled the first <num_bytes> magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr, + int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, + png_size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +extern PNG_EXPORT(int,png_check_sig) PNGARG((png_bytep sig, int num)); + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +extern PNG_EXPORT(png_structp,png_create_read_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +extern PNG_EXPORT(png_structp,png_create_write_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)); + +#ifdef PNG_WRITE_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_compression_buffer_size) + PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_WRITE_SUPPORTED +extern PNG_EXPORT(void,png_set_compression_buffer_size) + PNGARG((png_structp png_ptr, png_uint_32 size)); +#endif + +/* Reset the compression stream */ +extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr)); + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_structp,png_create_read_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +extern PNG_EXPORT(png_structp,png_create_write_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +#endif + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_bytep data, png_size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr)); + +/* Allocate and initialize the info structure */ +extern PNG_EXPORT(png_infop,png_create_info_struct) + PNGARG((png_structp png_ptr)); + +/* Initialize the info structure (old interface - DEPRECATED) */ +extern PNG_EXPORT(void,png_info_init) PNGARG((png_infop info_ptr)); +#undef png_info_init +#define png_info_init(info_ptr) png_info_init_3(&info_ptr,\ + png_sizeof(png_info)); +extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr, + png_size_t png_info_struct_size)); + +/* Writes all the PNG information before the image. */ +extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read the information before the actual image data. */ +extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +#if defined(PNG_TIME_RFC1123_SUPPORTED) +extern PNG_EXPORT(png_charp,png_convert_to_rfc1123) + PNGARG((png_structp png_ptr, png_timep ptime)); +#endif + +#if !defined(_WIN32_WCE) +/* "time.h" functions are not supported on WindowsCE */ +#if defined(PNG_WRITE_tIME_SUPPORTED) +/* convert from a struct tm to png_time */ +extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime, + struct tm FAR * ttime)); + +/* convert from time_t to png_time. Uses gmtime() */ +extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime, + time_t ttime)); +#endif /* PNG_WRITE_tIME_SUPPORTED */ +#endif /* _WIN32_WCE */ + +#if defined(PNG_READ_EXPAND_SUPPORTED) +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_gray_1_2_4_to_8) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +/* Expand the grayscale to 24-bit RGB if necessary. */ +extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +/* Reduce RGB to grayscale. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr, + int error_action, double red, double green )); +#endif +extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green )); +extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp + png_ptr)); +#endif + +extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth, + png_colorp palette)); + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ +extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +#define PNG_FILLER_BEFORE 0 +#define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ +#if !defined(PNG_1_0_X) +extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); +#endif +#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr, + png_color_8p true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. */ +extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) +/* Handle alpha and tRNS by replacing with a background color. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, + png_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)); +#endif +#define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +#define PNG_BACKGROUND_GAMMA_SCREEN 1 +#define PNG_BACKGROUND_GAMMA_FILE 2 +#define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +/* strip the second byte of information from a 16-bit depth file. */ +extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +/* Turn on dithering, and reduce the palette to the number of colors available. */ +extern PNG_EXPORT(void,png_set_dither) PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_uint_16p histogram, int full_dither)); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) +/* Handle gamma correction. Screen_gamma=(display_exponent) */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, + double screen_gamma, double default_file_gamma)); +#endif +#endif + +#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* Permit or disallow empty PLTE (0: not permitted, 1: permitted) */ +/* Deprecated and will be removed. Use png_permit_mng_features() instead. */ +extern PNG_EXPORT(void,png_permit_empty_plte) PNGARG((png_structp png_ptr, + int empty_plte_permitted)); +#endif + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +/* Set how many lines between output flushes - 0 for no flushing */ +extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr)); +#endif + +/* optional update palette with requested transformations */ +extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr)); + +/* optional call to update the users info structure */ +extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read one or more rows of image data. */ +extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read a row of data. */ +extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr, + png_bytep row, + png_bytep display_row)); +#endif + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read the whole image into memory at once. */ +extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr, + png_bytepp image)); +#endif + +/* write a row of image data */ +extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr, + png_bytep row)); + +/* write a few rows of image data */ +extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_uint_32 num_rows)); + +/* write the image data */ +extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, + png_bytepp image)); + +/* writes the end of the PNG file. */ +extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read the end of the PNG file. */ +extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +/* free any memory associated with the png_info_struct */ +extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr, + png_infopp info_ptr_ptr)); + +/* free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp + png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* free all memory used by the read (old method - NOT DLL EXPORTED) */ +extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr, + png_infop end_info_ptr)); + +/* free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_write_struct) + PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); + +/* free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ +extern void png_write_destroy PNGARG((png_structp png_ptr)); + +/* set the libpng method of handling chunk CRC errors */ +extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, + int crit_action, int ancil_action)); + +/* Values for png_set_crc_action() to say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explination of the compression functions. + */ + +/* set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, + int filters)); + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ + PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* EXPERIMENTAL */ +/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ + * defines, either the default (minimum-sum-of-absolute-differences), or + * the experimental method (weighted-minimum-sum-of-absolute-differences). + * + * Weights are factors >= 1.0, indicating how important it is to keep the + * filter type consistent between rows. Larger numbers mean the current + * filter is that many times as likely to be the same as the "num_weights" + * previous filters. This is cumulative for each previous row with a weight. + * There needs to be "num_weights" values in "filter_weights", or it can be + * NULL if the weights aren't being specified. Weights have no influence on + * the selection of the first row filter. Well chosen weights can (in theory) + * improve the compression for a given image. + * + * Costs are factors >= 1.0 indicating the relative decoding costs of a + * filter type. Higher costs indicate more decoding expense, and are + * therefore less likely to be selected over a filter with lower computational + * costs. There needs to be a value in "filter_costs" for each valid filter + * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't + * setting the costs. Costs try to improve the speed of decompression without + * unduly increasing the compressed image size. + * + * A negative weight or cost indicates the default value is to be used, and + * values in the range [0.0, 1.0) indicate the value is to remain unchanged. + * The default values for both weights and costs are currently 1.0, but may + * change if good general weighting/cost heuristics can be found. If both + * the weights and costs are set to 1.0, this degenerates the WEIGHTED method + * to the UNWEIGHTED method, but with added encoding time/computation. + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, + int heuristic_method, int num_weights, png_doublep filter_weights, + png_doublep filter_costs)); +#endif +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +/* Heuristic used for row filter selection. These defines should NOT be + * changed. + */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer caclulations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr, + int level)); + +extern PNG_EXPORT(void,png_set_compression_mem_level) + PNGARG((png_structp png_ptr, int mem_level)); + +extern PNG_EXPORT(void,png_set_compression_strategy) + PNGARG((png_structp png_ptr, int strategy)); + +extern PNG_EXPORT(void,png_set_compression_window_bits) + PNGARG((png_structp png_ptr, int window_bits)); + +extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr, + int method)); + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng.txt for + * more information. + */ + +#if !defined(PNG_NO_STDIO) +/* Initialize the input/output for the PNG file to the default functions. */ +extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + */ +extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr)); + +extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr, + png_read_status_ptr read_row_fn)); + +extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr read_user_transform_fn)); +#endif + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr write_user_transform_fn)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp + png_ptr, png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr) + PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp + png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr, + png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn)); + +/* returns the user pointer associated with the push read functions */ +extern PNG_EXPORT(png_voidp,png_get_progressive_ptr) + PNGARG((png_structp png_ptr)); + +/* function to be called when data becomes available */ +extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); + +/* function that combines rows. Not very much different than the + * png_combine_row() call. Is this even used????? + */ +extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr, + png_bytep old_row, png_bytep new_row)); +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr, + png_uint_32 size)); + +#if defined(PNG_1_0_X) +# define png_malloc_warn png_malloc +#else +/* Added at libpng version 1.2.4 */ +extern PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr, + png_uint_32 size)); +#endif + +/* frees a pointer allocated by png_malloc() */ +extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); + +#if defined(PNG_1_0_X) +/* Function to allocate memory for zlib. */ +extern PNG_EXPORT(voidpf,png_zalloc) PNGARG((voidpf png_ptr, uInt items, + uInt size)); + +/* Function to free memory for zlib */ +extern PNG_EXPORT(void,png_zfree) PNGARG((voidpf png_ptr, voidpf ptr)); +#endif + +/* Free data that was allocated internally */ +extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 free_me, int num)); +#ifdef PNG_FREE_ME_SUPPORTED +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application */ +extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, + png_infop info_ptr, int freer, png_uint_32 mask)); +#endif +/* assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008 +#define PNG_FREE_ICCP 0x0010 +#define PNG_FREE_SPLT 0x0020 +#define PNG_FREE_ROWS 0x0040 +#define PNG_FREE_PCAL 0x0080 +#define PNG_FREE_SCAL 0x0100 +#define PNG_FREE_UNKN 0x0200 +#define PNG_FREE_LIST 0x0400 +#define PNG_FREE_PLTE 0x1000 +#define PNG_FREE_TRNS 0x2000 +#define PNG_FREE_TEXT 0x4000 +#define PNG_FREE_ALL 0x7fff +#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr, + png_uint_32 size)); +extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr, + png_voidp ptr)); +#endif + +extern PNG_EXPORT(png_voidp,png_memcpy_check) PNGARG((png_structp png_ptr, + png_voidp s1, png_voidp s2, png_uint_32 size)); + +extern PNG_EXPORT(png_voidp,png_memset_check) PNGARG((png_structp png_ptr, + png_voidp s1, int value, png_uint_32 size)); + +#if defined(USE_FAR_KEYWORD) /* memory model conversion function */ +extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr, + int check)); +#endif /* USE_FAR_KEYWORD */ + +/* Fatal error in PNG image of libpng - can't continue */ +extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)); + +/* The same, but the chunk name is prepended to the error string. */ +extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)); + +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +/* The png_set_<chunk> functions are for storing values in the png_info_struct. + * Similarly, the png_get_<chunk> calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_<chunk> functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr, +png_infop info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +extern PNG_EXPORT(png_uint_32,png_get_rowbytes) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +/* Returns row_pointers, which is an array of pointers to scanlines that was +returned from png_read_png(). */ +extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr, +png_infop info_ptr)); +/* Set row_pointers, which is an array of pointers to scanlines for use +by png_write_png(). */ +extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image height in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image bit_depth. */ +extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image color_type. */ +extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image filter_type. */ +extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image interlace_type. */ +extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image compression_type. */ +extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +#endif + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +/* Returns pointer to signature string read from PNG header */ +extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#if defined(PNG_bKGD_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p *background)); +#endif + +#if defined(PNG_bKGD_SUPPORTED) +extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p background)); +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_white_x, png_fixed_point + *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point + *int_blue_x, png_fixed_point *int_blue_y)); +#endif +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double white_x, double white_y, double red_x, + double red_y, double green_x, double green_y, double blue_x, double blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif +#endif + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *file_gamma)); +#endif +extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_file_gamma)); +#endif + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double file_gamma)); +#endif +extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_file_gamma)); +#endif + +#if defined(PNG_hIST_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p *hist)); +#endif + +#if defined(PNG_hIST_SUPPORTED) +extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p hist)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#if defined(PNG_oFFs_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#if defined(PNG_oFFs_SUPPORTED) +extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#if defined(PNG_pCAL_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1, + int *type, int *nparams, png_charp *units, png_charpp *params)); +#endif + +#if defined(PNG_pCAL_SUPPORTED) +extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_charp units, png_charpp params)); +#endif + +#if defined(PNG_pHYs_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif + +#if defined(PNG_pHYs_SUPPORTED) +extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp *palette, int *num_palette)); + +extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp palette, int num_palette)); + +#if defined(PNG_sBIT_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p *sig_bit)); +#endif + +#if defined(PNG_sBIT_SUPPORTED) +extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p sig_bit)); +#endif + +#if defined(PNG_sRGB_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *intent)); +#endif + +#if defined(PNG_sRGB_SUPPORTED) +extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +#endif + +#if defined(PNG_iCCP_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charpp name, int *compression_type, + png_charpp profile, png_uint_32 *proflen)); + /* Note to maintainer: profile should be png_bytepp */ +#endif + +#if defined(PNG_iCCP_SUPPORTED) +extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp name, int compression_type, + png_charp profile, png_uint_32 proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#if defined(PNG_sPLT_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tpp entries)); +#endif + +#if defined(PNG_sPLT_SUPPORTED) +extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tp entries, int nentries)); +#endif + +#if defined(PNG_TEXT_SUPPORTED) +/* png_get_text also returns the number of text chunks in *num_text */ +extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* + * Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#if defined(PNG_TEXT_SUPPORTED) +extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)); +#endif + +#if defined(PNG_tIME_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep *mod_time)); +#endif + +#if defined(PNG_tIME_SUPPORTED) +extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep mod_time)); +#endif + +#if defined(PNG_tRNS_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep *trans, int *num_trans, + png_color_16p *trans_values)); +#endif + +#if defined(PNG_tRNS_SUPPORTED) +extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep trans, int num_trans, + png_color_16p trans_values)); +#endif + +#if defined(PNG_tRNS_SUPPORTED) +#endif + +#if defined(PNG_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, double *width, double *height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight)); +#endif +#endif +#endif /* PNG_sCAL_SUPPORTED */ + +#if defined(PNG_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, double width, double height)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, png_charp swidth, png_charp sheight)); +#endif +#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +/* provide a list of chunks and how they are to be handled, if the built-in + handling or default unknown chunk handling is not desired. Any chunks not + listed will be handled in the default manner. The IHDR and IEND chunks + must not be listed. + keep = 0: follow default behavour + = 1: do not keep + = 2: keep only if safe-to-copy + = 3: keep even if unsafe-to-copy +*/ +extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp + png_ptr, int keep, png_bytep chunk_list, int num_chunks)); +extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)); +extern PNG_EXPORT(void, png_set_unknown_chunk_location) + PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location)); +extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp + png_ptr, png_infop info_ptr, png_unknown_chunkpp entries)); +#endif +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep + chunk_name)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + If you need to turn it off for a chunk that your application has freed, + you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); */ +extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, + png_infop info_ptr, int mask)); + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +/* The "params" pointer is currently not used and is for future expansion. */ +extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +#endif + +/* Define PNG_DEBUG at compile time for debugging information. Higher + * numbers for PNG_DEBUG mean more debugging information. This has + * only been added since version 0.95 so it is not implemented throughout + * libpng yet, but more support will be added as needed. + */ +#ifdef PNG_DEBUG +#if (PNG_DEBUG > 0) +#if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) +#include <crtdbg.h> +#if (PNG_DEBUG > 1) +#define png_debug(l,m) _RPT0(_CRT_WARN,m) +#define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m,p1) +#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m,p1,p2) +#endif +#else /* PNG_DEBUG_FILE || !_MSC_VER */ +#ifndef PNG_DEBUG_FILE +#define PNG_DEBUG_FILE stderr +#endif /* PNG_DEBUG_FILE */ +#if (PNG_DEBUG > 1) +#define png_debug(l,m) \ +{ \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ +} +#define png_debug1(l,m,p1) \ +{ \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ +} +#define png_debug2(l,m,p1,p2) \ +{ \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ +} +#endif /* (PNG_DEBUG > 1) */ +#endif /* _MSC_VER */ +#endif /* (PNG_DEBUG > 0) */ +#endif /* PNG_DEBUG */ +#ifndef png_debug +#define png_debug(l, m) +#endif +#ifndef png_debug1 +#define png_debug1(l, m, p1) +#endif +#ifndef png_debug2 +#define png_debug2(l, m, p1, p2) +#endif + +extern PNG_EXPORT(png_bytep,png_sig_bytes) PNGARG((void)); + +extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp + png_ptr, png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 + +/* Added to version 1.2.0 */ +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) +#define PNG_ASM_FLAG_MMX_SUPPORT_COMPILED 0x01 /* not user-settable */ +#define PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU 0x02 /* not user-settable */ +#define PNG_ASM_FLAG_MMX_READ_COMBINE_ROW 0x04 +#define PNG_ASM_FLAG_MMX_READ_INTERLACE 0x08 +#define PNG_ASM_FLAG_MMX_READ_FILTER_SUB 0x10 +#define PNG_ASM_FLAG_MMX_READ_FILTER_UP 0x20 +#define PNG_ASM_FLAG_MMX_READ_FILTER_AVG 0x40 +#define PNG_ASM_FLAG_MMX_READ_FILTER_PAETH 0x80 +#define PNG_ASM_FLAGS_INITIALIZED 0x80000000 /* not user-settable */ + +#define PNG_MMX_READ_FLAGS ( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW \ + | PNG_ASM_FLAG_MMX_READ_INTERLACE \ + | PNG_ASM_FLAG_MMX_READ_FILTER_SUB \ + | PNG_ASM_FLAG_MMX_READ_FILTER_UP \ + | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \ + | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ) +#define PNG_MMX_WRITE_FLAGS ( 0 ) + +#define PNG_MMX_FLAGS ( PNG_ASM_FLAG_MMX_SUPPORT_COMPILED \ + | PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU \ + | PNG_MMX_READ_FLAGS \ + | PNG_MMX_WRITE_FLAGS ) + +#define PNG_SELECT_READ 1 +#define PNG_SELECT_WRITE 2 + +#if !defined(PNG_1_0_X) +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_mmx_flagmask) + PNGARG((int flag_select, int *compilerID)); + +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_asm_flagmask) + PNGARG((int flag_select)); + +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_asm_flags) + PNGARG((png_structp png_ptr)); + +/* pngget.c */ +extern PNG_EXPORT(png_byte,png_get_mmx_bitdepth_threshold) + PNGARG((png_structp png_ptr)); + +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_mmx_rowbytes_threshold) + PNGARG((png_structp png_ptr)); + +/* pngset.c */ +extern PNG_EXPORT(void,png_set_asm_flags) + PNGARG((png_structp png_ptr, png_uint_32 asm_flags)); + +/* pngset.c */ +extern PNG_EXPORT(void,png_set_mmx_thresholds) + PNGARG((png_structp png_ptr, png_byte mmx_bitdepth_threshold, + png_uint_32 mmx_rowbytes_threshold)); + +#endif /* PNG_1_0_X */ +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + +#if !defined(PNG_1_0_X) +/* png.c, pnggccrd.c, or pngvcrd.c */ +extern PNG_EXPORT(int,png_mmx_support) PNGARG((void)); + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp + png_ptr, png_uint_32 strip_mode)); +#endif + +#endif /* PNG_1_0_X */ + +/* Added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +extern PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp + png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); +extern PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_structp + png_ptr)); +extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp + png_ptr)); +#endif + +/* Maintainer: Put new public prototypes here ^, in libpng.3, and project defs */ + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 - \ + (png_uint_16)(alpha)) + (png_uint_16)128); \ + (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } + +# define png_composite_16(composite, fg, alpha, bg) \ + { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(png_uint_32)(65535L - \ + (png_uint_32)(alpha)) + (png_uint_32)32768L); \ + (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } + +#else /* standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + (png_uint_16)127) / 255) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ + (png_uint_32)32767) / (png_uint_32)65535L) + +#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ + +/* These next functions are used internally in the code. They generally + * shouldn't be used unless you are writing code to add or replace some + * functionality in libpng. More information about most functions can + * be found in the files where the functions are located. + */ + +#if defined(PNG_INTERNAL) + +/* Various modes of operation. Note that after an init, mode is set to + * zero automatically when the structure is created. + */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_HAVE_IDAT 0x04 +#define PNG_AFTER_IDAT 0x08 +#define PNG_HAVE_IEND 0x10 +#define PNG_HAVE_gAMA 0x20 +#define PNG_HAVE_cHRM 0x40 +#define PNG_HAVE_sRGB 0x80 +#define PNG_HAVE_CHUNK_HEADER 0x100 +#define PNG_WROTE_tIME 0x200 +#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 +#define PNG_BACKGROUND_IS_GRAY 0x800 +#define PNG_HAVE_PNG_SIGNATURE 0x1000 + +/* flags for the transformations the PNG library does on the image data */ +#define PNG_BGR 0x0001 +#define PNG_INTERLACE 0x0002 +#define PNG_PACK 0x0004 +#define PNG_SHIFT 0x0008 +#define PNG_SWAP_BYTES 0x0010 +#define PNG_INVERT_MONO 0x0020 +#define PNG_DITHER 0x0040 +#define PNG_BACKGROUND 0x0080 +#define PNG_BACKGROUND_EXPAND 0x0100 + /* 0x0200 unused */ +#define PNG_16_TO_8 0x0400 +#define PNG_RGBA 0x0800 +#define PNG_EXPAND 0x1000 +#define PNG_GAMMA 0x2000 +#define PNG_GRAY_TO_RGB 0x4000 +#define PNG_FILLER 0x8000L +#define PNG_PACKSWAP 0x10000L +#define PNG_SWAP_ALPHA 0x20000L +#define PNG_STRIP_ALPHA 0x40000L +#define PNG_INVERT_ALPHA 0x80000L +#define PNG_USER_TRANSFORM 0x100000L +#define PNG_RGB_TO_GRAY_ERR 0x200000L +#define PNG_RGB_TO_GRAY_WARN 0x400000L +#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ +#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ + +/* flags for png_create_struct */ +#define PNG_STRUCT_PNG 0x0001 +#define PNG_STRUCT_INFO 0x0002 + +/* Scaling factor for filter heuristic weighting calculations */ +#define PNG_WEIGHT_SHIFT 8 +#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) +#define PNG_COST_SHIFT 3 +#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) + +/* flags for the png_ptr->flags rather than declaring a byte for each one */ +#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 +#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002 +#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004 +#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008 +#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010 +#define PNG_FLAG_ZLIB_FINISHED 0x0020 +#define PNG_FLAG_ROW_INIT 0x0040 +#define PNG_FLAG_FILLER_AFTER 0x0080 +#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 +#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 +#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 +#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 +#define PNG_FLAG_FREE_PLTE 0x1000 +#define PNG_FLAG_FREE_TRNS 0x2000 +#define PNG_FLAG_FREE_HIST 0x4000 +#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L +#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L +#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L +#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L +#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L +#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L + +#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ + PNG_FLAG_CRC_ANCILLARY_NOWARN) + +#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ + PNG_FLAG_CRC_CRITICAL_IGNORE) + +#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ + PNG_FLAG_CRC_CRITICAL_MASK) + +/* save typing and make code easier to understand */ + +#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ + abs((int)((c1).green) - (int)((c2).green)) + \ + abs((int)((c1).blue) - (int)((c2).blue))) + +/* Added to libpng-1.2.6 JB */ +#define PNG_ROWBYTES(pixel_bits, width) \ + ((pixel_bits) >= 8 ? \ + ((width) * (((png_uint_32)(pixel_bits)) >> 3)) : \ + (( ((width) * ((png_uint_32)(pixel_bits))) + 7) >> 3) ) + +/* PNG_OUT_OF_RANGE returns true if value is outside the range + ideal-delta..ideal+delta. Each argument is evaluated twice. + "ideal" and "delta" should be constants, normally simple + integers, "value" a variable. Added to libpng-1.2.6 JB */ +#define PNG_OUT_OF_RANGE(value, ideal, delta) \ + ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) + +/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */ +#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN) +/* place to hold the signature string for a PNG file. */ +#ifdef PNG_USE_GLOBAL_ARRAYS + PNG_EXPORT_VAR (const png_byte FARDATA) png_sig[8]; +#else +#define png_sig png_sig_bytes(NULL) +#endif +#endif /* PNG_NO_EXTERN */ + +/* Constant strings for known chunk types. If you need to add a chunk, + * define the name here, and add an invocation of the macro in png.c and + * wherever it's needed. + */ +#define PNG_IHDR const png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'} +#define PNG_IDAT const png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'} +#define PNG_IEND const png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'} +#define PNG_PLTE const png_byte png_PLTE[5] = { 80, 76, 84, 69, '\0'} +#define PNG_bKGD const png_byte png_bKGD[5] = { 98, 75, 71, 68, '\0'} +#define PNG_cHRM const png_byte png_cHRM[5] = { 99, 72, 82, 77, '\0'} +#define PNG_gAMA const png_byte png_gAMA[5] = {103, 65, 77, 65, '\0'} +#define PNG_hIST const png_byte png_hIST[5] = {104, 73, 83, 84, '\0'} +#define PNG_iCCP const png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'} +#define PNG_iTXt const png_byte png_iTXt[5] = {105, 84, 88, 116, '\0'} +#define PNG_oFFs const png_byte png_oFFs[5] = {111, 70, 70, 115, '\0'} +#define PNG_pCAL const png_byte png_pCAL[5] = {112, 67, 65, 76, '\0'} +#define PNG_sCAL const png_byte png_sCAL[5] = {115, 67, 65, 76, '\0'} +#define PNG_pHYs const png_byte png_pHYs[5] = {112, 72, 89, 115, '\0'} +#define PNG_sBIT const png_byte png_sBIT[5] = {115, 66, 73, 84, '\0'} +#define PNG_sPLT const png_byte png_sPLT[5] = {115, 80, 76, 84, '\0'} +#define PNG_sRGB const png_byte png_sRGB[5] = {115, 82, 71, 66, '\0'} +#define PNG_tEXt const png_byte png_tEXt[5] = {116, 69, 88, 116, '\0'} +#define PNG_tIME const png_byte png_tIME[5] = {116, 73, 77, 69, '\0'} +#define PNG_tRNS const png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'} +#define PNG_zTXt const png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} + +#ifdef PNG_USE_GLOBAL_ARRAYS +PNG_EXPORT_VAR (const png_byte FARDATA) png_IHDR[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_IDAT[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_IEND[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_PLTE[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_bKGD[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_cHRM[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_gAMA[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_hIST[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_iCCP[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_iTXt[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_oFFs[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_pCAL[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_sCAL[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_pHYs[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_sBIT[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_sPLT[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_sRGB[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_tEXt[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_tIME[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_tRNS[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_zTXt[5]; +#endif /* PNG_USE_GLOBAL_ARRAYS */ + + +/* Inline macros to do direct reads of bytes from the input buffer. These + * require that you are using an architecture that uses PNG byte ordering + * (MSB first) and supports unaligned data storage. I think that PowerPC + * in big-endian mode and 680x0 are the only ones that will support this. + * The x86 line of processors definitely do not. The png_get_int_32() + * routine also assumes we are using two's complement format for negative + * values, which is almost certainly true. + */ +#if defined(PNG_READ_BIG_ENDIAN_SUPPORTED) +# if defined(PNG_pCAL_SUPPORTED) || defined(PNG_oFFs_SUPPORTED) +# define png_get_int_32(buf) ( *((png_int_32p) (buf))) +# endif +# define png_get_uint_32(buf) ( *((png_uint_32p) (buf))) +# define png_get_uint_16(buf) ( *((png_uint_16p) (buf))) +#else +# if defined(PNG_pCAL_SUPPORTED) || defined(PNG_oFFs_SUPPORTED) +PNG_EXTERN png_int_32 png_get_int_32 PNGARG((png_bytep buf)); +# endif +PNG_EXTERN png_uint_32 png_get_uint_32 PNGARG((png_bytep buf)); +PNG_EXTERN png_uint_16 png_get_uint_16 PNGARG((png_bytep buf)); +#endif /* !PNG_READ_BIG_ENDIAN_SUPPORTED */ +PNG_EXTERN png_uint_32 png_get_uint_31 PNGARG((png_structp png_ptr, + png_bytep buf)); + +/* Initialize png_ptr struct for reading, and allocate any other memory. + * (old interface - DEPRECATED - use png_create_read_struct instead). + */ +extern PNG_EXPORT(void,png_read_init) PNGARG((png_structp png_ptr)); +#undef png_read_init +#define png_read_init(png_ptr) png_read_init_3(&png_ptr, \ + PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); +extern PNG_EXPORT(void,png_read_init_3) PNGARG((png_structpp ptr_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size)); +extern PNG_EXPORT(void,png_read_init_2) PNGARG((png_structp png_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t + png_info_size)); + +/* Initialize png_ptr struct for writing, and allocate any other memory. + * (old interface - DEPRECATED - use png_create_write_struct instead). + */ +extern PNG_EXPORT(void,png_write_init) PNGARG((png_structp png_ptr)); +#undef png_write_init +#define png_write_init(png_ptr) png_write_init_3(&png_ptr, \ + PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); +extern PNG_EXPORT(void,png_write_init_3) PNGARG((png_structpp ptr_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size)); +extern PNG_EXPORT(void,png_write_init_2) PNGARG((png_structp png_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t + png_info_size)); + +/* Allocate memory for an internal libpng struct */ +PNG_EXTERN png_voidp png_create_struct PNGARG((int type)); + +/* Free memory from internal libpng struct */ +PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); + +PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr + malloc_fn, png_voidp mem_ptr)); +PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, + png_free_ptr free_fn, png_voidp mem_ptr)); + +/* Free any memory that info_ptr points to and reset struct. */ +PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_1_0_X +/* Function to allocate memory for zlib. */ +PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, uInt size)); + +/* Function to free memory for zlib */ +PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); + +#ifdef PNG_SIZE_T +/* Function to convert a sizeof an item to png_sizeof item */ + PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); +#endif + +/* Next four functions are used internally as callbacks. PNGAPI is required + * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3. */ + +PNG_EXTERN void PNGAPI png_default_read_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void PNGAPI png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)); +#endif + +PNG_EXTERN void PNGAPI png_default_write_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +#if !defined(PNG_NO_STDIO) +PNG_EXTERN void PNGAPI png_default_flush PNGARG((png_structp png_ptr)); +#endif +#endif +#else /* PNG_1_0_X */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)); +#endif +#endif /* PNG_1_0_X */ + +/* Reset the CRC variable */ +PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); + +/* Write the "data" buffer to whatever output you are using. */ +PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +/* Read data from whatever input you are using into the "data" buffer */ +PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +/* Read bytes into buf, and update png_ptr->crc */ +PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, + png_size_t length)); + +/* Decompress data in a chunk that uses compression */ +#if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \ + defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) +PNG_EXTERN png_charp png_decompress_chunk PNGARG((png_structp png_ptr, + int comp_type, png_charp chunkdata, png_size_t chunklength, + png_size_t prefix_length, png_size_t *data_length)); +#endif + +/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ +PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)); + +/* Read the CRC from the file and compare it to the libpng calculated CRC */ +PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)); + +/* Calculate the CRC over a section of data. Note that we are only + * passing a maximum of 64K on systems that have this as a memory limit, + * since this is the maximum buffer size we can specify. + */ +PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr, + png_size_t length)); + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); +#endif + + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). + * The only currently known PNG chunks that use signed numbers are + * the ancillary extension chunks, oFFs and pCAL. + */ +PNG_EXTERN void png_save_uint_32 PNGARG((png_bytep buf, png_uint_32 i)); + +#if defined(PNG_WRITE_pCAL_SUPPORTED) || defined(PNG_WRITE_oFFs_SUPPORTED) +PNG_EXTERN void png_save_int_32 PNGARG((png_bytep buf, png_int_32 i)); +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +PNG_EXTERN void png_save_uint_16 PNGARG((png_bytep buf, unsigned int i)); + +/* simple function to write the signature */ +PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr)); + +/* write various chunks */ + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. + */ +PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width, + png_uint_32 height, + int bit_depth, int color_type, int compression_method, int filter_method, + int interlace_method)); + +PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette, + png_uint_32 num_pal)); + +PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); + +#if defined(PNG_WRITE_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, png_fixed_point + file_gamma)); +#endif +#endif + +#if defined(PNG_WRITE_sBIT_SUPPORTED) +PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit, + int color_type)); +#endif + +#if defined(PNG_WRITE_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr, + double white_x, double white_y, + double red_x, double red_y, double green_x, double green_y, + double blue_x, double blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif +#endif + +#if defined(PNG_WRITE_sRGB_SUPPORTED) +PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, + int intent)); +#endif + +#if defined(PNG_WRITE_iCCP_SUPPORTED) +PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, + png_charp name, int compression_type, + png_charp profile, int proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#if defined(PNG_WRITE_sPLT_SUPPORTED) +PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr, + png_sPLT_tp palette)); +#endif + +#if defined(PNG_WRITE_tRNS_SUPPORTED) +PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans, + png_color_16p values, int number, int color_type)); +#endif + +#if defined(PNG_WRITE_bKGD_SUPPORTED) +PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, + png_color_16p values, int color_type)); +#endif + +#if defined(PNG_WRITE_hIST_SUPPORTED) +PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist, + int num_hist)); +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr, + png_charp key, png_charpp new_key)); +#endif + +#if defined(PNG_WRITE_tEXt_SUPPORTED) +PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len)); +#endif + +#if defined(PNG_WRITE_zTXt_SUPPORTED) +PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len, int compression)); +#endif + +#if defined(PNG_WRITE_iTXt_SUPPORTED) +PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, + int compression, png_charp key, png_charp lang, png_charp lang_key, + png_charp text)); +#endif + +#if defined(PNG_TEXT_SUPPORTED) /* Added at version 1.0.14 and 1.2.4 */ +PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)); +#endif + +#if defined(PNG_WRITE_oFFs_SUPPORTED) +PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr, + png_int_32 x_offset, png_int_32 y_offset, int unit_type)); +#endif + +#if defined(PNG_WRITE_pCAL_SUPPORTED) +PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose, + png_int_32 X0, png_int_32 X1, int type, int nparams, + png_charp units, png_charpp params)); +#endif + +#if defined(PNG_WRITE_pHYs_SUPPORTED) +PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr, + png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, + int unit_type)); +#endif + +#if defined(PNG_WRITE_tIME_SUPPORTED) +PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, + png_timep mod_time)); +#endif + +#if defined(PNG_WRITE_sCAL_SUPPORTED) +#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) +PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr, + int unit, double width, double height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, + int unit, png_charp width, png_charp height)); +#endif +#endif +#endif + +/* Called when finished processing a row of data */ +PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); + +/* Internal use only. Called before first row of data */ +PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); + +#if defined(PNG_READ_GAMMA_SUPPORTED) +PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr)); +#endif + +/* combine a row of data, dealing with alpha, etc. if requested */ +PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, + int mask)); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) +/* expand an interlaced row */ +/* OLD pre-1.0.9 interface: +PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass, png_uint_32 transformations)); + */ +PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)); +#endif + +/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ + +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* grab pixels out of a row for an interlaced pass */ +PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass)); +#endif + +/* unfilter a row */ +PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, + png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter)); + +/* Choose the best filter to use and filter the row data */ +PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, + png_row_infop row_info)); + +/* Write out the filtered row. */ +PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr, + png_bytep filtered_row)); +/* finish a row while reading, dealing with interlacing passes, etc. */ +PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); + +/* initialize the row buffers, etc. */ +PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)); +/* optional call to update the users info structure */ +PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* these are the functions that do the transformations */ +#if defined(PNG_READ_FILLER_SUPPORTED) +PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 filler, png_uint_32 flags)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 flags)); +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) +PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop + row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) +PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) +PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p sig_bits)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +PNG_EXTERN void png_do_dither PNGARG((png_row_infop row_info, + png_bytep row, png_bytep palette_lookup, png_bytep dither_lookup)); + +# if defined(PNG_CORRECT_PALETTE_SUPPORTED) +PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette)); +# endif +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_WRITE_PACK_SUPPORTED) +PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 bit_depth)); +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) +PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p bit_depth)); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) +#if defined(PNG_READ_GAMMA_SUPPORTED) +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background, + png_color_16p background_1, + png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, + png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, + png_uint_16pp gamma_16_to_1, int gamma_shift)); +#else +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background)); +#endif +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) +PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row, + png_bytep gamma_table, png_uint_16pp gamma_16_table, + int gamma_shift)); +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) +PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, + png_bytep row, png_colorp palette, png_bytep trans, int num_trans)); +PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, + png_bytep row, png_color_16p trans_value)); +#endif + +/* The following decodes the appropriate chunks, and does error correction, + * then calls the appropriate callback for the chunk if it is valid. + */ + +/* decode the IHDR chunk */ +PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); + +#if defined(PNG_READ_bKGD_SUPPORTED) +PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_cHRM_SUPPORTED) +PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_gAMA_SUPPORTED) +PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_hIST_SUPPORTED) +PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_iCCP_SUPPORTED) +extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#if defined(PNG_READ_iTXt_SUPPORTED) +PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_oFFs_SUPPORTED) +PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_pCAL_SUPPORTED) +PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_pHYs_SUPPORTED) +PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_sBIT_SUPPORTED) +PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_sCAL_SUPPORTED) +PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_sPLT_SUPPORTED) +extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#if defined(PNG_READ_sRGB_SUPPORTED) +PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_tEXt_SUPPORTED) +PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_tIME_SUPPORTED) +PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_tRNS_SUPPORTED) +PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_zTXt_SUPPORTED) +PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); + +PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, + png_bytep chunk_name)); + +/* handle the transformations for reading and writing */ +PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); + +PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, + png_uint_32 length)); +PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row)); +PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); +#if defined(PNG_READ_tEXt_SUPPORTED) +PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) +PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) +PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) +/* png.c */ /* PRIVATE */ +PNG_EXTERN void png_init_mmx_flags PNGARG((png_structp png_ptr)); +#endif +/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + +#endif /* PNG_INTERNAL */ + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* do not put anything past this line */ +#endif /* PNG_H */ diff --git a/Utilities/FLTK/png/pngconf.h b/Utilities/FLTK/png/pngconf.h new file mode 100644 index 0000000000..1267e9c8db --- /dev/null +++ b/Utilities/FLTK/png/pngconf.h @@ -0,0 +1,1376 @@ + +/* pngconf.h - machine configurable file for libpng + * + * libpng version 1.2.7 - September 12, 2004 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +/* Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#ifdef PNG_USER_CONFIG +#include "pngusr.h" +#endif + +/* This is the size of the compression buffer, and thus the size of + * an IDAT chunk. Make this whatever size you feel is best for your + * machine. One of these will be allocated per png_struct. When this + * is full, it writes the data to the disk, and does some other + * calculations. Making this an extremely small size will slow + * the library down, but you may want to experiment to determine + * where it becomes significant, if you are concerned with memory + * usage. Note that zlib allocates at least 32Kb also. For readers, + * this describes the size of the buffer available to read the data in. + * Unless this gets smaller than the size of a row (compressed), + * it should not make much difference how big this is. + */ + +#ifndef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 8192 +#endif + +/* Enable if you want a write-only libpng */ + +#ifndef PNG_NO_READ_SUPPORTED +# define PNG_READ_SUPPORTED +#endif + +/* Enable if you want a read-only libpng */ + +#ifndef PNG_NO_WRITE_SUPPORTED +# define PNG_WRITE_SUPPORTED +#endif + +/* Enabled by default in 1.2.0. You can disable this if you don't need to + support PNGs that are embedded in MNG datastreams */ +#if !defined(PNG_1_0_X) && !defined(PNG_NO_MNG_FEATURES) +# ifndef PNG_MNG_FEATURES_SUPPORTED +# define PNG_MNG_FEATURES_SUPPORTED +# endif +#endif + +#ifndef PNG_NO_FLOATING_POINT_SUPPORTED +# ifndef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FLOATING_POINT_SUPPORTED +# endif +#endif + +/* If you are running on a machine where you cannot allocate more + * than 64K of memory at once, uncomment this. While libpng will not + * normally need that much memory in a chunk (unless you load up a very + * large file), zlib needs to know how big of a chunk it can use, and + * libpng thus makes sure to check any memory allocation to verify it + * will fit into memory. +#define PNG_MAX_MALLOC_64K + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) +# define PNG_MAX_MALLOC_64K +#endif + +/* Special munging to support doing things the 'cygwin' way: + * 'Normal' png-on-win32 defines/defaults: + * PNG_BUILD_DLL -- building dll + * PNG_USE_DLL -- building an application, linking to dll + * (no define) -- building static library, or building an + * application and linking to the static lib + * 'Cygwin' defines/defaults: + * PNG_BUILD_DLL -- (ignored) building the dll + * (no define) -- (ignored) building an application, linking to the dll + * PNG_STATIC -- (ignored) building the static lib, or building an + * application that links to the static lib. + * ALL_STATIC -- (ignored) building various static libs, or building an + * application that links to the static libs. + * Thus, + * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and + * this bit of #ifdefs will define the 'correct' config variables based on + * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but + * unnecessary. + * + * Also, the precedence order is: + * ALL_STATIC (since we can't #undef something outside our namespace) + * PNG_BUILD_DLL + * PNG_STATIC + * (nothing) == PNG_USE_DLL + * + * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent + * of auto-import in binutils, we no longer need to worry about + * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, + * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes + * to __declspec() stuff. However, we DO need to worry about + * PNG_BUILD_DLL and PNG_STATIC because those change some defaults + * such as CONSOLE_IO and whether GLOBAL_ARRAYS are allowed. + */ +#if defined(__CYGWIN__) +# if defined(ALL_STATIC) +# if defined(PNG_BUILD_DLL) +# undef PNG_BUILD_DLL +# endif +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if defined(PNG_DLL) +# undef PNG_DLL +# endif +# if !defined(PNG_STATIC) +# define PNG_STATIC +# endif +# else +# if defined (PNG_BUILD_DLL) +# if defined(PNG_STATIC) +# undef PNG_STATIC +# endif +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if !defined(PNG_DLL) +# define PNG_DLL +# endif +# else +# if defined(PNG_STATIC) +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if defined(PNG_DLL) +# undef PNG_DLL +# endif +# else +# if !defined(PNG_USE_DLL) +# define PNG_USE_DLL +# endif +# if !defined(PNG_DLL) +# define PNG_DLL +# endif +# endif +# endif +# endif +#endif + +/* This protects us against compilers that run on a windowing system + * and thus don't have or would rather us not use the stdio types: + * stdin, stdout, and stderr. The only one currently used is stderr + * in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will + * prevent these from being compiled and used. #defining PNG_NO_STDIO + * will also prevent these, plus will prevent the entire set of stdio + * macros and functions (FILE *, printf, etc.) from being compiled and used, + * unless (PNG_DEBUG > 0) has been #defined. + * + * #define PNG_NO_CONSOLE_IO + * #define PNG_NO_STDIO + */ + +#if defined(_WIN32_WCE) +# include <windows.h> + /* Console I/O functions are not supported on WindowsCE */ +# define PNG_NO_CONSOLE_IO +# ifdef PNG_DEBUG +# undef PNG_DEBUG +# endif +#endif + +#ifdef PNG_BUILD_DLL +# ifndef PNG_CONSOLE_IO_SUPPORTED +# ifndef PNG_NO_CONSOLE_IO +# define PNG_NO_CONSOLE_IO +# endif +# endif +#endif + +# ifdef PNG_NO_STDIO +# ifndef PNG_NO_CONSOLE_IO +# define PNG_NO_CONSOLE_IO +# endif +# ifdef PNG_DEBUG +# if (PNG_DEBUG > 0) +# include <stdio.h> +# endif +# endif +# else +# if !defined(_WIN32_WCE) +/* "stdio.h" functions are not supported on WindowsCE */ +# include <stdio.h> +# endif +# endif + +/* This macro protects us against machines that don't have function + * prototypes (ie K&R style headers). If your compiler does not handle + * function prototypes, define this macro and use the included ansi2knr. + * I've always been able to use _NO_PROTO as the indicator, but you may + * need to drag the empty declaration out in front of here, or change the + * ifdef to suit your own needs. + */ +#ifndef PNGARG + +#ifdef OF /* zlib prototype munger */ +# define PNGARG(arglist) OF(arglist) +#else + +#ifdef _NO_PROTO +# define PNGARG(arglist) () +# ifndef PNG_TYPECAST_NULL +# define PNG_TYPECAST_NULL +# endif +#else +# define PNGARG(arglist) arglist +#endif /* _NO_PROTO */ + +#endif /* OF */ + +#endif /* PNGARG */ + +/* Try to determine if we are compiling on a Mac. Note that testing for + * just __MWERKS__ is not good enough, because the Codewarrior is now used + * on non-Mac platforms. + */ +#ifndef MACOS +# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ + defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) +# define MACOS +# endif +#endif + +/* enough people need this for various reasons to include it here */ +#if !defined(MACOS) && !defined(RISCOS) && !defined(_WIN32_WCE) +# include <sys/types.h> +#endif + +#if !defined(PNG_SETJMP_NOT_SUPPORTED) && !defined(PNG_NO_SETJMP_SUPPORTED) +# define PNG_SETJMP_SUPPORTED +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This is an attempt to force a single setjmp behaviour on Linux. If + * the X config stuff didn't define _BSD_SOURCE we wouldn't need this. + */ + +# ifdef __linux__ +# ifdef _BSD_SOURCE +# define PNG_SAVE_BSD_SOURCE +# undef _BSD_SOURCE +# endif +# ifdef _SETJMP_H + /* If you encounter a compiler error here, see the explanation + * near the end of INSTALL. + */ + __png.h__ already includes setjmp.h; + __dont__ include it again.; +# endif +# endif /* __linux__ */ + + /* include setjmp.h for error handling */ +# include <setjmp.h> + +# ifdef __linux__ +# ifdef PNG_SAVE_BSD_SOURCE +# define _BSD_SOURCE +# undef PNG_SAVE_BSD_SOURCE +# endif +# endif /* __linux__ */ +#endif /* PNG_SETJMP_SUPPORTED */ + +#ifdef BSD +# include <strings.h> +#else +# include <string.h> +#endif + +/* Other defines for things like memory and the like can go here. */ +#ifdef PNG_INTERNAL + +#include <stdlib.h> + +/* The functions exported by PNG_EXTERN are PNG_INTERNAL functions, which + * aren't usually used outside the library (as far as I know), so it is + * debatable if they should be exported at all. In the future, when it is + * possible to have run-time registry of chunk-handling functions, some of + * these will be made available again. +#define PNG_EXTERN extern + */ +#define PNG_EXTERN + +/* Other defines specific to compilers can go here. Try to keep + * them inside an appropriate ifdef/endif pair for portability. + */ + +#if defined(PNG_FLOATING_POINT_SUPPORTED) +# if defined(MACOS) + /* We need to check that <math.h> hasn't already been included earlier + * as it seems it doesn't agree with <fp.h>, yet we should really use + * <fp.h> if possible. + */ +# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) +# include <fp.h> +# endif +# else +# include <math.h> +# endif +# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) + /* Amiga SAS/C: We must include builtin FPU functions when compiling using + * MATH=68881 + */ +# include <m68881.h> +# endif +#endif + +/* Codewarrior on NT has linking problems without this. */ +#if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__) +# define PNG_ALWAYS_EXTERN +#endif + +/* This provides the non-ANSI (far) memory allocation routines. */ +#if defined(__TURBOC__) && defined(__MSDOS__) +# include <mem.h> +# include <alloc.h> +#endif + +/* I have no idea why is this necessary... */ +#if defined(_MSC_VER) && (defined(WIN32) || defined(_Windows) || \ + defined(_WINDOWS) || defined(_WIN32) || defined(__WIN32__)) +# include <malloc.h> +#endif + +/* This controls how fine the dithering gets. As this allocates + * a largish chunk of memory (32K), those who are not as concerned + * with dithering quality can decrease some or all of these. + */ +#ifndef PNG_DITHER_RED_BITS +# define PNG_DITHER_RED_BITS 5 +#endif +#ifndef PNG_DITHER_GREEN_BITS +# define PNG_DITHER_GREEN_BITS 5 +#endif +#ifndef PNG_DITHER_BLUE_BITS +# define PNG_DITHER_BLUE_BITS 5 +#endif + +/* This controls how fine the gamma correction becomes when you + * are only interested in 8 bits anyway. Increasing this value + * results in more memory being used, and more pow() functions + * being called to fill in the gamma tables. Don't set this value + * less then 8, and even that may not work (I haven't tested it). + */ + +#ifndef PNG_MAX_GAMMA_8 +# define PNG_MAX_GAMMA_8 11 +#endif + +/* This controls how much a difference in gamma we can tolerate before + * we actually start doing gamma conversion. + */ +#ifndef PNG_GAMMA_THRESHOLD +# define PNG_GAMMA_THRESHOLD 0.05 +#endif + +#endif /* PNG_INTERNAL */ + +/* The following uses const char * instead of char * for error + * and warning message functions, so some compilers won't complain. + * If you do not want to use const, define PNG_NO_CONST here. + */ + +#ifndef PNG_NO_CONST +# define PNG_CONST const +#else +# define PNG_CONST +#endif + +/* The following defines give you the ability to remove code from the + * library that you will not be using. I wish I could figure out how to + * automate this, but I can't do that without making it seriously hard + * on the users. So if you are not using an ability, change the #define + * to and #undef, and that part of the library will not be compiled. If + * your linker can't find a function, you may want to make sure the + * ability is defined here. Some of these depend upon some others being + * defined. I haven't figured out all the interactions here, so you may + * have to experiment awhile to get everything to compile. If you are + * creating or using a shared library, you probably shouldn't touch this, + * as it will affect the size of the structures, and this will cause bad + * things to happen if the library and/or application ever change. + */ + +/* Any features you will not be using can be undef'ed here */ + +/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user + * to turn it off with "*TRANSFORMS_NOT_SUPPORTED" or *PNG_NO_*_TRANSFORMS + * on the compile line, then pick and choose which ones to define without + * having to edit this file. It is safe to use the *TRANSFORMS_NOT_SUPPORTED + * if you only want to have a png-compliant reader/writer but don't need + * any of the extra transformations. This saves about 80 kbytes in a + * typical installation of the library. (PNG_NO_* form added in version + * 1.0.1c, for consistency) + */ + +/* The size of the png_text structure changed in libpng-1.0.6 when + * iTXt is supported. It is turned off by default, to support old apps + * that malloc the png_text structure instead of calling png_set_text() + * and letting libpng malloc it. It will be turned on by default in + * libpng-1.3.0. + */ + +#ifndef PNG_iTXt_SUPPORTED +# if !defined(PNG_READ_iTXt_SUPPORTED) && !defined(PNG_NO_READ_iTXt) +# define PNG_NO_READ_iTXt +# endif +# if !defined(PNG_WRITE_iTXt_SUPPORTED) && !defined(PNG_NO_WRITE_iTXt) +# define PNG_NO_WRITE_iTXt +# endif +#endif + +/* The following support, added after version 1.0.0, can be turned off here en + * masse by defining PNG_LEGACY_SUPPORTED in case you need binary compatibility + * with old applications that require the length of png_struct and png_info + * to remain unchanged. + */ + +#ifdef PNG_LEGACY_SUPPORTED +# define PNG_NO_FREE_ME +# define PNG_NO_READ_UNKNOWN_CHUNKS +# define PNG_NO_WRITE_UNKNOWN_CHUNKS +# define PNG_NO_READ_USER_CHUNKS +# define PNG_NO_READ_iCCP +# define PNG_NO_WRITE_iCCP +# define PNG_NO_READ_iTXt +# define PNG_NO_WRITE_iTXt +# define PNG_NO_READ_sCAL +# define PNG_NO_WRITE_sCAL +# define PNG_NO_READ_sPLT +# define PNG_NO_WRITE_sPLT +# define PNG_NO_INFO_IMAGE +# define PNG_NO_READ_RGB_TO_GRAY +# define PNG_NO_READ_USER_TRANSFORM +# define PNG_NO_WRITE_USER_TRANSFORM +# define PNG_NO_USER_MEM +# define PNG_NO_READ_EMPTY_PLTE +# define PNG_NO_MNG_FEATURES +# define PNG_NO_FIXED_POINT_SUPPORTED +#endif + +/* Ignore attempt to turn off both floating and fixed point support */ +#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \ + !defined(PNG_NO_FIXED_POINT_SUPPORTED) +# define PNG_FIXED_POINT_SUPPORTED +#endif + +#ifndef PNG_NO_FREE_ME +# define PNG_FREE_ME_SUPPORTED +#endif + +#if defined(PNG_READ_SUPPORTED) + +#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_TRANSFORMS) +# define PNG_READ_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_READ_EXPAND +# define PNG_READ_EXPAND_SUPPORTED +# endif +# ifndef PNG_NO_READ_SHIFT +# define PNG_READ_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACK +# define PNG_READ_PACK_SUPPORTED +# endif +# ifndef PNG_NO_READ_BGR +# define PNG_READ_BGR_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP +# define PNG_READ_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACKSWAP +# define PNG_READ_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT +# define PNG_READ_INVERT_SUPPORTED +# endif +# ifndef PNG_NO_READ_DITHER +# define PNG_READ_DITHER_SUPPORTED +# endif +# ifndef PNG_NO_READ_BACKGROUND +# define PNG_READ_BACKGROUND_SUPPORTED +# endif +# ifndef PNG_NO_READ_16_TO_8 +# define PNG_READ_16_TO_8_SUPPORTED +# endif +# ifndef PNG_NO_READ_FILLER +# define PNG_READ_FILLER_SUPPORTED +# endif +# ifndef PNG_NO_READ_GAMMA +# define PNG_READ_GAMMA_SUPPORTED +# endif +# ifndef PNG_NO_READ_GRAY_TO_RGB +# define PNG_READ_GRAY_TO_RGB_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP_ALPHA +# define PNG_READ_SWAP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT_ALPHA +# define PNG_READ_INVERT_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_STRIP_ALPHA +# define PNG_READ_STRIP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_USER_TRANSFORM +# define PNG_READ_USER_TRANSFORM_SUPPORTED +# endif +# ifndef PNG_NO_READ_RGB_TO_GRAY +# define PNG_READ_RGB_TO_GRAY_SUPPORTED +# endif +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + +#if !defined(PNG_NO_PROGRESSIVE_READ) && \ + !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED) /* if you don't do progressive */ +# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ +#endif /* about interlacing capability! You'll */ + /* still have interlacing unless you change the following line: */ + +#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */ + +#ifndef PNG_NO_READ_COMPOSITE_NODIV +# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ +# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ +# endif +#endif + +/* Deprecated, will be removed from version 2.0.0. + Use PNG_MNG_FEATURES_SUPPORTED instead. */ +#ifndef PNG_NO_READ_EMPTY_PLTE +# define PNG_READ_EMPTY_PLTE_SUPPORTED +#endif + +#endif /* PNG_READ_SUPPORTED */ + +#if defined(PNG_WRITE_SUPPORTED) + +# if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_TRANSFORMS) +# define PNG_WRITE_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_WRITE_SHIFT +# define PNG_WRITE_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACK +# define PNG_WRITE_PACK_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_BGR +# define PNG_WRITE_BGR_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_SWAP +# define PNG_WRITE_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACKSWAP +# define PNG_WRITE_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_INVERT +# define PNG_WRITE_INVERT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_FILLER +# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ +# endif +# ifndef PNG_NO_WRITE_SWAP_ALPHA +# define PNG_WRITE_SWAP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_INVERT_ALPHA +# define PNG_WRITE_INVERT_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_USER_TRANSFORM +# define PNG_WRITE_USER_TRANSFORM_SUPPORTED +# endif +#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ + +#define PNG_WRITE_INTERLACING_SUPPORTED /* not required for PNG-compliant + encoders, but can cause trouble + if left undefined */ + +#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \ + defined(PNG_FLOATING_POINT_SUPPORTED) +# define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#endif + +#ifndef PNG_NO_WRITE_FLUSH +# define PNG_WRITE_FLUSH_SUPPORTED +#endif + +/* Deprecated, see PNG_MNG_FEATURES_SUPPORTED, above */ +#ifndef PNG_NO_WRITE_EMPTY_PLTE +# define PNG_WRITE_EMPTY_PLTE_SUPPORTED +#endif + +#endif /* PNG_WRITE_SUPPORTED */ + +#ifndef PNG_1_0_X +# ifndef PNG_NO_ERROR_NUMBERS +# define PNG_ERROR_NUMBERS_SUPPORTED +# endif +#endif /* PNG_1_0_X */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +# ifndef PNG_NO_USER_TRANSFORM_PTR +# define PNG_USER_TRANSFORM_PTR_SUPPORTED +# endif +#endif + +#ifndef PNG_NO_STDIO +# define PNG_TIME_RFC1123_SUPPORTED +#endif + +/* This adds extra functions in pngget.c for accessing data from the + * info pointer (added in version 0.99) + * png_get_image_width() + * png_get_image_height() + * png_get_bit_depth() + * png_get_color_type() + * png_get_compression_type() + * png_get_filter_type() + * png_get_interlace_type() + * png_get_pixel_aspect_ratio() + * png_get_pixels_per_meter() + * png_get_x_offset_pixels() + * png_get_y_offset_pixels() + * png_get_x_offset_microns() + * png_get_y_offset_microns() + */ +#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED) +# define PNG_EASY_ACCESS_SUPPORTED +#endif + +/* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0 + even when PNG_USE_PNGVCRD or PNG_USE_PNGGCCRD is not defined */ +#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_ASSEMBLER_CODE) +# ifndef PNG_ASSEMBLER_CODE_SUPPORTED +# define PNG_ASSEMBLER_CODE_SUPPORTED +# endif +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_MMX_CODE_SUPPORTED +# endif +#endif + +/* If you are sure that you don't need thread safety and you are compiling + with PNG_USE_PNGCCRD for an MMX application, you can define this for + faster execution. See pnggccrd.c. +#define PNG_THREAD_UNSAFE_OK +*/ + +#if !defined(PNG_1_0_X) +#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED) +# define PNG_USER_MEM_SUPPORTED +#endif +#endif /* PNG_1_0_X */ + +/* Added at libpng-1.2.6 */ +#if !defined(PNG_1_0_X) +#ifndef PNG_SET_USER_LIMITS_SUPPORTED +#if !defined(PNG_NO_SET_USER_LIMITS) && !defined(PNG_SET_USER_LIMITS_SUPPORTED) +# define PNG_SET_USER_LIMITS_SUPPORTED +#endif +#endif +#endif /* PNG_1_0_X */ + +/* Added at libpng-1.0.16 and 1.2.6. To accept all valid PNGS no matter + * how large, set these limits to 0x7fffffffL + */ +#ifndef PNG_USER_WIDTH_MAX +# define PNG_USER_WIDTH_MAX 1000000L +#endif +#ifndef PNG_USER_HEIGHT_MAX +# define PNG_USER_HEIGHT_MAX 1000000L +#endif + +/* These are currently experimental features, define them if you want */ + +/* very little testing */ +/* +#ifdef PNG_READ_SUPPORTED +# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# endif +#endif +*/ + +/* This is only for PowerPC big-endian and 680x0 systems */ +/* some testing */ +/* +#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED +# define PNG_READ_BIG_ENDIAN_SUPPORTED +#endif +*/ + +/* Buggy compilers (e.g., gcc 2.7.2.2) need this */ +/* +#define PNG_NO_POINTER_INDEXING +*/ + +/* These functions are turned off by default, as they will be phased out. */ +/* +#define PNG_USELESS_TESTS_SUPPORTED +#define PNG_CORRECT_PALETTE_SUPPORTED +*/ + +/* Any chunks you are not interested in, you can undef here. The + * ones that allocate memory may be expecially important (hIST, + * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info + * a bit smaller. + */ + +#if defined(PNG_READ_SUPPORTED) && \ + !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_ANCILLARY_CHUNKS) +# define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#endif + +#if defined(PNG_WRITE_SUPPORTED) && \ + !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS) +# define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#endif + +#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_READ_TEXT +# define PNG_NO_READ_iTXt +# define PNG_NO_READ_tEXt +# define PNG_NO_READ_zTXt +#endif +#ifndef PNG_NO_READ_bKGD +# define PNG_READ_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +#endif +#ifndef PNG_NO_READ_cHRM +# define PNG_READ_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +#endif +#ifndef PNG_NO_READ_gAMA +# define PNG_READ_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +#endif +#ifndef PNG_NO_READ_hIST +# define PNG_READ_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +#endif +#ifndef PNG_NO_READ_iCCP +# define PNG_READ_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +#endif +#ifndef PNG_NO_READ_iTXt +# ifndef PNG_READ_iTXt_SUPPORTED +# define PNG_READ_iTXt_SUPPORTED +# endif +# ifndef PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_READ_oFFs +# define PNG_READ_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +#endif +#ifndef PNG_NO_READ_pCAL +# define PNG_READ_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_sCAL +# define PNG_READ_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_pHYs +# define PNG_READ_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +#endif +#ifndef PNG_NO_READ_sBIT +# define PNG_READ_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sPLT +# define PNG_READ_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sRGB +# define PNG_READ_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +#endif +#ifndef PNG_NO_READ_tEXt +# define PNG_READ_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_tIME +# define PNG_READ_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +#endif +#ifndef PNG_NO_READ_tRNS +# define PNG_READ_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +#endif +#ifndef PNG_NO_READ_zTXt +# define PNG_READ_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_UNKNOWN_CHUNKS +# define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +# ifndef PNG_NO_HANDLE_AS_UNKNOWN +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +#endif +#if !defined(PNG_NO_READ_USER_CHUNKS) && \ + defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) +# define PNG_READ_USER_CHUNKS_SUPPORTED +# define PNG_USER_CHUNKS_SUPPORTED +# ifdef PNG_NO_READ_UNKNOWN_CHUNKS +# undef PNG_NO_READ_UNKNOWN_CHUNKS +# endif +# ifdef PNG_NO_HANDLE_AS_UNKNOWN +# undef PNG_NO_HANDLE_AS_UNKNOWN +# endif +#endif +#ifndef PNG_NO_READ_OPT_PLTE +# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ +#endif /* optional PLTE chunk in RGB and RGBA images */ +#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \ + defined(PNG_READ_zTXt_SUPPORTED) +# define PNG_READ_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +#endif + +#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */ + +#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_WRITE_TEXT +# define PNG_NO_WRITE_iTXt +# define PNG_NO_WRITE_tEXt +# define PNG_NO_WRITE_zTXt +#endif +#ifndef PNG_NO_WRITE_bKGD +# define PNG_WRITE_bKGD_SUPPORTED +# ifndef PNG_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_cHRM +# define PNG_WRITE_cHRM_SUPPORTED +# ifndef PNG_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_gAMA +# define PNG_WRITE_gAMA_SUPPORTED +# ifndef PNG_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_hIST +# define PNG_WRITE_hIST_SUPPORTED +# ifndef PNG_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iCCP +# define PNG_WRITE_iCCP_SUPPORTED +# ifndef PNG_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iTXt +# ifndef PNG_WRITE_iTXt_SUPPORTED +# define PNG_WRITE_iTXt_SUPPORTED +# endif +# ifndef PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_oFFs +# define PNG_WRITE_oFFs_SUPPORTED +# ifndef PNG_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pCAL +# define PNG_WRITE_pCAL_SUPPORTED +# ifndef PNG_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sCAL +# define PNG_WRITE_sCAL_SUPPORTED +# ifndef PNG_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pHYs +# define PNG_WRITE_pHYs_SUPPORTED +# ifndef PNG_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sBIT +# define PNG_WRITE_sBIT_SUPPORTED +# ifndef PNG_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sPLT +# define PNG_WRITE_sPLT_SUPPORTED +# ifndef PNG_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sRGB +# define PNG_WRITE_sRGB_SUPPORTED +# ifndef PNG_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tEXt +# define PNG_WRITE_tEXt_SUPPORTED +# ifndef PNG_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tIME +# define PNG_WRITE_tIME_SUPPORTED +# ifndef PNG_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tRNS +# define PNG_WRITE_tRNS_SUPPORTED +# ifndef PNG_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_zTXt +# define PNG_WRITE_zTXt_SUPPORTED +# ifndef PNG_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS +# define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +# ifndef PNG_NO_HANDLE_AS_UNKNOWN +# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +# endif +#endif +#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \ + defined(PNG_WRITE_zTXt_SUPPORTED) +# define PNG_WRITE_TEXT_SUPPORTED +# ifndef PNG_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +# endif +#endif + +#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */ + +/* Turn this off to disable png_read_png() and + * png_write_png() and leave the row_pointers member + * out of the info structure. + */ +#ifndef PNG_NO_INFO_IMAGE +# define PNG_INFO_IMAGE_SUPPORTED +#endif + +/* need the time information for reading tIME chunks */ +#if defined(PNG_tIME_SUPPORTED) +# if !defined(_WIN32_WCE) + /* "time.h" functions are not supported on WindowsCE */ +# include <time.h> +# endif +#endif + +/* Some typedefs to get us started. These should be safe on most of the + * common platforms. The typedefs should be at least as large as the + * numbers suggest (a png_uint_32 must be at least 32 bits long), but they + * don't have to be exactly that size. Some compilers dislike passing + * unsigned shorts as function parameters, so you may be better off using + * unsigned int for png_uint_16. Likewise, for 64-bit systems, you may + * want to have unsigned int for png_uint_32 instead of unsigned long. + */ + +typedef unsigned long png_uint_32; +typedef long png_int_32; +typedef unsigned short png_uint_16; +typedef short png_int_16; +typedef unsigned char png_byte; + +/* This is usually size_t. It is typedef'ed just in case you need it to + change (I'm not sure if you will or not, so I thought I'd be safe) */ +#ifdef PNG_SIZE_T + typedef PNG_SIZE_T png_size_t; +# define png_sizeof(x) png_convert_size(sizeof (x)) +#else + typedef size_t png_size_t; +# define png_sizeof(x) sizeof (x) +#endif + +/* The following is needed for medium model support. It cannot be in the + * PNG_INTERNAL section. Needs modification for other compilers besides + * MSC. Model independent support declares all arrays and pointers to be + * large using the far keyword. The zlib version used must also support + * model independent data. As of version zlib 1.0.4, the necessary changes + * have been made in zlib. The USE_FAR_KEYWORD define triggers other + * changes that are needed. (Tim Wegner) + */ + +/* Separate compiler dependencies (problem here is that zlib.h always + defines FAR. (SJT) */ +#ifdef __BORLANDC__ +# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) +# define LDATA 1 +# else +# define LDATA 0 +# endif + /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ +# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) +# define PNG_MAX_MALLOC_64K +# if (LDATA != 1) +# ifndef FAR +# define FAR __far +# endif +# define USE_FAR_KEYWORD +# endif /* LDATA != 1 */ + /* Possibly useful for moving data out of default segment. + * Uncomment it if you want. Could also define FARDATA as + * const if your compiler supports it. (SJT) +# define FARDATA FAR + */ +# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ +#endif /* __BORLANDC__ */ + + +/* Suggest testing for specific compiler first before testing for + * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, + * making reliance oncertain keywords suspect. (SJT) + */ + +/* MSC Medium model */ +#if defined(FAR) +# if defined(M_I86MM) +# define USE_FAR_KEYWORD +# define FARDATA FAR +# include <dos.h> +# endif +#endif + +/* SJT: default case */ +#ifndef FAR +# define FAR +#endif + +/* At this point FAR is always defined */ +#ifndef FARDATA +# define FARDATA +#endif + +/* Typedef for floating-point numbers that are converted + to fixed-point with a multiple of 100,000, e.g., int_gamma */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void FAR * png_voidp; +typedef png_byte FAR * png_bytep; +typedef png_uint_32 FAR * png_uint_32p; +typedef png_int_32 FAR * png_int_32p; +typedef png_uint_16 FAR * png_uint_16p; +typedef png_int_16 FAR * png_int_16p; +typedef PNG_CONST char FAR * png_const_charp; +typedef char FAR * png_charp; +typedef png_fixed_point FAR * png_fixed_point_p; + +#ifndef PNG_NO_STDIO +#if defined(_WIN32_WCE) +typedef HANDLE png_FILE_p; +#else +typedef FILE * png_FILE_p; +#endif +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * png_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte FAR * FAR * png_bytepp; +typedef png_uint_32 FAR * FAR * png_uint_32pp; +typedef png_int_32 FAR * FAR * png_int_32pp; +typedef png_uint_16 FAR * FAR * png_uint_16pp; +typedef png_int_16 FAR * FAR * png_int_16pp; +typedef PNG_CONST char FAR * FAR * png_const_charpp; +typedef char FAR * FAR * png_charpp; +typedef png_fixed_point FAR * FAR * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * FAR * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char FAR * FAR * FAR * png_charppp; + +/* libpng typedefs for types in zlib. If zlib changes + * or another compression library is used, then change these. + * Eliminates need to change all the source files. + */ +typedef charf * png_zcharp; +typedef charf * FAR * png_zcharpp; +typedef z_stream FAR * png_zstreamp; + +/* + * Define PNG_BUILD_DLL if the module being built is a Windows + * LIBPNG DLL. + * + * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL. + * It is equivalent to Microsoft predefined macro _DLL that is + * automatically defined when you compile using the share + * version of the CRT (C Run-Time library) + * + * The cygwin mods make this behavior a little different: + * Define PNG_BUILD_DLL if you are building a dll for use with cygwin + * Define PNG_STATIC if you are building a static library for use with cygwin, + * -or- if you are building an application that you want to link to the + * static library. + * PNG_USE_DLL is defined by default (no user action needed) unless one of + * the other flags is defined. + */ + +#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL)) +# define PNG_DLL +#endif +/* If CYGWIN, then disallow GLOBAL ARRAYS unless building a static lib. + * When building a static lib, default to no GLOBAL ARRAYS, but allow + * command-line override + */ +#if defined(__CYGWIN__) +# if !defined(PNG_STATIC) +# if defined(PNG_USE_GLOBAL_ARRAYS) +# undef PNG_USE_GLOBAL_ARRAYS +# endif +# if !defined(PNG_USE_LOCAL_ARRAYS) +# define PNG_USE_LOCAL_ARRAYS +# endif +# else +# if defined(PNG_USE_LOCAL_ARRAYS) || defined(PNG_NO_GLOBAL_ARRAYS) +# if defined(PNG_USE_GLOBAL_ARRAYS) +# undef PNG_USE_GLOBAL_ARRAYS +# endif +# endif +# endif +# if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) +# define PNG_USE_LOCAL_ARRAYS +# endif +#endif + +/* Do not use global arrays (helps with building DLL's) + * They are no longer used in libpng itself, since version 1.0.5c, + * but might be required for some pre-1.0.5c applications. + */ +#if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) +# if defined(PNG_NO_GLOBAL_ARRAYS) || (defined(__GNUC__) && defined(PNG_DLL)) +# define PNG_USE_LOCAL_ARRAYS +# else +# define PNG_USE_GLOBAL_ARRAYS +# endif +#endif + +#if defined(__CYGWIN__) +# undef PNGAPI +# define PNGAPI __cdecl +# undef PNG_IMPEXP +# define PNG_IMPEXP +#endif + +/* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", + * you may get warnings regarding the linkage of png_zalloc and png_zfree. + * Don't ignore those warnings; you must also reset the default calling + * convention in your compiler to match your PNGAPI, and you must build + * zlib and your applications the same way you build libpng. + */ + +#if defined(__MINGW32__) && !defined(PNG_MODULEDEF) +# ifndef PNG_NO_MODULEDEF +# define PNG_NO_MODULEDEF +# endif +#endif + +#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF) +# define PNG_IMPEXP +#endif + +#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \ + (( defined(_Windows) || defined(_WINDOWS) || \ + defined(WIN32) || defined(_WIN32) || defined(__WIN32__) )) + +# ifndef PNGAPI +# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) +# define PNGAPI __cdecl +# else +# define PNGAPI _cdecl +# endif +# endif + +# if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \ + 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */) +# define PNG_IMPEXP +# endif + +# if !defined(PNG_IMPEXP) + +# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol +# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol + + /* Borland/Microsoft */ +# if defined(_MSC_VER) || defined(__BORLANDC__) +# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500) +# define PNG_EXPORT PNG_EXPORT_TYPE1 +# else +# define PNG_EXPORT PNG_EXPORT_TYPE2 +# if defined(PNG_BUILD_DLL) +# define PNG_IMPEXP __export +# else +# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in + VC++ */ +# endif /* Exists in Borland C++ for + C++ classes (== huge) */ +# endif +# endif + +# if !defined(PNG_IMPEXP) +# if defined(PNG_BUILD_DLL) +# define PNG_IMPEXP __declspec(dllexport) +# else +# define PNG_IMPEXP __declspec(dllimport) +# endif +# endif +# endif /* PNG_IMPEXP */ +#else /* !(DLL || non-cygwin WINDOWS) */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# ifndef PNGAPI +# define PNGAPI _System +# endif +# else +# if 0 /* ... other platforms, with other meanings */ +# endif +# endif +#endif + +#ifndef PNGAPI +# define PNGAPI +#endif +#ifndef PNG_IMPEXP +# define PNG_IMPEXP +#endif + +#ifndef PNG_EXPORT +# define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol +#endif + +#ifdef PNG_USE_GLOBAL_ARRAYS +# ifndef PNG_EXPORT_VAR +# define PNG_EXPORT_VAR(type) extern PNG_IMPEXP type +# endif +#endif + +/* User may want to use these so they are not in PNG_INTERNAL. Any library + * functions that are passed far data must be model independent. + */ + +#ifndef PNG_ABORT +# define PNG_ABORT() abort() +#endif + +#ifdef PNG_SETJMP_SUPPORTED +# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_SETJMP_NOT_SUPPORTED) +#endif + +#if defined(USE_FAR_KEYWORD) /* memory model independent fns */ +/* use this to make far-to-near assignments */ +# define CHECK 1 +# define NOCHECK 0 +# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) +# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK)) +# define png_strcpy _fstrcpy +# define png_strncpy _fstrncpy /* Added to v 1.2.6 */ +# define png_strlen _fstrlen +# define png_memcmp _fmemcmp /* SJT: added */ +# define png_memcpy _fmemcpy +# define png_memset _fmemset +#else /* use the usual functions */ +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# define png_strcpy strcpy +# define png_strncpy strncpy /* Added to v 1.2.6 */ +# define png_strlen strlen +# define png_memcmp memcmp /* SJT: added */ +# define png_memcpy memcpy +# define png_memset memset +#endif +/* End of memory model independent support */ + +/* Just a little check that someone hasn't tried to define something + * contradictory. + */ +#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) +# undef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 65536L +#endif + +#ifdef PNG_READ_SUPPORTED +/* Prior to libpng-1.0.9, this block was in pngasmrd.h */ +#if defined(PNG_INTERNAL) + +/* These are the default thresholds before the MMX code kicks in; if either + * rowbytes or bitdepth is below the threshold, plain C code is used. These + * can be overridden at runtime via the png_set_mmx_thresholds() call in + * libpng 1.2.0 and later. The values below were chosen by Intel. + */ + +#ifndef PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT +# define PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT 128 /* >= */ +#endif +#ifndef PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT +# define PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT 9 /* >= */ +#endif + +/* Set this in the makefile for VC++ on Pentium, not here. */ +/* Platform must be Pentium. Makefile must assemble and load pngvcrd.c . + * MMX will be detected at run time and used if present. + */ +#ifdef PNG_USE_PNGVCRD +# define PNG_HAVE_ASSEMBLER_COMBINE_ROW +# define PNG_HAVE_ASSEMBLER_READ_INTERLACE +# define PNG_HAVE_ASSEMBLER_READ_FILTER_ROW +#endif + +/* Set this in the makefile for gcc/as on Pentium, not here. */ +/* Platform must be Pentium. Makefile must assemble and load pnggccrd.c . + * MMX will be detected at run time and used if present. + */ +#ifdef PNG_USE_PNGGCCRD +# define PNG_HAVE_ASSEMBLER_COMBINE_ROW +# define PNG_HAVE_ASSEMBLER_READ_INTERLACE +# define PNG_HAVE_ASSEMBLER_READ_FILTER_ROW +#endif +/* - see pnggccrd.c for info about what is currently enabled */ + +#endif /* PNG_INTERNAL */ +#endif /* PNG_READ_SUPPORTED */ + +#endif /* PNGCONF_H */ + diff --git a/Utilities/FLTK/png/pngerror.c b/Utilities/FLTK/png/pngerror.c new file mode 100644 index 0000000000..c251571926 --- /dev/null +++ b/Utilities/FLTK/png/pngerror.c @@ -0,0 +1,295 @@ + +/* pngerror.c - stub functions for i/o and memory allocation + * + * libpng version 1.2.7 - September 12, 2004 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file provides a location for all error handling. Users who + * need special error handling are expected to write replacement functions + * and use png_set_error_fn() to use those functions. See the instructions + * at each function. + */ + +#define PNG_INTERNAL +#include "png.h" + +static void /* PRIVATE */ +png_default_error PNGARG((png_structp png_ptr, + png_const_charp error_message)); +static void /* PRIVATE */ +png_default_warning PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +/* This function is called whenever there is a fatal error. This function + * should not be changed. If there is a need to handle errors differently, + * you should supply a replacement error function and use png_set_error_fn() + * to replace the error function at run-time. + */ +void PNGAPI +png_error(png_structp png_ptr, png_const_charp error_message) +{ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + char msg[16]; + if (png_ptr->flags&(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) + { + if (*error_message == '#') + { + int offset; + for (offset=1; offset<15; offset++) + if (*(error_message+offset) == ' ') + break; + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + int i; + for (i=0; i<offset-1; i++) + msg[i]=error_message[i+1]; + msg[i]='\0'; + error_message=msg; + } + else + error_message+=offset; + } + else + { + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + msg[0]='0'; + msg[1]='\0'; + error_message=msg; + } + } + } +#endif + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_ptr, error_message); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, error_message); +} + +/* This function is called whenever there is a non-fatal error. This function + * should not be changed. If there is a need to handle warnings differently, + * you should supply a replacement warning function and use + * png_set_error_fn() to replace the warning function at run-time. + */ +void PNGAPI +png_warning(png_structp png_ptr, png_const_charp warning_message) +{ + int offset = 0; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (png_ptr->flags&(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) +#endif + { + if (*warning_message == '#') + { + for (offset=1; offset<15; offset++) + if (*(warning_message+offset) == ' ') + break; + } + } + if (png_ptr != NULL && png_ptr->warning_fn != NULL) + (*(png_ptr->warning_fn))(png_ptr, warning_message+offset); + else + png_default_warning(png_ptr, warning_message+offset); +} + +/* These utilities are used internally to build an error message that relates + * to the current chunk. The chunk name comes from png_ptr->chunk_name, + * this is used to prefix the message. The message is limited in length + * to 63 bytes, the name characters are output as hex digits wrapped in [] + * if the character is invalid. + */ +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) +static PNG_CONST char png_digit[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' +}; + +static void /* PRIVATE */ +png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp + error_message) +{ + int iout = 0, iin = 0; + + while (iin < 4) + { + int c = png_ptr->chunk_name[iin++]; + if (isnonalpha(c)) + { + buffer[iout++] = '['; + buffer[iout++] = png_digit[(c & 0xf0) >> 4]; + buffer[iout++] = png_digit[c & 0x0f]; + buffer[iout++] = ']'; + } + else + { + buffer[iout++] = (png_byte)c; + } + } + + if (error_message == NULL) + buffer[iout] = 0; + else + { + buffer[iout++] = ':'; + buffer[iout++] = ' '; + png_strncpy(buffer+iout, error_message, 63); + buffer[iout+63] = 0; + } +} + +void PNGAPI +png_chunk_error(png_structp png_ptr, png_const_charp error_message) +{ + char msg[18+64]; + png_format_buffer(png_ptr, msg, error_message); + png_error(png_ptr, msg); +} + +void PNGAPI +png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) +{ + char msg[18+64]; + png_format_buffer(png_ptr, msg, warning_message); + png_warning(png_ptr, msg); +} + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static void /* PRIVATE */ +png_default_error(png_structp png_ptr, png_const_charp error_message) +{ +#ifndef PNG_NO_CONSOLE_IO +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*error_message == '#') + { + int offset; + char error_number[16]; + for (offset=0; offset<15; offset++) + { + error_number[offset] = *(error_message+offset+1); + if (*(error_message+offset) == ' ') + break; + } + if((offset > 1) && (offset < 15)) + { + error_number[offset-1]='\0'; + fprintf(stderr, "libpng error no. %s: %s\n", error_number, + error_message+offset); + } + else + fprintf(stderr, "libpng error: %s, offset=%d\n", error_message,offset); + } + else +#endif + fprintf(stderr, "libpng error: %s\n", error_message); +#endif + +#ifdef PNG_SETJMP_SUPPORTED +# ifdef USE_FAR_KEYWORD + { + jmp_buf jmpbuf; + png_memcpy(jmpbuf,png_ptr->jmpbuf,png_sizeof(jmp_buf)); + longjmp(jmpbuf, 1); + } +# else + longjmp(png_ptr->jmpbuf, 1); +# endif +#else + /* make compiler happy */ ; + if (png_ptr) + PNG_ABORT(); +#endif +#ifdef PNG_NO_CONSOLE_IO + /* make compiler happy */ ; + if (&error_message != NULL) + return; +#endif +} + +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want them to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void /* PRIVATE */ +png_default_warning(png_structp png_ptr, png_const_charp warning_message) +{ +#ifndef PNG_NO_CONSOLE_IO +# ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*warning_message == '#') + { + int offset; + char warning_number[16]; + for (offset=0; offset<15; offset++) + { + warning_number[offset]=*(warning_message+offset+1); + if (*(warning_message+offset) == ' ') + break; + } + if((offset > 1) && (offset < 15)) + { + warning_number[offset-1]='\0'; + fprintf(stderr, "libpng warning no. %s: %s\n", warning_number, + warning_message+offset); + } + else + fprintf(stderr, "libpng warning: %s\n", warning_message); + } + else +# endif + fprintf(stderr, "libpng warning: %s\n", warning_message); +#else + /* make compiler happy */ ; + if (warning_message) + return; +#endif + /* make compiler happy */ ; + if (png_ptr) + return; +} + +/* This function is called when the application wants to use another method + * of handling errors and warnings. Note that the error function MUST NOT + * return to the calling routine or serious problems will occur. The return + * method used in the default routine calls longjmp(png_ptr->jmpbuf, 1) + */ +void PNGAPI +png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warning_fn) +{ + png_ptr->error_ptr = error_ptr; + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; +} + + +/* This function returns a pointer to the error_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_error_ptr(png_structp png_ptr) +{ + return ((png_voidp)png_ptr->error_ptr); +} + + +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +void PNGAPI +png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) +{ + if(png_ptr != NULL) + { + png_ptr->flags &= + ((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); + } +} +#endif diff --git a/Utilities/FLTK/png/pngget.c b/Utilities/FLTK/png/pngget.c new file mode 100644 index 0000000000..eefd3319b4 --- /dev/null +++ b/Utilities/FLTK/png/pngget.c @@ -0,0 +1,934 @@ + +/* pngget.c - retrieval of values from info struct + * + * libpng 1.2.7 - September 12, 2004 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" + +png_uint_32 PNGAPI +png_get_valid(png_structp png_ptr, png_infop info_ptr, png_uint_32 flag) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->valid & flag); + else + return(0); +} + +png_uint_32 PNGAPI +png_get_rowbytes(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->rowbytes); + else + return(0); +} + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +png_bytepp PNGAPI +png_get_rows(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->row_pointers); + else + return(0); +} +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* easy access to info, added in libpng-0.99 */ +png_uint_32 PNGAPI +png_get_image_width(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->width; + } + return (0); +} + +png_uint_32 PNGAPI +png_get_image_height(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->height; + } + return (0); +} + +png_byte PNGAPI +png_get_bit_depth(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->bit_depth; + } + return (0); +} + +png_byte PNGAPI +png_get_color_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->color_type; + } + return (0); +} + +png_byte PNGAPI +png_get_filter_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->filter_type; + } + return (0); +} + +png_byte PNGAPI +png_get_interlace_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->interlace_type; + } + return (0); +} + +png_byte PNGAPI +png_get_compression_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->compression_type; + } + return (0); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_x_pixels_per_meter"); + if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER) + return (0); + else return (info_ptr->x_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_y_pixels_per_meter"); + if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER) + return (0); + else return (info_ptr->y_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +png_uint_32 PNGAPI +png_get_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_pixels_per_meter"); + if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER || + info_ptr->x_pixels_per_unit != info_ptr->y_pixels_per_unit) + return (0); + else return (info_ptr->x_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_pixel_aspect_ratio(png_structp png_ptr, png_infop info_ptr) + { + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_aspect_ratio"); + if (info_ptr->x_pixels_per_unit == 0) + return ((float)0.0); + else + return ((float)((float)info_ptr->y_pixels_per_unit + /(float)info_ptr->x_pixels_per_unit)); + } +#else + return (0.0); +#endif + return ((float)0.0); +} +#endif + +png_int_32 PNGAPI +png_get_x_offset_microns(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns"); + if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) + return (0); + else return (info_ptr->x_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_microns(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns"); + if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) + return (0); + else return (info_ptr->y_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_x_offset_pixels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns"); + if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) + return (0); + else return (info_ptr->x_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_pixels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns"); + if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) + return (0); + else return (info_ptr->y_offset); + } +#else + return (0); +#endif + return (0); +} + +#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) +png_uint_32 PNGAPI +png_get_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_x_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_y_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +float PNGAPI +png_get_x_offset_inches(png_structp png_ptr, png_infop info_ptr) +{ + return ((float)png_get_x_offset_microns(png_ptr, info_ptr) + *.00003937); +} + +float PNGAPI +png_get_y_offset_inches(png_structp png_ptr, png_infop info_ptr) +{ + return ((float)png_get_y_offset_microns(png_ptr, info_ptr) + *.00003937); +} + +#if defined(PNG_pHYs_SUPPORTED) +png_uint_32 PNGAPI +png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function\n", "pHYs"); + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + if(*unit_type == 1) + { + if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50); + if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50); + } + } + } + return (retval); +} +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ + +/* png_get_channels really belongs in here, too, but it's been around longer */ + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +png_byte PNGAPI +png_get_channels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->channels); + else + return (0); +} + +png_bytep PNGAPI +png_get_signature(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->signature); + else + return (NULL); +} + +#if defined(PNG_bKGD_SUPPORTED) +png_uint_32 PNGAPI +png_get_bKGD(png_structp png_ptr, png_infop info_ptr, + png_color_16p *background) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) + && background != NULL) + { + png_debug1(1, "in %s retrieval function\n", "bKGD"); + *background = &(info_ptr->background); + return (PNG_INFO_bKGD); + } + return (0); +} +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM(png_structp png_ptr, png_infop info_ptr, + double *white_x, double *white_y, double *red_x, double *red_y, + double *green_x, double *green_y, double *blue_x, double *blue_y) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + png_debug1(1, "in %s retrieval function\n", "cHRM"); + if (white_x != NULL) + *white_x = (double)info_ptr->x_white; + if (white_y != NULL) + *white_y = (double)info_ptr->y_white; + if (red_x != NULL) + *red_x = (double)info_ptr->x_red; + if (red_y != NULL) + *red_y = (double)info_ptr->y_red; + if (green_x != NULL) + *green_x = (double)info_ptr->x_green; + if (green_y != NULL) + *green_y = (double)info_ptr->y_green; + if (blue_x != NULL) + *blue_x = (double)info_ptr->x_blue; + if (blue_y != NULL) + *blue_y = (double)info_ptr->y_blue; + return (PNG_INFO_cHRM); + } + return (0); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x, + png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y, + png_fixed_point *blue_x, png_fixed_point *blue_y) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + png_debug1(1, "in %s retrieval function\n", "cHRM"); + if (white_x != NULL) + *white_x = info_ptr->int_x_white; + if (white_y != NULL) + *white_y = info_ptr->int_y_white; + if (red_x != NULL) + *red_x = info_ptr->int_x_red; + if (red_y != NULL) + *red_y = info_ptr->int_y_red; + if (green_x != NULL) + *green_x = info_ptr->int_x_green; + if (green_y != NULL) + *green_y = info_ptr->int_y_green; + if (blue_x != NULL) + *blue_x = info_ptr->int_x_blue; + if (blue_y != NULL) + *blue_y = info_ptr->int_y_blue; + return (PNG_INFO_cHRM); + } + return (0); +} +#endif +#endif + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) + && file_gamma != NULL) + { + png_debug1(1, "in %s retrieval function\n", "gAMA"); + *file_gamma = (double)info_ptr->gamma; + return (PNG_INFO_gAMA); + } + return (0); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point *int_file_gamma) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) + && int_file_gamma != NULL) + { + png_debug1(1, "in %s retrieval function\n", "gAMA"); + *int_file_gamma = info_ptr->int_gamma; + return (PNG_INFO_gAMA); + } + return (0); +} +#endif +#endif + +#if defined(PNG_sRGB_SUPPORTED) +png_uint_32 PNGAPI +png_get_sRGB(png_structp png_ptr, png_infop info_ptr, int *file_srgb_intent) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB) + && file_srgb_intent != NULL) + { + png_debug1(1, "in %s retrieval function\n", "sRGB"); + *file_srgb_intent = (int)info_ptr->srgb_intent; + return (PNG_INFO_sRGB); + } + return (0); +} +#endif + +#if defined(PNG_iCCP_SUPPORTED) +png_uint_32 PNGAPI +png_get_iCCP(png_structp png_ptr, png_infop info_ptr, + png_charpp name, int *compression_type, + png_charpp profile, png_uint_32 *proflen) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) + && name != NULL && profile != NULL && proflen != NULL) + { + png_debug1(1, "in %s retrieval function\n", "iCCP"); + *name = info_ptr->iccp_name; + *profile = info_ptr->iccp_profile; + /* compression_type is a dummy so the API won't have to change + if we introduce multiple compression types later. */ + *proflen = (int)info_ptr->iccp_proflen; + *compression_type = (int)info_ptr->iccp_compression; + return (PNG_INFO_iCCP); + } + return (0); +} +#endif + +#if defined(PNG_sPLT_SUPPORTED) +png_uint_32 PNGAPI +png_get_sPLT(png_structp png_ptr, png_infop info_ptr, + png_sPLT_tpp spalettes) +{ + if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL) + *spalettes = info_ptr->splt_palettes; + return ((png_uint_32)info_ptr->splt_palettes_num); +} +#endif + +#if defined(PNG_hIST_SUPPORTED) +png_uint_32 PNGAPI +png_get_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p *hist) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) + && hist != NULL) + { + png_debug1(1, "in %s retrieval function\n", "hIST"); + *hist = info_ptr->hist; + return (PNG_INFO_hIST); + } + return (0); +} +#endif + +png_uint_32 PNGAPI +png_get_IHDR(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *width, png_uint_32 *height, int *bit_depth, + int *color_type, int *interlace_type, int *compression_type, + int *filter_type) + +{ + if (png_ptr != NULL && info_ptr != NULL && width != NULL && height != NULL && + bit_depth != NULL && color_type != NULL) + { + png_debug1(1, "in %s retrieval function\n", "IHDR"); + *width = info_ptr->width; + *height = info_ptr->height; + *bit_depth = info_ptr->bit_depth; + if (info_ptr->bit_depth < 1 || info_ptr->bit_depth > 16) + png_error(png_ptr, "Invalid bit depth"); + *color_type = info_ptr->color_type; + if (info_ptr->color_type > 6) + png_error(png_ptr, "Invalid color type"); + if (compression_type != NULL) + *compression_type = info_ptr->compression_type; + if (filter_type != NULL) + *filter_type = info_ptr->filter_type; + if (interlace_type != NULL) + *interlace_type = info_ptr->interlace_type; + + /* check for potential overflow of rowbytes */ + if (width == 0 || *width > PNG_UINT_31_MAX) + png_error(png_ptr, "Invalid image width"); + if (height == 0 || *height > PNG_UINT_31_MAX) + png_error(png_ptr, "Invalid image height"); + if (info_ptr->width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 64 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + { + png_warning(png_ptr, + "Width too large for libpng to process image data."); + } + return (1); + } + return (0); +} + +#if defined(PNG_oFFs_SUPPORTED) +png_uint_32 PNGAPI +png_get_oFFs(png_structp png_ptr, png_infop info_ptr, + png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) + && offset_x != NULL && offset_y != NULL && unit_type != NULL) + { + png_debug1(1, "in %s retrieval function\n", "oFFs"); + *offset_x = info_ptr->x_offset; + *offset_y = info_ptr->y_offset; + *unit_type = (int)info_ptr->offset_unit_type; + return (PNG_INFO_oFFs); + } + return (0); +} +#endif + +#if defined(PNG_pCAL_SUPPORTED) +png_uint_32 PNGAPI +png_get_pCAL(png_structp png_ptr, png_infop info_ptr, + png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams, + png_charp *units, png_charpp *params) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) + && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL && + nparams != NULL && units != NULL && params != NULL) + { + png_debug1(1, "in %s retrieval function\n", "pCAL"); + *purpose = info_ptr->pcal_purpose; + *X0 = info_ptr->pcal_X0; + *X1 = info_ptr->pcal_X1; + *type = (int)info_ptr->pcal_type; + *nparams = (int)info_ptr->pcal_nparams; + *units = info_ptr->pcal_units; + *params = info_ptr->pcal_params; + return (PNG_INFO_pCAL); + } + return (0); +} +#endif + +#if defined(PNG_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL(png_structp png_ptr, png_infop info_ptr, + int *unit, double *width, double *height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_pixel_width; + *height = info_ptr->scal_pixel_height; + return (PNG_INFO_sCAL); + } + return(0); +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr, + int *unit, png_charpp width, png_charpp height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_s_width; + *height = info_ptr->scal_s_height; + return (PNG_INFO_sCAL); + } + return(0); +} +#endif +#endif +#endif + +#if defined(PNG_pHYs_SUPPORTED) +png_uint_32 PNGAPI +png_get_pHYs(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function\n", "pHYs"); + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + } + } + return (retval); +} +#endif + +png_uint_32 PNGAPI +png_get_PLTE(png_structp png_ptr, png_infop info_ptr, png_colorp *palette, + int *num_palette) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE) + && palette != NULL) + { + png_debug1(1, "in %s retrieval function\n", "PLTE"); + *palette = info_ptr->palette; + *num_palette = info_ptr->num_palette; + png_debug1(3, "num_palette = %d\n", *num_palette); + return (PNG_INFO_PLTE); + } + return (0); +} + +#if defined(PNG_sBIT_SUPPORTED) +png_uint_32 PNGAPI +png_get_sBIT(png_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) + && sig_bit != NULL) + { + png_debug1(1, "in %s retrieval function\n", "sBIT"); + *sig_bit = &(info_ptr->sig_bit); + return (PNG_INFO_sBIT); + } + return (0); +} +#endif + +#if defined(PNG_TEXT_SUPPORTED) +png_uint_32 PNGAPI +png_get_text(png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr, + int *num_text) +{ + if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0) + { + png_debug1(1, "in %s retrieval function\n", + (png_ptr->chunk_name[0] == '\0' ? "text" + : (png_const_charp)png_ptr->chunk_name)); + if (text_ptr != NULL) + *text_ptr = info_ptr->text; + if (num_text != NULL) + *num_text = info_ptr->num_text; + return ((png_uint_32)info_ptr->num_text); + } + if (num_text != NULL) + *num_text = 0; + return(0); +} +#endif + +#if defined(PNG_tIME_SUPPORTED) +png_uint_32 PNGAPI +png_get_tIME(png_structp png_ptr, png_infop info_ptr, png_timep *mod_time) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) + && mod_time != NULL) + { + png_debug1(1, "in %s retrieval function\n", "tIME"); + *mod_time = &(info_ptr->mod_time); + return (PNG_INFO_tIME); + } + return (0); +} +#endif + +#if defined(PNG_tRNS_SUPPORTED) +png_uint_32 PNGAPI +png_get_tRNS(png_structp png_ptr, png_infop info_ptr, + png_bytep *trans, int *num_trans, png_color_16p *trans_values) +{ + png_uint_32 retval = 0; + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_debug1(1, "in %s retrieval function\n", "tRNS"); + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (trans != NULL) + { + *trans = info_ptr->trans; + retval |= PNG_INFO_tRNS; + } + if (trans_values != NULL) + *trans_values = &(info_ptr->trans_values); + } + else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ + { + if (trans_values != NULL) + { + *trans_values = &(info_ptr->trans_values); + retval |= PNG_INFO_tRNS; + } + if(trans != NULL) + *trans = NULL; + } + if(num_trans != NULL) + { + *num_trans = info_ptr->num_trans; + retval |= PNG_INFO_tRNS; + } + } + return (retval); +} +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +png_uint_32 PNGAPI +png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr, + png_unknown_chunkpp unknowns) +{ + if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) + *unknowns = info_ptr->unknown_chunks; + return ((png_uint_32)info_ptr->unknown_chunks_num); +} +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +png_byte PNGAPI +png_get_rgb_to_gray_status (png_structp png_ptr) +{ + return (png_byte)(png_ptr? png_ptr->rgb_to_gray_status : 0); +} +#endif + +#if defined(PNG_USER_CHUNKS_SUPPORTED) +png_voidp PNGAPI +png_get_user_chunk_ptr(png_structp png_ptr) +{ + return (png_ptr? png_ptr->user_chunk_ptr : NULL); +} +#endif + +#ifdef PNG_WRITE_SUPPORTED +png_uint_32 PNGAPI +png_get_compression_buffer_size(png_structp png_ptr) +{ + return (png_uint_32)(png_ptr? png_ptr->zbuf_size : 0L); +} +#endif + +#ifndef PNG_1_0_X +#ifdef PNG_ASSEMBLER_CODE_SUPPORTED +/* this function was added to libpng 1.2.0 and should exist by default */ +png_uint_32 PNGAPI +png_get_asm_flags (png_structp png_ptr) +{ + return (png_uint_32)(png_ptr? png_ptr->asm_flags : 0L); +} + +/* this function was added to libpng 1.2.0 and should exist by default */ +png_uint_32 PNGAPI +png_get_asm_flagmask (int flag_select) +{ + png_uint_32 settable_asm_flags = 0; + + if (flag_select & PNG_SELECT_READ) + settable_asm_flags |= + PNG_ASM_FLAG_MMX_READ_COMBINE_ROW | + PNG_ASM_FLAG_MMX_READ_INTERLACE | + PNG_ASM_FLAG_MMX_READ_FILTER_SUB | + PNG_ASM_FLAG_MMX_READ_FILTER_UP | + PNG_ASM_FLAG_MMX_READ_FILTER_AVG | + PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ; + /* no non-MMX flags yet */ + +#if 0 + /* GRR: no write-flags yet, either, but someday... */ + if (flag_select & PNG_SELECT_WRITE) + settable_asm_flags |= + PNG_ASM_FLAG_MMX_WRITE_ [whatever] ; +#endif /* 0 */ + + return settable_asm_flags; /* _theoretically_ settable capabilities only */ +} +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + + +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) + /* GRR: could add this: && defined(PNG_MMX_CODE_SUPPORTED) */ +/* this function was added to libpng 1.2.0 */ +png_uint_32 PNGAPI +png_get_mmx_flagmask (int flag_select, int *compilerID) +{ + png_uint_32 settable_mmx_flags = 0; + + if (flag_select & PNG_SELECT_READ) + settable_mmx_flags |= + PNG_ASM_FLAG_MMX_READ_COMBINE_ROW | + PNG_ASM_FLAG_MMX_READ_INTERLACE | + PNG_ASM_FLAG_MMX_READ_FILTER_SUB | + PNG_ASM_FLAG_MMX_READ_FILTER_UP | + PNG_ASM_FLAG_MMX_READ_FILTER_AVG | + PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ; +#if 0 + /* GRR: no MMX write support yet, but someday... */ + if (flag_select & PNG_SELECT_WRITE) + settable_mmx_flags |= + PNG_ASM_FLAG_MMX_WRITE_ [whatever] ; +#endif /* 0 */ + + if (compilerID != NULL) { +#ifdef PNG_USE_PNGVCRD + *compilerID = 1; /* MSVC */ +#else +#ifdef PNG_USE_PNGGCCRD + *compilerID = 2; /* gcc/gas */ +#else + *compilerID = -1; /* unknown (i.e., no asm/MMX code compiled) */ +#endif +#endif + } + + return settable_mmx_flags; /* _theoretically_ settable capabilities only */ +} + +/* this function was added to libpng 1.2.0 */ +png_byte PNGAPI +png_get_mmx_bitdepth_threshold (png_structp png_ptr) +{ + return (png_byte)(png_ptr? png_ptr->mmx_bitdepth_threshold : 0); +} + +/* this function was added to libpng 1.2.0 */ +png_uint_32 PNGAPI +png_get_mmx_rowbytes_threshold (png_structp png_ptr) +{ + return (png_uint_32)(png_ptr? png_ptr->mmx_rowbytes_threshold : 0L); +} +#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* these functions were added to libpng 1.2.6 */ +png_uint_32 PNGAPI +png_get_user_width_max (png_structp png_ptr) +{ + return (png_ptr? png_ptr->user_width_max : 0); +} +png_uint_32 PNGAPI +png_get_user_height_max (png_structp png_ptr) +{ + return (png_ptr? png_ptr->user_height_max : 0); +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + +#endif /* ?PNG_1_0_X */ diff --git a/Utilities/FLTK/png/pngmem.c b/Utilities/FLTK/png/pngmem.c new file mode 100644 index 0000000000..7d0c2b9d29 --- /dev/null +++ b/Utilities/FLTK/png/pngmem.c @@ -0,0 +1,595 @@ + +/* pngmem.c - stub functions for memory allocation + * + * libpng version 1.2.7 - September 12, 2004 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file provides a location for all memory allocation. Users who + * need special memory handling are expected to supply replacement + * functions for png_malloc() and png_free(), and to use + * png_create_read_struct_2() and png_create_write_struct_2() to + * identify the replacement functions. + */ + +#define PNG_INTERNAL +#include "png.h" + +/* Borland DOS special memory handler */ +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* if you change this, be sure to change the one in png.h also */ + +/* Allocate memory for a png_struct. The malloc and memset can be replaced + by a single call to calloc() if this is thought to improve performance. */ +png_voidp /* PRIVATE */ +png_create_struct(int type) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL)); +} + +/* Alternate version of png_create_struct, for use with user-defined malloc. */ +png_voidp /* PRIVATE */ +png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = png_sizeof(png_info); + else if (type == PNG_STRUCT_PNG) + size = png_sizeof(png_struct); + else + return (png_get_copyright(NULL)); + +#ifdef PNG_USER_MEM_SUPPORTED + if(malloc_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size); + } + else +#endif /* PNG_USER_MEM_SUPPORTED */ + struct_ptr = (png_voidp)farmalloc(size); + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + return (struct_ptr); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +#endif + if (struct_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + if(free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } +#endif /* PNG_USER_MEM_SUPPORTED */ + farfree (struct_ptr); + } +} + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + * + * Borland seems to have a problem in DOS mode for exactly 64K. + * It gives you a segment with an offset of 8 (perhaps to store its + * memory stuff). zlib doesn't like this at all, so we have to + * detect and deal with it. This code should not be needed in + * Windows or OS/2 modes, and only in 16 bit mode. This code has + * been updated by Alexander Lehmann for version 0.89 to waste less + * memory. + * + * Note that we can't use png_size_t for the "size" declaration, + * since on some systems a png_size_t is a 16-bit quantity, and as a + * result, we would be truncating potentially larger memory requests + * (which should cause a fatal error) and introducing major problems. + */ + +png_voidp PNGAPI +png_malloc(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; + + if (png_ptr == NULL || size == 0) + return (NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + if(png_ptr->malloc_fn != NULL) + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + else + ret = (png_malloc_default(png_ptr, size)); + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of memory!"); + return (ret); +} + +png_voidp PNGAPI +png_malloc_default(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; +#endif /* PNG_USER_MEM_SUPPORTED */ + +#ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + { + png_warning(png_ptr, "Cannot Allocate > 64K"); + ret = NULL; + } + else +#endif + + if (size != (size_t)size) + ret = NULL; + else if (size == (png_uint_32)65536L) + { + if (png_ptr->offset_table == NULL) + { + /* try to see if we need to do any of this fancy stuff */ + ret = farmalloc(size); + if (ret == NULL || ((png_size_t)ret & 0xffff)) + { + int num_blocks; + png_uint_32 total_size; + png_bytep table; + int i; + png_byte huge * hptr; + + if (ret != NULL) + { + farfree(ret); + ret = NULL; + } + + if(png_ptr->zlib_window_bits > 14) + num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14)); + else + num_blocks = 1; + if (png_ptr->zlib_mem_level >= 7) + num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7)); + else + num_blocks++; + + total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16; + + table = farmalloc(total_size); + + if (table == NULL) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */ + else + png_warning(png_ptr, "Out Of Memory."); +#endif + return (NULL); + } + + if ((png_size_t)table & 0xfff0) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, + "Farmalloc didn't return normalized pointer"); + else + png_warning(png_ptr, + "Farmalloc didn't return normalized pointer"); +#endif + return (NULL); + } + + png_ptr->offset_table = table; + png_ptr->offset_table_ptr = farmalloc(num_blocks * + png_sizeof (png_bytep)); + + if (png_ptr->offset_table_ptr == NULL) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out Of memory."); /* Note "O" and "M" */ + else + png_warning(png_ptr, "Out Of memory."); +#endif + return (NULL); + } + + hptr = (png_byte huge *)table; + if ((png_size_t)hptr & 0xf) + { + hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); + hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */ + } + for (i = 0; i < num_blocks; i++) + { + png_ptr->offset_table_ptr[i] = (png_bytep)hptr; + hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */ + } + + png_ptr->offset_table_number = num_blocks; + png_ptr->offset_table_count = 0; + png_ptr->offset_table_count_free = 0; + } + } + + if (png_ptr->offset_table_count >= png_ptr->offset_table_number) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory."); /* Note "o" and "M" */ + else + png_warning(png_ptr, "Out of Memory."); +#endif + return (NULL); + } + + ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++]; + } + else + ret = farmalloc(size); + +#ifndef PNG_USER_MEM_SUPPORTED + if (ret == NULL) + { + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */ + else + png_warning(png_ptr, "Out of memory."); /* Note "o" and "m" */ + } +#endif + + return (ret); +} + +/* free a pointer allocated by png_malloc(). In the default + configuration, png_ptr is not used, but is passed in case it + is needed. If ptr is NULL, return without taking any action. */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + else png_free_default(png_ptr, ptr); +} + +void PNGAPI +png_free_default(png_structp png_ptr, png_voidp ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr->offset_table != NULL) + { + int i; + + for (i = 0; i < png_ptr->offset_table_count; i++) + { + if (ptr == png_ptr->offset_table_ptr[i]) + { + ptr = NULL; + png_ptr->offset_table_count_free++; + break; + } + } + if (png_ptr->offset_table_count_free == png_ptr->offset_table_count) + { + farfree(png_ptr->offset_table); + farfree(png_ptr->offset_table_ptr); + png_ptr->offset_table = NULL; + png_ptr->offset_table_ptr = NULL; + } + } + + if (ptr != NULL) + { + farfree(ptr); + } +} + +#else /* Not the Borland DOS special memory handler */ + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably. */ +png_voidp /* PRIVATE */ +png_create_struct(int type) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL)); +} + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably. */ +png_voidp /* PRIVATE */ +png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = png_sizeof(png_info); + else if (type == PNG_STRUCT_PNG) + size = png_sizeof(png_struct); + else + return (NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + if(malloc_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, size); + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + return (struct_ptr); + } +#endif /* PNG_USER_MEM_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(__FLAT__) + struct_ptr = (png_voidp)farmalloc(size); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + struct_ptr = (png_voidp)halloc(size,1); +# else + struct_ptr = (png_voidp)malloc(size); +# endif +#endif + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + + return (struct_ptr); +} + + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + if (struct_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + if(free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } +#endif /* PNG_USER_MEM_SUPPORTED */ +#if defined(__TURBOC__) && !defined(__FLAT__) + farfree(struct_ptr); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(struct_ptr); +# else + free(struct_ptr); +# endif +#endif + } +} + +/* Allocate memory. For reasonable files, size should never exceed + 64K. However, zlib may allocate more then 64K if you don't tell + it not to. See zconf.h and png.h for more information. zlib does + need to allocate exactly 64K, so whatever you call here must + have the ability to do that. */ + +png_voidp PNGAPI +png_malloc(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr == NULL || size == 0) + return (NULL); + + if(png_ptr->malloc_fn != NULL) + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + else + ret = (png_malloc_default(png_ptr, size)); + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory!"); + return (ret); +} + +png_voidp PNGAPI +png_malloc_default(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; +#endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || size == 0) + return (NULL); + +#ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + { +#ifndef PNG_USER_MEM_SUPPORTED + if(png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Cannot Allocate > 64K"); + else +#endif + return NULL; + } +#endif + + /* Check for overflow */ +#if defined(__TURBOC__) && !defined(__FLAT__) + if (size != (unsigned long)size) + ret = NULL; + else + ret = farmalloc(size); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + if (size != (unsigned long)size) + ret = NULL; + else + ret = halloc(size, 1); +# else + if (size != (size_t)size) + ret = NULL; + else + ret = malloc((size_t)size); +# endif +#endif + +#ifndef PNG_USER_MEM_SUPPORTED + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory"); +#endif + + return (ret); +} + +/* Free a pointer allocated by png_malloc(). If ptr is NULL, return + without taking any action. */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + else png_free_default(png_ptr, ptr); +} +void PNGAPI +png_free_default(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#endif /* PNG_USER_MEM_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(__FLAT__) + farfree(ptr); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(ptr); +# else + free(ptr); +# endif +#endif +} + +#endif /* Not Borland DOS special memory handler */ + +#if defined(PNG_1_0_X) +# define png_malloc_warn png_malloc +#else +/* This function was added at libpng version 1.2.3. The png_malloc_warn() + * function will set up png_malloc() to issue a png_warning and return NULL + * instead of issuing a png_error, if it fails to allocate the requested + * memory. + */ +png_voidp PNGAPI +png_malloc_warn(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ptr; + png_uint_32 save_flags=png_ptr->flags; + + png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; + ptr = (png_voidp)png_malloc((png_structp)png_ptr, size); + png_ptr->flags=save_flags; + return(ptr); +} +#endif + +png_voidp PNGAPI +png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2, + png_uint_32 length) +{ + png_size_t size; + + size = (png_size_t)length; + if ((png_uint_32)size != length) + png_error(png_ptr,"Overflow in png_memcpy_check."); + + return(png_memcpy (s1, s2, size)); +} + +png_voidp PNGAPI +png_memset_check (png_structp png_ptr, png_voidp s1, int value, + png_uint_32 length) +{ + png_size_t size; + + size = (png_size_t)length; + if ((png_uint_32)size != length) + png_error(png_ptr,"Overflow in png_memset_check."); + + return (png_memset (s1, value, size)); + +} + +#ifdef PNG_USER_MEM_SUPPORTED +/* This function is called when the application wants to use another method + * of allocating and freeing memory. + */ +void PNGAPI +png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr + malloc_fn, png_free_ptr free_fn) +{ + png_ptr->mem_ptr = mem_ptr; + png_ptr->malloc_fn = malloc_fn; + png_ptr->free_fn = free_fn; +} + +/* This function returns a pointer to the mem_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_mem_ptr(png_structp png_ptr) +{ + return ((png_voidp)png_ptr->mem_ptr); +} +#endif /* PNG_USER_MEM_SUPPORTED */ diff --git a/Utilities/FLTK/png/pngpread.c b/Utilities/FLTK/png/pngpread.c new file mode 100644 index 0000000000..ba45d138ee --- /dev/null +++ b/Utilities/FLTK/png/pngpread.c @@ -0,0 +1,1573 @@ + +/* pngpread.c - read a png file in push mode + * + * libpng version 1.2.7 - September 12, 2004 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + +/* push model modes */ +#define PNG_READ_SIG_MODE 0 +#define PNG_READ_CHUNK_MODE 1 +#define PNG_READ_IDAT_MODE 2 +#define PNG_SKIP_MODE 3 +#define PNG_READ_tEXt_MODE 4 +#define PNG_READ_zTXt_MODE 5 +#define PNG_READ_DONE_MODE 6 +#define PNG_READ_iTXt_MODE 7 +#define PNG_ERROR_MODE 8 + +void PNGAPI +png_process_data(png_structp png_ptr, png_infop info_ptr, + png_bytep buffer, png_size_t buffer_size) +{ + png_push_restore_buffer(png_ptr, buffer, buffer_size); + + while (png_ptr->buffer_size) + { + png_process_some_data(png_ptr, info_ptr); + } +} + +/* What we do with the incoming data depends on what we were previously + * doing before we ran out of data... + */ +void /* PRIVATE */ +png_process_some_data(png_structp png_ptr, png_infop info_ptr) +{ + switch (png_ptr->process_mode) + { + case PNG_READ_SIG_MODE: + { + png_push_read_sig(png_ptr, info_ptr); + break; + } + case PNG_READ_CHUNK_MODE: + { + png_push_read_chunk(png_ptr, info_ptr); + break; + } + case PNG_READ_IDAT_MODE: + { + png_push_read_IDAT(png_ptr); + break; + } +#if defined(PNG_READ_tEXt_SUPPORTED) + case PNG_READ_tEXt_MODE: + { + png_push_read_tEXt(png_ptr, info_ptr); + break; + } +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + case PNG_READ_zTXt_MODE: + { + png_push_read_zTXt(png_ptr, info_ptr); + break; + } +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + case PNG_READ_iTXt_MODE: + { + png_push_read_iTXt(png_ptr, info_ptr); + break; + } +#endif + case PNG_SKIP_MODE: + { + png_push_crc_finish(png_ptr); + break; + } + default: + { + png_ptr->buffer_size = 0; + break; + } + } +} + +/* Read any remaining signature bytes from the stream and compare them with + * the correct PNG signature. It is possible that this routine is called + * with bytes already read from the signature, either because they have been + * checked by the calling application, or because of multiple calls to this + * routine. + */ +void /* PRIVATE */ +png_push_read_sig(png_structp png_ptr, png_infop info_ptr) +{ + png_size_t num_checked = png_ptr->sig_bytes, + num_to_check = 8 - num_checked; + + if (png_ptr->buffer_size < num_to_check) + { + num_to_check = png_ptr->buffer_size; + } + + png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), + num_to_check); + png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes+num_to_check); + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + else + { + if (png_ptr->sig_bytes >= 8) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } + } +} + +void /* PRIVATE */ +png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#if defined(PNG_READ_bKGD_SUPPORTED) + PNG_bKGD; +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + PNG_cHRM; +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + PNG_gAMA; +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + PNG_hIST; +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + PNG_iCCP; +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + PNG_iTXt; +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + PNG_oFFs; +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + PNG_pCAL; +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + PNG_pHYs; +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + PNG_sBIT; +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + PNG_sCAL; +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + PNG_sRGB; +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + PNG_sPLT; +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + PNG_tEXt; +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + PNG_tIME; +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + PNG_tRNS; +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + PNG_zTXt; +#endif +#endif /* PNG_USE_LOCAL_ARRAYS */ + /* First we make sure we have enough data for the 4 byte chunk name + * and the 4 byte chunk length before proceeding with decoding the + * chunk data. To fully decode each of these chunks, we also make + * sure we have enough data in the buffer for the 4 byte CRC at the + * end of every chunk (except IDAT, which is handled separately). + */ + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + } + + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); + } + else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); + + png_ptr->process_mode = PNG_READ_DONE_MODE; + png_push_have_end(png_ptr, info_ptr); + } +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + } + } +#endif + else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); + } + else if (!png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4)) + { + /* If we reach an IDAT chunk, this means we have read all of the + * header chunks, and we can start reading the image (or if this + * is called after the image has been read - we have an error). + */ + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + { + if (png_ptr->push_length == 0) + return; + + if (png_ptr->mode & PNG_AFTER_IDAT) + png_error(png_ptr, "Too many IDAT's found"); + } + + png_ptr->idat_size = png_ptr->push_length; + png_ptr->mode |= PNG_HAVE_IDAT; + png_ptr->process_mode = PNG_READ_IDAT_MODE; + png_push_have_info(png_ptr, info_ptr); + png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; + png_ptr->zstream.next_out = png_ptr->row_buf; + return; + } +#if defined(PNG_READ_gAMA_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_bKGD_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); + } +#endif + else + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + } + + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; +} + +void /* PRIVATE */ +png_push_crc_skip(png_structp png_ptr, png_uint_32 skip) +{ + png_ptr->process_mode = PNG_SKIP_MODE; + png_ptr->skip_length = skip; +} + +void /* PRIVATE */ +png_push_crc_finish(png_structp png_ptr) +{ + if (png_ptr->skip_length && png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size) + save_size = (png_size_t)png_ptr->skip_length; + else + save_size = png_ptr->save_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->skip_length -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (png_ptr->skip_length && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size) + save_size = (png_size_t)png_ptr->skip_length; + else + save_size = png_ptr->current_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->skip_length -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->skip_length) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } +} + +void PNGAPI +png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) +{ + png_bytep ptr; + + ptr = buffer; + if (png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->save_buffer_size) + save_size = length; + else + save_size = png_ptr->save_buffer_size; + + png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size); + length -= save_size; + ptr += save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (length && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->current_buffer_size) + save_size = length; + else + save_size = png_ptr->current_buffer_size; + + png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size); + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } +} + +void /* PRIVATE */ +png_push_save_buffer(png_structp png_ptr) +{ + if (png_ptr->save_buffer_size) + { + if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) + { + png_size_t i,istop; + png_bytep sp; + png_bytep dp; + + istop = png_ptr->save_buffer_size; + for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; + i < istop; i++, sp++, dp++) + { + *dp = *sp; + } + } + } + if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > + png_ptr->save_buffer_max) + { + png_size_t new_max; + png_bytep old_buffer; + + if (png_ptr->save_buffer_size > PNG_SIZE_MAX - + (png_ptr->current_buffer_size + 256)) + { + png_error(png_ptr, "Potential overflow of save_buffer"); + } + new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; + old_buffer = png_ptr->save_buffer; + png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr, + (png_uint_32)new_max); + png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); + png_free(png_ptr, old_buffer); + png_ptr->save_buffer_max = new_max; + } + if (png_ptr->current_buffer_size) + { + png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, + png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); + png_ptr->save_buffer_size += png_ptr->current_buffer_size; + png_ptr->current_buffer_size = 0; + } + png_ptr->save_buffer_ptr = png_ptr->save_buffer; + png_ptr->buffer_size = 0; +} + +void /* PRIVATE */ +png_push_restore_buffer(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + png_ptr->current_buffer = buffer; + png_ptr->current_buffer_size = buffer_length; + png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size; + png_ptr->current_buffer_ptr = png_ptr->current_buffer; +} + +void /* PRIVATE */ +png_push_read_IDAT(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IDAT; +#endif + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + + if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4)) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_error(png_ptr, "Not enough compressed data"); + return; + } + + png_ptr->idat_size = png_ptr->push_length; + } + if (png_ptr->idat_size && png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size) + { + save_size = (png_size_t)png_ptr->idat_size; + /* check for overflow */ + if((png_uint_32)save_size != png_ptr->idat_size) + png_error(png_ptr, "save_size overflowed in pngpread"); + } + else + save_size = png_ptr->save_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); + png_ptr->idat_size -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (png_ptr->idat_size && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size) + { + save_size = (png_size_t)png_ptr->idat_size; + /* check for overflow */ + if((png_uint_32)save_size != png_ptr->idat_size) + png_error(png_ptr, "save_size overflowed in pngpread"); + } + else + save_size = png_ptr->current_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->idat_size -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->idat_size) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + png_ptr->mode |= PNG_AFTER_IDAT; + } +} + +void /* PRIVATE */ +png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + int ret; + + if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length) + png_error(png_ptr, "Extra compression data"); + + png_ptr->zstream.next_in = buffer; + png_ptr->zstream.avail_in = (uInt)buffer_length; + for(;;) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK) + { + if (ret == Z_STREAM_END) + { + if (png_ptr->zstream.avail_in) + png_error(png_ptr, "Extra compressed data"); + if (!(png_ptr->zstream.avail_out)) + { + png_push_process_row(png_ptr); + } + + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + else if (ret == Z_BUF_ERROR) + break; + else + png_error(png_ptr, "Decompression Error"); + } + if (!(png_ptr->zstream.avail_out)) + { + if (( +#if defined(PNG_READ_INTERLACING_SUPPORTED) + png_ptr->interlaced && png_ptr->pass > 6) || + (!png_ptr->interlaced && +#endif + png_ptr->row_number == png_ptr->num_rows)) + { + if (png_ptr->zstream.avail_in) + png_warning(png_ptr, "Too much data in IDAT chunks"); + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + png_push_process_row(png_ptr); + png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; + png_ptr->zstream.next_out = png_ptr->row_buf; + } + else + break; + } +} + +void /* PRIVATE */ +png_push_process_row(png_structp png_ptr) +{ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, + png_ptr->rowbytes + 1); + + if (png_ptr->transformations) + png_do_read_transformations(png_ptr); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) + /* blow up interlaced rows to full size */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) +/* old interface (pre-1.0.9): + png_do_read_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + switch (png_ptr->pass) + { + case 0: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 0; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); /* updates png_ptr->pass */ + } + if (png_ptr->pass == 2) /* pass 1 might be empty */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + if (png_ptr->pass == 4 && png_ptr->height <= 4) + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + if (png_ptr->pass == 6 && png_ptr->height <= 4) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + break; + } + case 1: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 1; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 2) /* skip top 4 generated rows */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + break; + } + case 2: + { + int i; + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 4) /* pass 3 might be empty */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + break; + } + case 3: + { + int i; + for (i = 0; i < 4 && png_ptr->pass == 3; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 4) /* skip top two generated rows */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + break; + } + case 4: + { + int i; + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 6) /* pass 5 might be empty */ + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + break; + } + case 5: + { + int i; + for (i = 0; i < 2 && png_ptr->pass == 5; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 6) /* skip top generated row */ + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + break; + } + case 6: + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + if (png_ptr->pass != 6) + break; + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + } + else +#endif + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } +} + +void /* PRIVATE */ +png_read_push_finish_row(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + const int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + const int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + + /* start of interlace block in the y direction */ + const int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + + /* offset to next interlace block in the y direction */ + const int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + + /* Width of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h + const int FARDATA png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; + */ + + /* Height of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h + const int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; + */ +#endif + + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + png_memset_check(png_ptr, png_ptr->prev_row, 0, + png_ptr->rowbytes + 1); + do + { + png_ptr->pass++; + if ((png_ptr->pass == 1 && png_ptr->width < 5) || + (png_ptr->pass == 3 && png_ptr->width < 3) || + (png_ptr->pass == 5 && png_ptr->width < 2)) + png_ptr->pass++; + + if (png_ptr->pass > 7) + png_ptr->pass--; + if (png_ptr->pass >= 7) + break; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + + if (png_ptr->transformations & PNG_INTERLACE) + break; + + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + + } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); + } +} + +#if defined(PNG_READ_tEXt_SUPPORTED) +void /* PRIVATE */ +png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place tEXt"); + /* to quiet some compiler warnings */ + if(info_ptr == NULL) return; + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(length+1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_tEXt_MODE; +} + +void /* PRIVATE */ +png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + else + text_size = png_ptr->current_text_left; + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#if defined(PNG_MAX_MALLOC_64K) + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* empty loop */ ; + + if (text != key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, + (png_uint_32)png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; +#endif + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + png_ptr->current_text = NULL; + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk."); + } +} +#endif + +#if defined(PNG_READ_zTXt_SUPPORTED) +void /* PRIVATE */ +png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place zTXt"); + /* to quiet some compiler warnings */ + if(info_ptr == NULL) return; + } + +#ifdef PNG_MAX_MALLOC_64K + /* We can't handle zTXt chunks > 64K, since we don't have enough space + * to be able to store the uncompressed data. Actually, the threshold + * is probably around 32K, but it isn't as definite as 64K is. + */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_push_crc_skip(png_ptr, length); + return; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(length+1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_zTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + else + text_size = png_ptr->current_text_left; + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + png_size_t text_size, key_size; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* empty loop */ ; + + /* zTXt can't have zero text */ + if (text == key + png_ptr->current_text_size) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */ + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + png_ptr->zstream.next_in = (png_bytep )text; + png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - + (text - key)); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + key_size = text - key; + text_size = 0; + text = NULL; + ret = Z_STREAM_END; + + while (png_ptr->zstream.avail_in) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) + { + if (text == NULL) + { + text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out + + key_size + 1)); + png_memcpy(text + key_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + png_memcpy(text, key, key_size); + text_size = key_size + png_ptr->zbuf_size - + png_ptr->zstream.avail_out; + *(text + text_size) = '\0'; + } + else + { + png_charp tmp; + + tmp = text; + text = (png_charp)png_malloc(png_ptr, text_size + + (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out + + 1)); + png_memcpy(text, tmp, text_size); + png_free(png_ptr, tmp); + png_memcpy(text + text_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; + *(text + text_size) = '\0'; + } + if (ret != Z_STREAM_END) + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else + { + break; + } + + if (ret == Z_STREAM_END) + break; + } + + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + if (ret != Z_STREAM_END) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + + png_ptr->current_text = NULL; + png_free(png_ptr, key); + key = text; + text += key_size; + + text_ptr = (png_textp)png_malloc(png_ptr, + (png_uint_32)png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; +#endif + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk."); + } +} +#endif + +#if defined(PNG_READ_iTXt_SUPPORTED) +void /* PRIVATE */ +png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place iTXt"); + /* to quiet some compiler warnings */ + if(info_ptr == NULL) return; + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(length+1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_iTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) +{ + + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + else + text_size = png_ptr->current_text_left; + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp key; + int comp_flag; + png_charp lang; + png_charp lang_key; + png_charp text; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#if defined(PNG_MAX_MALLOC_64K) + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (lang = key; *lang; lang++) + /* empty loop */ ; + + if (lang != key + png_ptr->current_text_size) + lang++; + + comp_flag = *lang++; + lang++; /* skip comp_type, always zero */ + + for (lang_key = lang; *lang_key; lang_key++) + /* empty loop */ ; + lang_key++; /* skip NUL separator */ + + for (text = lang_key; *text; text++) + /* empty loop */ ; + + if (text != key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, + (png_uint_32)png_sizeof(png_text)); + text_ptr->compression = comp_flag + 2; + text_ptr->key = key; + text_ptr->lang = lang; + text_ptr->lang_key = lang_key; + text_ptr->text = text; + text_ptr->text_length = 0; + text_ptr->itxt_length = png_strlen(text); + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_ptr->current_text = NULL; + + png_free(png_ptr, text_ptr); + if (ret) + png_warning(png_ptr, "Insufficient memory to store iTXt chunk."); + } +} +#endif + +/* This function is called when we haven't found a handler for this + * chunk. If there isn't a problem with the chunk itself (ie a bad chunk + * name or a critical chunk), the chunk is (currently) silently ignored. + */ +void /* PRIVATE */ +png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + png_uint_32 skip=0; + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + + /* to quiet compiler warnings about unused info_ptr */ + if (info_ptr == NULL) + return; + } + +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) + { + png_unknown_chunk chunk; + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name); + chunk.data = (png_bytep)png_malloc(png_ptr, length); + png_crc_read(png_ptr, chunk.data, length); + chunk.size = length; +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) + if(png_ptr->read_user_chunk_fn != NULL) + { + /* callback to user unknown chunk handler */ + if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) + png_chunk_error(png_ptr, "unknown critical chunk"); + } + png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1); + } + else +#endif + png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1); + png_free(png_ptr, chunk.data); + } + else +#endif + skip=length; + png_push_crc_skip(png_ptr, skip); +} + +void /* PRIVATE */ +png_push_have_info(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->info_fn != NULL) + (*(png_ptr->info_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_end(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->end_fn != NULL) + (*(png_ptr->end_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_row(png_structp png_ptr, png_bytep row) +{ + if (png_ptr->row_fn != NULL) + (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, + (int)png_ptr->pass); +} + +void PNGAPI +png_progressive_combine_row (png_structp png_ptr, + png_bytep old_row, png_bytep new_row) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + const int FARDATA png_pass_dsp_mask[7] = + {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; +#endif + if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */ + png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]); +} + +void PNGAPI +png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn) +{ + png_ptr->info_fn = info_fn; + png_ptr->row_fn = row_fn; + png_ptr->end_fn = end_fn; + + png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); +} + +png_voidp PNGAPI +png_get_progressive_ptr(png_structp png_ptr) +{ + return png_ptr->io_ptr; +} +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ diff --git a/Utilities/FLTK/png/pngread.c b/Utilities/FLTK/png/pngread.c new file mode 100644 index 0000000000..168e28013d --- /dev/null +++ b/Utilities/FLTK/png/pngread.c @@ -0,0 +1,1453 @@ + +/* pngread.c - read a PNG file + * + * libpng 1.2.7 - September 12, 2004 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file contains routines that an application calls directly to + * read a PNG file or stream. + */ + +#define PNG_INTERNAL +#include "png.h" + +/* Create a PNG structure for reading, and allocate any memory needed. */ +png_structp PNGAPI +png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn) +{ + +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); +} + +/* Alternate create PNG structure for reading, and allocate any memory needed. */ +png_structp PNGAPI +png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + + png_structp png_ptr; + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + + int i; + + png_debug(1, "in png_create_read_struct\n"); +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); +#else + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); +#endif + if (png_ptr == NULL) + return (NULL); + +#if !defined(PNG_1_0_X) +#ifdef PNG_ASSEMBLER_CODE_SUPPORTED + png_init_mmx_flags(png_ptr); /* 1.2.0 addition */ +#endif +#endif /* PNG_1_0_X */ + + /* added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max=PNG_USER_WIDTH_MAX; + png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; +#endif + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_ptr->jmpbuf)) +#endif + { + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf=NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, + (png_free_ptr)free_fn, (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + return (NULL); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); +#endif +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#endif + + png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); + + i=0; + do + { + if(user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first digit. + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[80]; + if (user_png_ver) + { + sprintf(msg, "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + sprintf(msg, "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); +#endif +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "Incompatible libpng version in application and library"); + } + } + + /* initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + switch (inflateInit(&png_ptr->zstream)) + { + case Z_OK: /* Do nothing */ break; + case Z_MEM_ERROR: + case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break; + case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break; + default: png_error(png_ptr, "Unknown zlib error"); + } + + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); + +#ifdef PNG_SETJMP_SUPPORTED +/* Applications that neglect to set up their own setjmp() and then encounter + a png_error() will longjmp here. Since the jmpbuf is then meaningless we + abort instead of returning. */ +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) + PNG_ABORT(); + png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); +#else + if (setjmp(png_ptr->jmpbuf)) + PNG_ABORT(); +#endif +#endif + return (png_ptr); +} + +/* Initialize PNG structure for reading, and allocate any memory needed. + This interface is deprecated in favour of the png_create_read_struct(), + and it will eventually disappear. */ +#undef png_read_init +void PNGAPI +png_read_init(png_structp png_ptr) +{ + /* We only come here via pre-1.0.7-compiled applications */ + png_read_init_2(png_ptr, "1.0.6 or earlier", 0, 0); +} + +void PNGAPI +png_read_init_2(png_structp png_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size, png_size_t png_info_size) +{ + /* We only come here via pre-1.0.12-compiled applications */ +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + if(png_sizeof(png_struct) > png_struct_size || + png_sizeof(png_info) > png_info_size) + { + char msg[80]; + png_ptr->warning_fn=NULL; + if (user_png_ver) + { + sprintf(msg, "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + sprintf(msg, "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); + } +#endif + if(png_sizeof(png_struct) > png_struct_size) + { + png_ptr->error_fn=NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "The png struct allocated by the application for reading is too small."); + } + if(png_sizeof(png_info) > png_info_size) + { + png_ptr->error_fn=NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "The info struct allocated by application for reading is too small."); + } + png_read_init_3(&png_ptr, user_png_ver, png_struct_size); +} + +void PNGAPI +png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* to save current jump buffer */ +#endif + + int i=0; + + png_structp png_ptr=*ptr_ptr; + + do + { + if(user_png_ver[i] != png_libpng_ver[i]) + { +#ifdef PNG_LEGACY_SUPPORTED + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; +#else + png_ptr->warning_fn=NULL; + png_warning(png_ptr, + "Application uses deprecated png_read_init() and should be recompiled."); + break; +#endif + } + } while (png_libpng_ver[i++]); + + png_debug(1, "in png_read_init_3\n"); + +#ifdef PNG_SETJMP_SUPPORTED + /* save jump buffer and error functions */ + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); +#endif + + if(png_sizeof(png_struct) > png_struct_size) + { + png_destroy_struct(png_ptr); + *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); + png_ptr = *ptr_ptr; + } + + /* reset all variables to 0 */ + png_memset(png_ptr, 0, png_sizeof (png_struct)); + +#ifdef PNG_SETJMP_SUPPORTED + /* restore jump buffer */ + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); +#endif + + /* added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max=PNG_USER_WIDTH_MAX; + png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; +#endif + + /* initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + switch (inflateInit(&png_ptr->zstream)) + { + case Z_OK: /* Do nothing */ break; + case Z_MEM_ERROR: + case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break; + case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break; + default: png_error(png_ptr, "Unknown zlib error"); + } + + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); +} + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. This has been + * changed in v0.90 to allow reading a file that already has the magic + * bytes read from the stream. You can tell libpng how many bytes have + * been read from the beginning of the stream (up to the maximum of 8) + * via png_set_sig_bytes(), and we will only check the remaining bytes + * here. The application can then have access to the signature bytes we + * read if it is determined that this isn't a valid PNG file. + */ +void PNGAPI +png_read_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_info\n"); + /* If we haven't checked all of the PNG signature bytes, do so now. */ + if (png_ptr->sig_bytes < 8) + { + png_size_t num_checked = png_ptr->sig_bytes, + num_to_check = 8 - num_checked; + + png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); + png_ptr->sig_bytes = 8; + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + if (num_checked < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; + } + + for(;;) + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#if defined(PNG_READ_bKGD_SUPPORTED) + PNG_bKGD; +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + PNG_cHRM; +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + PNG_gAMA; +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + PNG_hIST; +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + PNG_iCCP; +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + PNG_iTXt; +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + PNG_oFFs; +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + PNG_pCAL; +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + PNG_pHYs; +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + PNG_sBIT; +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + PNG_sCAL; +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + PNG_sPLT; +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + PNG_sRGB; +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + PNG_tEXt; +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + PNG_tIME; +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + PNG_tRNS; +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + PNG_zTXt; +#endif +#endif /* PNG_GLOBAL_ARRAYS */ + png_byte chunk_length[4]; + png_uint_32 length; + + png_read_data(png_ptr, chunk_length, 4); + length = png_get_uint_31(png_ptr,chunk_length); + + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + + png_debug2(0, "Reading %s chunk, length=%lu.\n", png_ptr->chunk_name, + length); + + /* This should be a binary subdivision search or a hash for + * matching the chunk name rather than a linear search. + */ + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) + { + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + break; + } + } +#endif + else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + png_ptr->idat_size = length; + png_ptr->mode |= PNG_HAVE_IDAT; + break; + } +#if defined(PNG_READ_bKGD_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + else + png_handle_unknown(png_ptr, info_ptr, length); + } +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +/* optional call to update the users info_ptr structure */ +void PNGAPI +png_read_update_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_update_info\n"); + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + else + png_warning(png_ptr, + "Ignoring extra png_read_update_info() call; row buffer not reallocated"); + png_read_transform_info(png_ptr, info_ptr); +} + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Initialize palette, background, etc, after transformations + * are set, but before any reading takes place. This allows + * the user to obtain a gamma-corrected palette, for example. + * If the user doesn't call this, we will do it ourselves. + */ +void PNGAPI +png_start_read_image(png_structp png_ptr) +{ + png_debug(1, "in png_start_read_image\n"); + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +void PNGAPI +png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IDAT; + const int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; + const int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; +#endif + int ret; + png_debug2(1, "in png_read_row (row %lu, pass %d)\n", + png_ptr->row_number, png_ptr->pass); + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* check for transforms that have been set but were defined out */ +#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && !defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined."); +#endif + } + +#if defined(PNG_READ_INTERLACING_SUPPORTED) + /* if interlaced and we do not need a new row, combine row and return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + if (dsp_row != NULL && (png_ptr->row_number & 4)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 3: + if ((png_ptr->row_number & 3) || png_ptr->width < 3) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 4: + if ((png_ptr->row_number & 3) != 2) + { + if (dsp_row != NULL && (png_ptr->row_number & 2)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 5: + if ((png_ptr->row_number & 1) || png_ptr->width < 2) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 6: + if (!(png_ptr->row_number & 1)) + { + png_read_finish_row(png_ptr); + return; + } + break; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "Invalid attempt to read row data"); + + png_ptr->zstream.next_out = png_ptr->row_buf; + png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; + do + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_byte chunk_length[4]; + + png_crc_finish(png_ptr, 0); + + png_read_data(png_ptr, chunk_length, 4); + png_ptr->idat_size = png_get_uint_31(png_ptr,chunk_length); + + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, + (png_size_t)png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret == Z_STREAM_END) + { + if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_error(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression error"); + + } while (png_ptr->zstream.avail_out); + + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + if(png_ptr->row_buf[0]) + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, + png_ptr->rowbytes + 1); + +#if defined(PNG_MNG_FEATURES_SUPPORTED) + if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + if (png_ptr->transformations) + png_do_read_transformations(png_ptr); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) + /* blow up interlaced rows to full size */ + if (png_ptr->interlaced && + (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) +/* old interface (pre-1.0.9): + png_do_read_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + if (row != NULL) + png_combine_row(png_ptr, row, + png_pass_mask[png_ptr->pass]); + } + else +#endif + { + if (row != NULL) + png_combine_row(png_ptr, row, 0xff); + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 0xff); + } + png_read_finish_row(png_ptr); + + if (png_ptr->read_row_fn != NULL) + (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. If the image is interlaced, + * and png_set_interlace_handling() has been called, the rows need to + * contain the contents of the rows from the previous pass. If the + * image has alpha or transparency, and png_handle_alpha()[*] has been + * called, the rows contents must be initialized to the contents of the + * screen. + * + * "row" holds the actual image, and pixels are placed in it + * as they arrive. If the image is displayed after each pass, it will + * appear to "sparkle" in. "display_row" can be used to display a + * "chunky" progressive image, with finer detail added as it becomes + * available. If you do not want this "chunky" display, you may pass + * NULL for display_row. If you do not want the sparkle display, and + * you have not called png_handle_alpha(), you may pass NULL for rows. + * If you have called png_handle_alpha(), and the image has either an + * alpha channel or a transparency chunk, you must provide a buffer for + * rows. In this case, you do not have to provide a display_row buffer + * also, but you may. If the image is not interlaced, or if you have + * not called png_set_interlace_handling(), the display_row buffer will + * be ignored, so pass NULL to it. + * + * [*] png_handle_alpha() does not exist yet, as of libpng version 1.2.7 + */ + +void PNGAPI +png_read_rows(png_structp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows) +{ + png_uint_32 i; + png_bytepp rp; + png_bytepp dp; + + png_debug(1, "in png_read_rows\n"); + rp = row; + dp = display_row; + if (rp != NULL && dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp++; + png_bytep dptr = *dp++; + + png_read_row(png_ptr, rptr, dptr); + } + else if(rp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp; + png_read_row(png_ptr, rptr, png_bytep_NULL); + rp++; + } + else if(dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep dptr = *dp; + png_read_row(png_ptr, png_bytep_NULL, dptr); + dp++; + } +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Read the entire image. If the image has an alpha channel or a tRNS + * chunk, and you have called png_handle_alpha()[*], you will need to + * initialize the image to the current image that PNG will be overlaying. + * We set the num_rows again here, in case it was incorrectly set in + * png_read_start_row() by a call to png_read_update_info() or + * png_start_read_image() if png_set_interlace_handling() wasn't called + * prior to either of these functions like it should have been. You can + * only call this function once. If you desire to have an image for + * each pass of a interlaced image, use png_read_rows() instead. + * + * [*] png_handle_alpha() does not exist yet, as of libpng version 1.2.7 + */ +void PNGAPI +png_read_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i,image_height; + int pass, j; + png_bytepp rp; + + png_debug(1, "in png_read_image\n"); + +#ifdef PNG_READ_INTERLACING_SUPPORTED + pass = png_set_interlace_handling(png_ptr); +#else + if (png_ptr->interlaced) + png_error(png_ptr, + "Cannot read interlaced image -- interlace handler disabled."); + pass = 1; +#endif + + + image_height=png_ptr->height; + png_ptr->num_rows = image_height; /* Make sure this is set correctly */ + + for (j = 0; j < pass; j++) + { + rp = image; + for (i = 0; i < image_height; i++) + { + png_read_row(png_ptr, *rp, png_bytep_NULL); + rp++; + } + } +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. Will not read past the end of the + * file, will verify the end is accurate, and will read any comments + * or time information at the end of the file, if info is not NULL. + */ +void PNGAPI +png_read_end(png_structp png_ptr, png_infop info_ptr) +{ + png_byte chunk_length[4]; + png_uint_32 length; + + png_debug(1, "in png_read_end\n"); + png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */ + + do + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#if defined(PNG_READ_bKGD_SUPPORTED) + PNG_bKGD; +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + PNG_cHRM; +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + PNG_gAMA; +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + PNG_hIST; +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + PNG_iCCP; +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + PNG_iTXt; +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + PNG_oFFs; +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + PNG_pCAL; +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + PNG_pHYs; +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + PNG_sBIT; +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + PNG_sCAL; +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + PNG_sPLT; +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + PNG_sRGB; +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + PNG_tEXt; +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + PNG_tIME; +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + PNG_tRNS; +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + PNG_zTXt; +#endif +#endif /* PNG_GLOBAL_ARRAYS */ + + png_read_data(png_ptr, chunk_length, 4); + length = png_get_uint_31(png_ptr,chunk_length); + + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + + png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name); + + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) + { + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT) + png_error(png_ptr, "Too many IDAT's found"); + } + else + png_ptr->mode |= PNG_AFTER_IDAT; + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + } +#endif + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + /* Zero length IDATs are legal after the last IDAT has been + * read, but not after other chunks have been read. + */ + if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT) + png_error(png_ptr, "Too many IDAT's found"); + png_crc_finish(png_ptr, length); + } + else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); +#if defined(PNG_READ_bKGD_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + else + png_handle_unknown(png_ptr, info_ptr, length); + } while (!(png_ptr->mode & PNG_HAVE_IEND)); +} +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ + +/* free all memory used by the read */ +void PNGAPI +png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, + png_infopp end_info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL, end_info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; + png_voidp mem_ptr; +#endif + + png_debug(1, "in png_destroy_read_struct\n"); + if (png_ptr_ptr != NULL) + png_ptr = *png_ptr_ptr; + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (end_info_ptr_ptr != NULL) + end_info_ptr = *end_info_ptr_ptr; + +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + + png_read_destroy(png_ptr, info_ptr, end_info_ptr); + + if (info_ptr != NULL) + { +#if defined(PNG_TEXT_SUPPORTED) + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1); +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } + + if (end_info_ptr != NULL) + { +#if defined(PNG_READ_TEXT_SUPPORTED) + png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1); +#endif +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)end_info_ptr); +#endif + *end_info_ptr_ptr = NULL; + } + + if (png_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = NULL; + } +} + +/* free all memory used by the read (old method) */ +void /* PRIVATE */ +png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; +#endif + png_error_ptr error_fn; + png_error_ptr warning_fn; + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_read_destroy\n"); + if (info_ptr != NULL) + png_info_destroy(png_ptr, info_ptr); + + if (end_info_ptr != NULL) + png_info_destroy(png_ptr, end_info_ptr); + + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->big_row_buf); + png_free(png_ptr, png_ptr->prev_row); +#if defined(PNG_READ_DITHER_SUPPORTED) + png_free(png_ptr, png_ptr->palette_lookup); + png_free(png_ptr, png_ptr->dither_index); +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) + png_free(png_ptr, png_ptr->gamma_table); +#endif +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + png_free(png_ptr, png_ptr->gamma_from_1); + png_free(png_ptr, png_ptr->gamma_to_1); +#endif +#ifdef PNG_FREE_ME_SUPPORTED + if (png_ptr->free_me & PNG_FREE_PLTE) + png_zfree(png_ptr, png_ptr->palette); + png_ptr->free_me &= ~PNG_FREE_PLTE; +#else + if (png_ptr->flags & PNG_FLAG_FREE_PLTE) + png_zfree(png_ptr, png_ptr->palette); + png_ptr->flags &= ~PNG_FLAG_FREE_PLTE; +#endif +#if defined(PNG_tRNS_SUPPORTED) || \ + defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) +#ifdef PNG_FREE_ME_SUPPORTED + if (png_ptr->free_me & PNG_FREE_TRNS) + png_free(png_ptr, png_ptr->trans); + png_ptr->free_me &= ~PNG_FREE_TRNS; +#else + if (png_ptr->flags & PNG_FLAG_FREE_TRNS) + png_free(png_ptr, png_ptr->trans); + png_ptr->flags &= ~PNG_FLAG_FREE_TRNS; +#endif +#endif +#if defined(PNG_READ_hIST_SUPPORTED) +#ifdef PNG_FREE_ME_SUPPORTED + if (png_ptr->free_me & PNG_FREE_HIST) + png_free(png_ptr, png_ptr->hist); + png_ptr->free_me &= ~PNG_FREE_HIST; +#else + if (png_ptr->flags & PNG_FLAG_FREE_HIST) + png_free(png_ptr, png_ptr->hist); + png_ptr->flags &= ~PNG_FLAG_FREE_HIST; +#endif +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (png_ptr->gamma_16_table != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_table[i]); + } + png_free(png_ptr, png_ptr->gamma_16_table); + } +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_from_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_from_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_from_1); + } + if (png_ptr->gamma_16_to_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_to_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_to_1); + } +#endif +#endif +#if defined(PNG_TIME_RFC1123_SUPPORTED) + png_free(png_ptr, png_ptr->time_buffer); +#endif + + inflateEnd(&png_ptr->zstream); +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_free(png_ptr, png_ptr->save_buffer); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +#ifdef PNG_TEXT_SUPPORTED + png_free(png_ptr, png_ptr->current_text); +#endif /* PNG_TEXT_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + + /* Save the important info out of the png_struct, in case it is + * being used again. + */ +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; + warning_fn = png_ptr->warning_fn; + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, png_sizeof (png_struct)); + + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; + png_ptr->error_ptr = error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr->free_fn = free_fn; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); +#endif + +} + +void PNGAPI +png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn) +{ + png_ptr->read_row_fn = read_row_fn; +} + + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +#if defined(PNG_INFO_IMAGE_SUPPORTED) +void PNGAPI +png_read_png(png_structp png_ptr, png_infop info_ptr, + int transforms, + voidp params) +{ + int row; + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) + /* invert the alpha channel from opacity to transparency + */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + + /* png_read_info() gives us all of the information from the + * PNG file before the first IDAT (image data chunk). + */ + png_read_info(png_ptr, info_ptr); + if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) + png_error(png_ptr,"Image is too high to process with png_read_png()"); + + /* -------------- image transformations start here ------------------- */ + +#if defined(PNG_READ_16_TO_8_SUPPORTED) + /* tell libpng to strip 16 bit/color files down to 8 bits per color + */ + if (transforms & PNG_TRANSFORM_STRIP_16) + png_set_strip_16(png_ptr); +#endif + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) + /* Strip alpha bytes from the input data without combining with + * the background (not recommended). + */ + if (transforms & PNG_TRANSFORM_STRIP_ALPHA) + png_set_strip_alpha(png_ptr); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) + /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + /* Change the order of packed pixels to least significant bit first + * (not useful if you are using png_set_packing). + */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) + /* Expand paletted colors into true RGB triplets + * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel + * Expand paletted or RGB images with transparency to full alpha + * channels so the data will be available as RGBA quartets. + */ + if (transforms & PNG_TRANSFORM_EXPAND) + if ((png_ptr->bit_depth < 8) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || + (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) + png_set_expand(png_ptr); +#endif + + /* We don't handle background color or gamma transformation or dithering. + */ + +#if defined(PNG_READ_INVERT_SUPPORTED) + /* invert monochrome files to have 0 as white and 1 as black + */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) + /* If you want to shift the pixel values from the range [0,255] or + * [0,65535] to the original [0,7] or [0,31], or whatever range the + * colors were originally in: + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) + { + png_color_8p sig_bit; + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + png_set_shift(png_ptr, sig_bit); + } +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) + /* flip the RGB pixels to BGR (or RGBA to BGRA) + */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) + /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) + */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) + /* swap bytes of 16 bit files to least significant byte first + */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + + /* We don't handle adding filler bytes */ + + /* Optional call to gamma correct and add the background to the palette + * and update info structure. REQUIRED if you are expecting libpng to + * update the palette for you (i.e., you selected such a transform above). + */ + png_read_update_info(png_ptr, info_ptr); + + /* -------------- image transformations end here ------------------- */ + +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); +#endif + if(info_ptr->row_pointers == NULL) + { + info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, + info_ptr->height * png_sizeof(png_bytep)); +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_ROWS; +#endif + for (row = 0; row < (int)info_ptr->height; row++) + { + info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr)); + } + } + + png_read_image(png_ptr, info_ptr->row_pointers); + info_ptr->valid |= PNG_INFO_IDAT; + + /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(png_ptr, info_ptr); + + if(transforms == 0 || params == NULL) + /* quiet compiler warnings */ return; + +} +#endif +#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ diff --git a/Utilities/FLTK/png/pngrio.c b/Utilities/FLTK/png/pngrio.c new file mode 100644 index 0000000000..d7675eb623 --- /dev/null +++ b/Utilities/FLTK/png/pngrio.c @@ -0,0 +1,161 @@ + +/* pngrio.c - functions for data input + * + * libpng 1.2.7 - September 12, 2004 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file provides a location for all input. Users who need + * special handling are expected to write a function that has the same + * arguments as this and performs a similar function, but that possibly + * has a different input method. Note that you shouldn't change this + * function, but rather write a replacement function and then make + * libpng use it at run time with png_set_read_fn(...). + */ + +#define PNG_INTERNAL +#include "png.h" + +/* Read the data from whatever input you are using. The default routine + reads from a file pointer. Note that this routine sometimes gets called + with very small lengths, so you should implement some kind of simple + buffering if you are using unbuffered reads. This should never be asked + to read more then 64K on a 16 bit machine. */ +void /* PRIVATE */ +png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_debug1(4,"reading %d bytes\n", (int)length); + if (png_ptr->read_data_fn != NULL) + (*(png_ptr->read_data_fn))(png_ptr, data, length); + else + png_error(png_ptr, "Call to NULL read function"); +} + +#if !defined(PNG_NO_STDIO) +/* This is the function that does the actual reading of data. If you are + not reading from a standard C stream, you should create a replacement + read_data function and use it at run time with png_set_read_fn(), rather + than changing the library. */ +#ifndef USE_FAR_KEYWORD +void PNGAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ +#if defined(_WIN32_WCE) + if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) + check = 0; +#else + check = (png_size_t)fread(data, (png_size_t)1, length, + (png_FILE_p)png_ptr->io_ptr); +#endif + + if (check != length) + png_error(png_ptr, "Read Error"); +} +#else +/* this is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void /* PRIVATE */ +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + int check; + png_byte *n_data; + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + n_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)n_data == data) + { +#if defined(_WIN32_WCE) + if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) + check = 0; +#else + check = fread(n_data, 1, length, io_ptr); +#endif + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + do + { + read = MIN(NEAR_BUF_SIZE, remaining); +#if defined(_WIN32_WCE) + if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) ) + err = 0; +#else + err = fread(buf, (png_size_t)1, read, io_ptr); +#endif + png_memcpy(data, buf, read); /* copy far buffer to near buffer */ + if(err != read) + break; + else + check += err; + data += read; + remaining -= read; + } + while (remaining != 0); + } + if ((png_uint_32)check != (png_uint_32)length) + png_error(png_ptr, "read Error"); +} +#endif +#endif + +/* This function allows the application to supply a new input function + for libpng if standard C streams aren't being used. + + This function takes as its arguments: + png_ptr - pointer to a png input data structure + io_ptr - pointer to user supplied structure containing info about + the input functions. May be NULL. + read_data_fn - pointer to a new input function that takes as its + arguments a pointer to a png_struct, a pointer to + a location where input data can be stored, and a 32-bit + unsigned int that is the number of bytes to be read. + To exit and output any fatal error messages the new write + function should call png_error(png_ptr, "Error msg"). */ +void PNGAPI +png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn) +{ + png_ptr->io_ptr = io_ptr; + +#if !defined(PNG_NO_STDIO) + if (read_data_fn != NULL) + png_ptr->read_data_fn = read_data_fn; + else + png_ptr->read_data_fn = png_default_read_data; +#else + png_ptr->read_data_fn = read_data_fn; +#endif + + /* It is an error to write to a read device */ + if (png_ptr->write_data_fn != NULL) + { + png_ptr->write_data_fn = NULL; + png_warning(png_ptr, + "It's an error to set both read_data_fn and write_data_fn in the "); + png_warning(png_ptr, + "same structure. Resetting write_data_fn to NULL."); + } + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) + png_ptr->output_flush_fn = NULL; +#endif +} diff --git a/Utilities/FLTK/png/pngrtran.c b/Utilities/FLTK/png/pngrtran.c new file mode 100644 index 0000000000..cc7d4ff5c5 --- /dev/null +++ b/Utilities/FLTK/png/pngrtran.c @@ -0,0 +1,4177 @@ + +/* pngrtran.c - transforms the data in a row for PNG readers + * + * libpng version 1.2.7 - September 12, 2004 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file contains functions optionally called by an application + * in order to tell libpng how to handle data when reading a PNG. + * Transformations that are used in both reading and writing are + * in pngtrans.c. + */ + +#define PNG_INTERNAL +#include "png.h" + +/* Set the action on getting a CRC error for an ancillary or critical chunk. */ +void PNGAPI +png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action) +{ + png_debug(1, "in png_set_crc_action\n"); + /* Tell libpng how we react to CRC errors in critical chunks */ + switch (crit_action) + { + case PNG_CRC_NO_CHANGE: /* leave setting as is */ + break; + case PNG_CRC_WARN_USE: /* warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; + break; + case PNG_CRC_QUIET_USE: /* quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | + PNG_FLAG_CRC_CRITICAL_IGNORE; + break; + case PNG_CRC_WARN_DISCARD: /* not a valid action for critical data */ + png_warning(png_ptr, "Can't discard critical data on CRC error."); + case PNG_CRC_ERROR_QUIT: /* error/quit */ + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + break; + } + + switch (ancil_action) + { + case PNG_CRC_NO_CHANGE: /* leave setting as is */ + break; + case PNG_CRC_WARN_USE: /* warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; + break; + case PNG_CRC_QUIET_USE: /* quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | + PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + case PNG_CRC_ERROR_QUIT: /* error/quit */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + case PNG_CRC_WARN_DISCARD: /* warn/discard data */ + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + break; + } +} + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(PNG_FLOATING_POINT_SUPPORTED) +/* handle alpha and tRNS via a background color */ +void PNGAPI +png_set_background(png_structp png_ptr, + png_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma) +{ + png_debug(1, "in png_set_background\n"); + if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) + { + png_warning(png_ptr, "Application must supply a known background gamma"); + return; + } + + png_ptr->transformations |= PNG_BACKGROUND; + png_memcpy(&(png_ptr->background), background_color, + png_sizeof(png_color_16)); + png_ptr->background_gamma = (float)background_gamma; + png_ptr->background_gamma_type = (png_byte)(background_gamma_code); + png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0); + + /* Note: if need_expand is set and color_type is either RGB or RGB_ALPHA + * (in which case need_expand is superfluous anyway), the background color + * might actually be gray yet not be flagged as such. This is not a problem + * for the current code, which uses PNG_BACKGROUND_IS_GRAY only to + * decide when to do the png_do_gray_to_rgb() transformation. + */ + if ((need_expand && !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) || + (!need_expand && background_color->red == background_color->green && + background_color->red == background_color->blue)) + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; +} +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +/* strip 16 bit depth files to 8 bit depth */ +void PNGAPI +png_set_strip_16(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_16\n"); + png_ptr->transformations |= PNG_16_TO_8; +} +#endif + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +void PNGAPI +png_set_strip_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_alpha\n"); + png_ptr->transformations |= PNG_STRIP_ALPHA; +} +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +/* Dither file to 8 bit. Supply a palette, the current number + * of elements in the palette, the maximum number of elements + * allowed, and a histogram if possible. If the current number + * of colors is greater then the maximum number, the palette will be + * modified to fit in the maximum number. "full_dither" indicates + * whether we need a dithering cube set up for RGB images, or if we + * simply are reducing the number of colors in a paletted image. + */ + +typedef struct png_dsort_struct +{ + struct png_dsort_struct FAR * next; + png_byte left; + png_byte right; +} png_dsort; +typedef png_dsort FAR * png_dsortp; +typedef png_dsort FAR * FAR * png_dsortpp; + +void PNGAPI +png_set_dither(png_structp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_uint_16p histogram, + int full_dither) +{ + png_debug(1, "in png_set_dither\n"); + png_ptr->transformations |= PNG_DITHER; + + if (!full_dither) + { + int i; + + png_ptr->dither_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof (png_byte))); + for (i = 0; i < num_palette; i++) + png_ptr->dither_index[i] = (png_byte)i; + } + + if (num_palette > maximum_colors) + { + if (histogram != NULL) + { + /* This is easy enough, just throw out the least used colors. + Perhaps not the best solution, but good enough. */ + + int i; + + /* initialize an array to sort colors */ + png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof (png_byte))); + + /* initialize the dither_sort array */ + for (i = 0; i < num_palette; i++) + png_ptr->dither_sort[i] = (png_byte)i; + + /* Find the least used palette entries by starting a + bubble sort, and running it until we have sorted + out enough colors. Note that we don't care about + sorting all the colors, just finding which are + least used. */ + + for (i = num_palette - 1; i >= maximum_colors; i--) + { + int done; /* to stop early if the list is pre-sorted */ + int j; + + done = 1; + for (j = 0; j < i; j++) + { + if (histogram[png_ptr->dither_sort[j]] + < histogram[png_ptr->dither_sort[j + 1]]) + { + png_byte t; + + t = png_ptr->dither_sort[j]; + png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1]; + png_ptr->dither_sort[j + 1] = t; + done = 0; + } + } + if (done) + break; + } + + /* swap the palette around, and set up a table, if necessary */ + if (full_dither) + { + int j = num_palette; + + /* put all the useful colors within the max, but don't + move the others */ + for (i = 0; i < maximum_colors; i++) + { + if ((int)png_ptr->dither_sort[i] >= maximum_colors) + { + do + j--; + while ((int)png_ptr->dither_sort[j] >= maximum_colors); + palette[i] = palette[j]; + } + } + } + else + { + int j = num_palette; + + /* move all the used colors inside the max limit, and + develop a translation table */ + for (i = 0; i < maximum_colors; i++) + { + /* only move the colors we need to */ + if ((int)png_ptr->dither_sort[i] >= maximum_colors) + { + png_color tmp_color; + + do + j--; + while ((int)png_ptr->dither_sort[j] >= maximum_colors); + + tmp_color = palette[j]; + palette[j] = palette[i]; + palette[i] = tmp_color; + /* indicate where the color went */ + png_ptr->dither_index[j] = (png_byte)i; + png_ptr->dither_index[i] = (png_byte)j; + } + } + + /* find closest color for those colors we are not using */ + for (i = 0; i < num_palette; i++) + { + if ((int)png_ptr->dither_index[i] >= maximum_colors) + { + int min_d, k, min_k, d_index; + + /* find the closest color to one we threw out */ + d_index = png_ptr->dither_index[i]; + min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); + for (k = 1, min_k = 0; k < maximum_colors; k++) + { + int d; + + d = PNG_COLOR_DIST(palette[d_index], palette[k]); + + if (d < min_d) + { + min_d = d; + min_k = k; + } + } + /* point to closest color */ + png_ptr->dither_index[i] = (png_byte)min_k; + } + } + } + png_free(png_ptr, png_ptr->dither_sort); + png_ptr->dither_sort=NULL; + } + else + { + /* This is much harder to do simply (and quickly). Perhaps + we need to go through a median cut routine, but those + don't always behave themselves with only a few colors + as input. So we will just find the closest two colors, + and throw out one of them (chosen somewhat randomly). + [We don't understand this at all, so if someone wants to + work on improving it, be our guest - AED, GRP] + */ + int i; + int max_d; + int num_new_palette; + png_dsortp t; + png_dsortpp hash; + + t=NULL; + + /* initialize palette index arrays */ + png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof (png_byte))); + png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof (png_byte))); + + /* initialize the sort array */ + for (i = 0; i < num_palette; i++) + { + png_ptr->index_to_palette[i] = (png_byte)i; + png_ptr->palette_to_index[i] = (png_byte)i; + } + + hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 * + png_sizeof (png_dsortp))); + for (i = 0; i < 769; i++) + hash[i] = NULL; +/* png_memset(hash, 0, 769 * png_sizeof (png_dsortp)); */ + + num_new_palette = num_palette; + + /* initial wild guess at how far apart the farthest pixel + pair we will be eliminating will be. Larger + numbers mean more areas will be allocated, Smaller + numbers run the risk of not saving enough data, and + having to do this all over again. + + I have not done extensive checking on this number. + */ + max_d = 96; + + while (num_new_palette > maximum_colors) + { + for (i = 0; i < num_new_palette - 1; i++) + { + int j; + + for (j = i + 1; j < num_new_palette; j++) + { + int d; + + d = PNG_COLOR_DIST(palette[i], palette[j]); + + if (d <= max_d) + { + + t = (png_dsortp)png_malloc_warn(png_ptr, + (png_uint_32)(png_sizeof(png_dsort))); + if (t == NULL) + break; + t->next = hash[d]; + t->left = (png_byte)i; + t->right = (png_byte)j; + hash[d] = t; + } + } + if (t == NULL) + break; + } + + if (t != NULL) + for (i = 0; i <= max_d; i++) + { + if (hash[i] != NULL) + { + png_dsortp p; + + for (p = hash[i]; p; p = p->next) + { + if ((int)png_ptr->index_to_palette[p->left] + < num_new_palette && + (int)png_ptr->index_to_palette[p->right] + < num_new_palette) + { + int j, next_j; + + if (num_new_palette & 0x01) + { + j = p->left; + next_j = p->right; + } + else + { + j = p->right; + next_j = p->left; + } + + num_new_palette--; + palette[png_ptr->index_to_palette[j]] + = palette[num_new_palette]; + if (!full_dither) + { + int k; + + for (k = 0; k < num_palette; k++) + { + if (png_ptr->dither_index[k] == + png_ptr->index_to_palette[j]) + png_ptr->dither_index[k] = + png_ptr->index_to_palette[next_j]; + if ((int)png_ptr->dither_index[k] == + num_new_palette) + png_ptr->dither_index[k] = + png_ptr->index_to_palette[j]; + } + } + + png_ptr->index_to_palette[png_ptr->palette_to_index + [num_new_palette]] = png_ptr->index_to_palette[j]; + png_ptr->palette_to_index[png_ptr->index_to_palette[j]] + = png_ptr->palette_to_index[num_new_palette]; + + png_ptr->index_to_palette[j] = (png_byte)num_new_palette; + png_ptr->palette_to_index[num_new_palette] = (png_byte)j; + } + if (num_new_palette <= maximum_colors) + break; + } + if (num_new_palette <= maximum_colors) + break; + } + } + + for (i = 0; i < 769; i++) + { + if (hash[i] != NULL) + { + png_dsortp p = hash[i]; + while (p) + { + t = p->next; + png_free(png_ptr, p); + p = t; + } + } + hash[i] = 0; + } + max_d += 96; + } + png_free(png_ptr, hash); + png_free(png_ptr, png_ptr->palette_to_index); + png_free(png_ptr, png_ptr->index_to_palette); + png_ptr->palette_to_index=NULL; + png_ptr->index_to_palette=NULL; + } + num_palette = maximum_colors; + } + if (png_ptr->palette == NULL) + { + png_ptr->palette = palette; + } + png_ptr->num_palette = (png_uint_16)num_palette; + + if (full_dither) + { + int i; + png_bytep distance; + int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS + + PNG_DITHER_BLUE_BITS; + int num_red = (1 << PNG_DITHER_RED_BITS); + int num_green = (1 << PNG_DITHER_GREEN_BITS); + int num_blue = (1 << PNG_DITHER_BLUE_BITS); + png_size_t num_entries = ((png_size_t)1 << total_bits); + + png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr, + (png_uint_32)(num_entries * png_sizeof (png_byte))); + + png_memset(png_ptr->palette_lookup, 0, num_entries * + png_sizeof (png_byte)); + + distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * + png_sizeof(png_byte))); + + png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); + + for (i = 0; i < num_palette; i++) + { + int ir, ig, ib; + int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS)); + int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS)); + int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS)); + + for (ir = 0; ir < num_red; ir++) + { + /* int dr = abs(ir - r); */ + int dr = ((ir > r) ? ir - r : r - ir); + int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS)); + + for (ig = 0; ig < num_green; ig++) + { + /* int dg = abs(ig - g); */ + int dg = ((ig > g) ? ig - g : g - ig); + int dt = dr + dg; + int dm = ((dr > dg) ? dr : dg); + int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS); + + for (ib = 0; ib < num_blue; ib++) + { + int d_index = index_g | ib; + /* int db = abs(ib - b); */ + int db = ((ib > b) ? ib - b : b - ib); + int dmax = ((dm > db) ? dm : db); + int d = dmax + dt + db; + + if (d < (int)distance[d_index]) + { + distance[d_index] = (png_byte)d; + png_ptr->palette_lookup[d_index] = (png_byte)i; + } + } + } + } + } + + png_free(png_ptr, distance); + } +} +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) +/* Transform the image from the file_gamma to the screen_gamma. We + * only do transformations on images where the file_gamma and screen_gamma + * are not close reciprocals, otherwise it slows things down slightly, and + * also needlessly introduces small errors. + * + * We will turn off gamma transformation later if no semitransparent entries + * are present in the tRNS array for palette images. We can't do it here + * because we don't necessarily have the tRNS chunk yet. + */ +void PNGAPI +png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) +{ + png_debug(1, "in png_set_gamma\n"); + if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) + png_ptr->transformations |= PNG_GAMMA; + png_ptr->gamma = (float)file_gamma; + png_ptr->screen_gamma = (float)scrn_gamma; +} +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) +/* Expand paletted images to RGB, expand grayscale images of + * less than 8-bit depth to 8-bit depth, and expand tRNS chunks + * to alpha channels. + */ +void PNGAPI +png_set_expand(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand\n"); + png_ptr->transformations |= PNG_EXPAND; +} + +/* GRR 19990627: the following three functions currently are identical + * to png_set_expand(). However, it is entirely reasonable that someone + * might wish to expand an indexed image to RGB but *not* expand a single, + * fully transparent palette entry to a full alpha channel--perhaps instead + * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace + * the transparent color with a particular RGB value, or drop tRNS entirely. + * IOW, a future version of the library may make the transformations flag + * a bit more fine-grained, with separate bits for each of these three + * functions. + * + * More to the point, these functions make it obvious what libpng will be + * doing, whereas "expand" can (and does) mean any number of things. + */ + +/* Expand paletted images to RGB. */ +void PNGAPI +png_set_palette_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand\n"); + png_ptr->transformations |= PNG_EXPAND; +} + +/* Expand grayscale images of less than 8-bit depth to 8 bits. */ +void PNGAPI +png_set_gray_1_2_4_to_8(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand\n"); + png_ptr->transformations |= PNG_EXPAND; +} + +/* Expand tRNS chunks to alpha channels. */ +void PNGAPI +png_set_tRNS_to_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand\n"); + png_ptr->transformations |= PNG_EXPAND; +} +#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +void PNGAPI +png_set_gray_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_gray_to_rgb\n"); + png_ptr->transformations |= PNG_GRAY_TO_RGB; +} +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +#if defined(PNG_FLOATING_POINT_SUPPORTED) +/* Convert a RGB image to a grayscale of the same width. This allows us, + * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. + */ + +void PNGAPI +png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, + double green) +{ + int red_fixed = (int)((float)red*100000.0 + 0.5); + int green_fixed = (int)((float)green*100000.0 + 0.5); + png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed); +} +#endif + +void PNGAPI +png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, + png_fixed_point red, png_fixed_point green) +{ + png_debug(1, "in png_set_rgb_to_gray\n"); + switch(error_action) + { + case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY; + break; + case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; + break; + case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; + } + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#if defined(PNG_READ_EXPAND_SUPPORTED) + png_ptr->transformations |= PNG_EXPAND; +#else + { + png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED."); + png_ptr->transformations &= ~PNG_RGB_TO_GRAY; + } +#endif + { + png_uint_16 red_int, green_int; + if(red < 0 || green < 0) + { + red_int = 6968; /* .212671 * 32768 + .5 */ + green_int = 23434; /* .715160 * 32768 + .5 */ + } + else if(red + green < 100000L) + { + red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); + green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); + } + else + { + png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); + red_int = 6968; + green_int = 23434; + } + png_ptr->rgb_to_gray_red_coeff = red_int; + png_ptr->rgb_to_gray_green_coeff = green_int; + png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(32768-red_int-green_int); + } +} +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +void PNGAPI +png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + read_user_transform_fn) +{ + png_debug(1, "in png_set_read_user_transform_fn\n"); +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->read_user_transform_fn = read_user_transform_fn; +#endif +#ifdef PNG_LEGACY_SUPPORTED + if(read_user_transform_fn) + png_warning(png_ptr, + "This version of libpng does not support user transforms"); +#endif +} +#endif + +/* Initialize everything needed for the read. This includes modifying + * the palette. + */ +void /* PRIVATE */ +png_init_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_init_read_transformations\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if(png_ptr != NULL) +#endif + { +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \ + || defined(PNG_READ_GAMMA_SUPPORTED) + int color_type = png_ptr->color_type; +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_EXPAND)) + { + if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ + { + /* expand background chunk. */ + switch (png_ptr->bit_depth) + { + case 1: + png_ptr->background.gray *= (png_uint_16)0xff; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + break; + case 2: + png_ptr->background.gray *= (png_uint_16)0x55; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + break; + case 4: + png_ptr->background.gray *= (png_uint_16)0x11; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + break; + case 8: + case 16: + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + break; + } + } + else if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_ptr->background.red = + png_ptr->palette[png_ptr->background.index].red; + png_ptr->background.green = + png_ptr->palette[png_ptr->background.index].green; + png_ptr->background.blue = + png_ptr->palette[png_ptr->background.index].blue; + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_ALPHA) + { +#if defined(PNG_READ_EXPAND_SUPPORTED) + if (!(png_ptr->transformations & PNG_EXPAND)) +#endif + { + /* invert the alpha channel (in tRNS) unless the pixels are + going to be expanded, in which case leave it for later */ + int i,istop; + istop=(int)png_ptr->num_trans; + for (i=0; i<istop; i++) + png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]); + } + } +#endif + + } + } +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) + png_ptr->background_1 = png_ptr->background; +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) + + if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0) + && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0) + < PNG_GAMMA_THRESHOLD)) + { + int i,k; + k=0; + for (i=0; i<png_ptr->num_trans; i++) + { + if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff) + k=1; /* partial transparency is present */ + } + if (k == 0) + png_ptr->transformations &= (~PNG_GAMMA); + } + + if (png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) + { + png_build_gamma_table(png_ptr); +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->transformations & PNG_BACKGROUND) + { + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + /* could skip if no transparency and + */ + png_color back, back_1; + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) + { + back.red = png_ptr->gamma_table[png_ptr->background.red]; + back.green = png_ptr->gamma_table[png_ptr->background.green]; + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; + + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; + } + else + { + double g, gs; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = 1.0; + break; + case PNG_BACKGROUND_GAMMA_FILE: + g = 1.0 / (png_ptr->gamma); + gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + break; + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = 1.0 / (png_ptr->background_gamma); + gs = 1.0 / (png_ptr->background_gamma * + png_ptr->screen_gamma); + break; + default: + g = 1.0; /* back_1 */ + gs = 1.0; /* back */ + } + + if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD) + { + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + } + else + { + back.red = (png_byte)(pow( + (double)png_ptr->background.red/255, gs) * 255.0 + .5); + back.green = (png_byte)(pow( + (double)png_ptr->background.green/255, gs) * 255.0 + .5); + back.blue = (png_byte)(pow( + (double)png_ptr->background.blue/255, gs) * 255.0 + .5); + } + + back_1.red = (png_byte)(pow( + (double)png_ptr->background.red/255, g) * 255.0 + .5); + back_1.green = (png_byte)(pow( + (double)png_ptr->background.green/255, g) * 255.0 + .5); + back_1.blue = (png_byte)(pow( + (double)png_ptr->background.blue/255, g) * 255.0 + .5); + } + for (i = 0; i < num_palette; i++) + { + if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff) + { + if (png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else /* if (png_ptr->trans[i] != 0xff) */ + { + png_byte v, w; + + v = png_ptr->gamma_to_1[palette[i].red]; + png_composite(w, v, png_ptr->trans[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].green]; + png_composite(w, v, png_ptr->trans[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].blue]; + png_composite(w, v, png_ptr->trans[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } + /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ + else + /* color_type != PNG_COLOR_TYPE_PALETTE */ + { + double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1); + double g = 1.0; + double gs = 1.0; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = 1.0; + break; + case PNG_BACKGROUND_GAMMA_FILE: + g = 1.0 / (png_ptr->gamma); + gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + break; + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = 1.0 / (png_ptr->background_gamma); + gs = 1.0 / (png_ptr->background_gamma * + png_ptr->screen_gamma); + break; + } + + png_ptr->background_1.gray = (png_uint_16)(pow( + (double)png_ptr->background.gray / m, g) * m + .5); + png_ptr->background.gray = (png_uint_16)(pow( + (double)png_ptr->background.gray / m, gs) * m + .5); + + if ((png_ptr->background.red != png_ptr->background.green) || + (png_ptr->background.red != png_ptr->background.blue) || + (png_ptr->background.red != png_ptr->background.gray)) + { + /* RGB or RGBA with color background */ + png_ptr->background_1.red = (png_uint_16)(pow( + (double)png_ptr->background.red / m, g) * m + .5); + png_ptr->background_1.green = (png_uint_16)(pow( + (double)png_ptr->background.green / m, g) * m + .5); + png_ptr->background_1.blue = (png_uint_16)(pow( + (double)png_ptr->background.blue / m, g) * m + .5); + png_ptr->background.red = (png_uint_16)(pow( + (double)png_ptr->background.red / m, gs) * m + .5); + png_ptr->background.green = (png_uint_16)(pow( + (double)png_ptr->background.green / m, gs) * m + .5); + png_ptr->background.blue = (png_uint_16)(pow( + (double)png_ptr->background.blue / m, gs) * m + .5); + } + else + { + /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ + png_ptr->background_1.red = png_ptr->background_1.green + = png_ptr->background_1.blue = png_ptr->background_1.gray; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + } + } + } + else + /* transformation does not include PNG_BACKGROUND */ +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + else +#endif +#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */ +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + /* No GAMMA transformation */ + if ((png_ptr->transformations & PNG_BACKGROUND) && + (color_type == PNG_COLOR_TYPE_PALETTE)) + { + int i; + int istop = (int)png_ptr->num_trans; + png_color back; + png_colorp palette = png_ptr->palette; + + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + + for (i = 0; i < istop; i++) + { + if (png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else if (png_ptr->trans[i] != 0xff) + { + /* The png_composite() macro is defined in png.h */ + png_composite(palette[i].red, palette[i].red, + png_ptr->trans[i], back.red); + png_composite(palette[i].green, palette[i].green, + png_ptr->trans[i], back.green); + png_composite(palette[i].blue, palette[i].blue, + png_ptr->trans[i], back.blue); + } + } + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + +#if defined(PNG_READ_SHIFT_SUPPORTED) + if ((png_ptr->transformations & PNG_SHIFT) && + (color_type == PNG_COLOR_TYPE_PALETTE)) + { + png_uint_16 i; + png_uint_16 istop = png_ptr->num_palette; + int sr = 8 - png_ptr->sig_bit.red; + int sg = 8 - png_ptr->sig_bit.green; + int sb = 8 - png_ptr->sig_bit.blue; + + if (sr < 0 || sr > 8) + sr = 0; + if (sg < 0 || sg > 8) + sg = 0; + if (sb < 0 || sb > 8) + sb = 0; + for (i = 0; i < istop; i++) + { + png_ptr->palette[i].red >>= sr; + png_ptr->palette[i].green >>= sg; + png_ptr->palette[i].blue >>= sb; + } + } +#endif /* PNG_READ_SHIFT_SUPPORTED */ + } +#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \ + && !defined(PNG_READ_BACKGROUND_SUPPORTED) + if(png_ptr) + return; +#endif +} + +/* Modify the info structure to reflect the transformations. The + * info should be updated so a PNG file could be written with it, + * assuming the transformations result in valid PNG data. + */ +void /* PRIVATE */ +png_read_transform_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_transform_info\n"); +#if defined(PNG_READ_EXPAND_SUPPORTED) + if (png_ptr->transformations & PNG_EXPAND) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans) + info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + else + info_ptr->color_type = PNG_COLOR_TYPE_RGB; + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } + else + { + if (png_ptr->num_trans) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + if (info_ptr->bit_depth < 8) + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } + } +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->transformations & PNG_BACKGROUND) + { + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; + info_ptr->num_trans = 0; + info_ptr->background = png_ptr->background; + } +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (png_ptr->transformations & PNG_GAMMA) + { +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->gamma = png_ptr->gamma; +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = png_ptr->int_gamma; +#endif + } +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) + if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16)) + info_ptr->bit_depth = 8; +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) + if (png_ptr->transformations & PNG_DITHER) + { + if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && + png_ptr->palette_lookup && info_ptr->bit_depth == 8) + { + info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; + } + } +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) + if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) + info_ptr->bit_depth = 8; +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + info_ptr->color_type |= PNG_COLOR_MASK_COLOR; +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; +#endif + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + else + info_ptr->channels = 1; + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_STRIP_ALPHA) + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; +#endif + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + +#if defined(PNG_READ_FILLER_SUPPORTED) + /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ + if ((png_ptr->transformations & PNG_FILLER) && + ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) + { + info_ptr->channels++; + /* if adding a true alpha channel not just filler */ +#if !defined(PNG_1_0_X) + if (png_ptr->transformations & PNG_ADD_ALPHA) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; +#endif + } +#endif + +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ +defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + if(png_ptr->transformations & PNG_USER_TRANSFORM) + { + if(info_ptr->bit_depth < png_ptr->user_transform_depth) + info_ptr->bit_depth = png_ptr->user_transform_depth; + if(info_ptr->channels < png_ptr->user_transform_channels) + info_ptr->channels = png_ptr->user_transform_channels; + } +#endif + + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * + info_ptr->bit_depth); + + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,info_ptr->width); + +#if !defined(PNG_READ_EXPAND_SUPPORTED) + if(png_ptr) + return; +#endif +} + +/* Transform the row. The order of transformations is significant, + * and is very touchy. If you add a transformation, take care to + * decide how it fits in with the other transformations here. + */ +void /* PRIVATE */ +png_do_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_read_transformations\n"); +#if !defined(PNG_USELESS_TESTS_SUPPORTED) + if (png_ptr->row_buf == NULL) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[50]; + + sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number, + png_ptr->pass); + png_error(png_ptr, msg); +#else + png_error(png_ptr, "NULL row buffer"); +#endif + } +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE) + { + png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette, png_ptr->trans, png_ptr->num_trans); + } + else + { + if (png_ptr->num_trans) + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->trans_values)); + else + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + NULL); + } + } +#endif + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_STRIP_ALPHA) + png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + PNG_FLAG_FILLER_AFTER); +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + { + int rgb_error = + png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1); + if(rgb_error) + { + png_ptr->rgb_to_gray_status=1; + if(png_ptr->transformations == PNG_RGB_TO_GRAY_WARN) + png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + if(png_ptr->transformations == PNG_RGB_TO_GRAY_ERR) + png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + } + } +#endif + +/* +From Andreas Dilger e-mail to png-implement, 26 March 1998: + + In most cases, the "simple transparency" should be done prior to doing + gray-to-RGB, or you will have to test 3x as many bytes to check if a + pixel is transparent. You would also need to make sure that the + transparency information is upgraded to RGB. + + To summarize, the current flow is: + - Gray + simple transparency -> compare 1 or 2 gray bytes and composite + with background "in place" if transparent, + convert to RGB if necessary + - Gray + alpha -> composite with gray background and remove alpha bytes, + convert to RGB if necessary + + To support RGB backgrounds for gray images we need: + - Gray + simple transparency -> convert to RGB + simple transparency, compare + 3 or 6 bytes and composite with background + "in place" if transparent (3x compare/pixel + compared to doing composite with gray bkgrnd) + - Gray + alpha -> convert to RGB + alpha, composite with background and + remove alpha bytes (3x float operations/pixel + compared with composite on gray background) + + Greg's change will do this. The reason it wasn't done before is for + performance, as this increases the per-pixel operations. If we would check + in advance if the background was gray or RGB, and position the gray-to-RGB + transform appropriately, then it would save a lot of work/time. + */ + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + /* if gray -> RGB, do so now only if background is non-gray; else do later + * for performance reasons */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if ((png_ptr->transformations & PNG_BACKGROUND) && + ((png_ptr->num_trans != 0 ) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) + png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->trans_values), &(png_ptr->background) +#if defined(PNG_READ_GAMMA_SUPPORTED) + , &(png_ptr->background_1), + png_ptr->gamma_table, png_ptr->gamma_from_1, + png_ptr->gamma_to_1, png_ptr->gamma_16_table, + png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1, + png_ptr->gamma_shift +#endif +); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) + if ((png_ptr->transformations & PNG_GAMMA) && +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + !((png_ptr->transformations & PNG_BACKGROUND) && + ((png_ptr->num_trans != 0) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && +#endif + (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) + png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->gamma_table, png_ptr->gamma_16_table, + png_ptr->gamma_shift); +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) + if (png_ptr->transformations & PNG_16_TO_8) + png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) + if (png_ptr->transformations & PNG_DITHER) + { + png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette_lookup, png_ptr->dither_index); + if(png_ptr->row_info.rowbytes == (png_uint_32)0) + png_error(png_ptr, "png_do_dither returned rowbytes=0"); + } +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + /* if gray -> RGB, do so now only if we did not do so above */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->filler, png_ptr->flags); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if(png_ptr->read_user_transform_fn != NULL) + (*(png_ptr->read_user_transform_fn)) /* user read transform function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_uint_32 rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + if(png_ptr->user_transform_depth) + png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; + if(png_ptr->user_transform_channels) + png_ptr->row_info.channels = png_ptr->user_transform_channels; +#endif + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + } +#endif + +} + +#if defined(PNG_READ_PACK_SUPPORTED) +/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, + * without changing the actual values. Thus, if you had a row with + * a bit depth of 1, you would end up with bytes that only contained + * the numbers 0 or 1. If you would rather they contain 0 and 255, use + * png_do_shift() after this. + */ +void /* PRIVATE */ +png_do_unpack(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_unpack\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL && row_info->bit_depth < 8) +#else + if (row_info->bit_depth < 8) +#endif + { + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + switch (row_info->bit_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x01); + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + case 2: + { + + png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x03); + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + case 4: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x0f); + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift = 4; + + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_width * row_info->channels; + } +} +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) +/* Reverse the effects of png_do_shift. This routine merely shifts the + * pixels back to their significant bits values. Thus, if you have + * a row of bit depth 8, but only 5 are significant, this will shift + * the values back to 0 through 31. + */ +void /* PRIVATE */ +png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) +{ + png_debug(1, "in png_do_unshift\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && sig_bits != NULL && +#endif + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift[4]; + int channels = 0; + int c; + png_uint_16 value = 0; + png_uint_32 row_width = row_info->width; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift[channels++] = row_info->bit_depth - sig_bits->red; + shift[channels++] = row_info->bit_depth - sig_bits->green; + shift[channels++] = row_info->bit_depth - sig_bits->blue; + } + else + { + shift[channels++] = row_info->bit_depth - sig_bits->gray; + } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift[channels++] = row_info->bit_depth - sig_bits->alpha; + } + + for (c = 0; c < channels; c++) + { + if (shift[c] <= 0) + shift[c] = 0; + else + value = 1; + } + + if (!value) + return; + + switch (row_info->bit_depth) + { + case 2: + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (bp = row, i = 0; i < istop; i++) + { + *bp >>= 1; + *bp++ &= 0x55; + } + break; + } + case 4: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) | + (png_byte)((int)0xf >> shift[0])); + + for (i = 0; i < istop; i++) + { + *bp >>= shift[0]; + *bp++ &= mask; + } + break; + } + case 8: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = row_width * channels; + + for (i = 0; i < istop; i++) + { + *bp++ >>= shift[i%channels]; + } + break; + } + case 16: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_width; + + for (i = 0; i < istop; i++) + { + value = (png_uint_16)((*bp << 8) + *(bp + 1)); + value >>= shift[i%channels]; + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + break; + } + } + } +} +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +/* chop rows of bit depth 16 down to 8 */ +void /* PRIVATE */ +png_do_chop(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_chop\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL && row_info->bit_depth == 16) +#else + if (row_info->bit_depth == 16) +#endif + { + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + png_uint_32 istop = row_info->width * row_info->channels; + + for (i = 0; i<istop; i++, sp += 2, dp++) + { +#if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED) + /* This does a more accurate scaling of the 16-bit color + * value, rather than a simple low-byte truncation. + * + * What the ideal calculation should be: + * *dp = (((((png_uint_32)(*sp) << 8) | + * (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L; + * + * GRR: no, I think this is what it really should be: + * *dp = (((((png_uint_32)(*sp) << 8) | + * (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L; + * + * GRR: here's the exact calculation with shifts: + * temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L; + * *dp = (temp - (temp >> 8)) >> 8; + * + * Approximate calculation with shift/add instead of multiply/divide: + * *dp = ((((png_uint_32)(*sp) << 8) | + * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8; + * + * What we actually do to avoid extra shifting and conversion: + */ + + *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); +#else + /* Simply discard the low order byte */ + *dp = *sp; +#endif + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_info->width * row_info->channels; + } +} +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) +void /* PRIVATE */ +png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_swap_alpha\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This converts from RGBA to ARGB */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + /* This converts from RRGGBBAA to AARRGGBB */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from GA to AG */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + /* This converts from GGAA to AAGG */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } + } + } +} +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) +void /* PRIVATE */ +png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_invert_alpha\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This inverts the alpha channel in RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=3; + dp=sp; + } + } + /* This inverts the alpha channel in RRGGBBAA */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=6; + dp=sp; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This inverts the alpha channel in GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = *(--sp); + } + } + /* This inverts the alpha channel in GGAA */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); +/* + *(--dp) = *(--sp); + *(--dp) = *(--sp); +*/ + sp-=2; + dp=sp; + } + } + } + } +} +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) +/* Add filler channel if we have RGB color */ +void /* PRIVATE */ +png_do_read_filler(png_row_infop row_info, png_bytep row, + png_uint_32 filler, png_uint_32 flags) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_byte hi_filler = (png_byte)((filler>>8) & 0xff); + png_byte lo_filler = (png_byte)(filler & 0xff); + + png_debug(1, "in png_do_read_filler\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if(row_info->bit_depth == 8) + { + /* This changes the data from G to GX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + /* This changes the data from G to XG */ + else + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + } + else if(row_info->bit_depth == 16) + { + /* This changes the data from GG to GGXX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + /* This changes the data from GG to XXGG */ + else + { + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + } /* COLOR_TYPE == GRAY */ + else if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if(row_info->bit_depth == 8) + { + /* This changes the data from RGB to RGBX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + /* This changes the data from RGB to XRGB */ + else + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + else if(row_info->bit_depth == 16) + { + /* This changes the data from RRGGBB to RRGGBBXX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + /* This changes the data from RRGGBB to XXRRGGBB */ + else + { + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + } + } /* COLOR_TYPE == RGB */ +} +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +/* expand grayscale files to RGB, with or without alpha */ +void /* PRIVATE */ +png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_debug(1, "in png_do_gray_to_rgb\n"); + if (row_info->bit_depth >= 8 && +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + !(row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + (png_size_t)row_width - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + else + { + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + else + { + png_bytep sp = row + (png_size_t)row_width * 4 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + row_info->channels += (png_byte)2; + row_info->color_type |= PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + } +} +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +/* reduce RGB files to grayscale, with or without alpha + * using the equation given in Poynton's ColorFAQ at + * <http://www.inforamp.net/~poynton/> + * Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net + * + * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + * + * We approximate this with + * + * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B + * + * which can be expressed with integers as + * + * Y = (6969 * R + 23434 * G + 2365 * B)/32768 + * + * The calculation is to be done in a linear colorspace. + * + * Other integer coefficents can be used via png_set_rgb_to_gray(). + */ +int /* PRIVATE */ +png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) + +{ + png_uint_32 i; + + png_uint_32 row_width = row_info->width; + int rgb_error = 0; + + png_debug(1, "in png_do_rgb_to_gray\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; + png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; + png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if(red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1[ + (rc*red+gc*green+bc*blue)>>15]; + } + else + *(dp++) = *(sp-1); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if(red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15); + } + else + *(dp++) = *(sp-1); + } + } + } + + else /* RGB bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if(red == green && red == blue) + w = red; + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 + + bc*blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if(red != green || red != blue) + rgb_error |= 1; + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + } + } + } + } + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if(red != green || red != blue) + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1 + [(rc*red + gc*green + bc*blue)>>15]; + *(dp++) = *(sp++); /* alpha */ + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if(red != green || red != blue) + rgb_error |= 1; + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = *(sp++); /* alpha */ + } + } + } + else /* RGBA bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if(red == green && red == blue) + w = red; + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc * red_1 + + gc * green_1 + bc * blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + if(red != green || red != blue) + rgb_error |= 1; + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + } + } + row_info->channels -= (png_byte)2; + row_info->color_type &= ~PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + } + return rgb_error; +} +#endif + +/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth + * large of png_color. This lets grayscale images be treated as + * paletted. Most useful for gamma correction and simplification + * of code. + */ +void PNGAPI +png_build_grayscale_palette(int bit_depth, png_colorp palette) +{ + int num_palette; + int color_inc; + int i; + int v; + + png_debug(1, "in png_do_build_grayscale_palette\n"); + if (palette == NULL) + return; + + switch (bit_depth) + { + case 1: + num_palette = 2; + color_inc = 0xff; + break; + case 2: + num_palette = 4; + color_inc = 0x55; + break; + case 4: + num_palette = 16; + color_inc = 0x11; + break; + case 8: + num_palette = 256; + color_inc = 1; + break; + default: + num_palette = 0; + color_inc = 0; + break; + } + + for (i = 0, v = 0; i < num_palette; i++, v += color_inc) + { + palette[i].red = (png_byte)v; + palette[i].green = (png_byte)v; + palette[i].blue = (png_byte)v; + } +} + +/* This function is currently unused. Do we really need it? */ +#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED) +void /* PRIVATE */ +png_correct_palette(png_structp png_ptr, png_colorp palette, + int num_palette) +{ + png_debug(1, "in png_correct_palette\n"); +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) + if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND)) + { + png_color back, back_1; + + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) + { + back.red = png_ptr->gamma_table[png_ptr->background.red]; + back.green = png_ptr->gamma_table[png_ptr->background.green]; + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; + + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; + } + else + { + double g; + + g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma); + + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN || + fabs(g - 1.0) < PNG_GAMMA_THRESHOLD) + { + back.red = png_ptr->background.red; + back.green = png_ptr->background.green; + back.blue = png_ptr->background.blue; + } + else + { + back.red = + (png_byte)(pow((double)png_ptr->background.red/255, g) * + 255.0 + 0.5); + back.green = + (png_byte)(pow((double)png_ptr->background.green/255, g) * + 255.0 + 0.5); + back.blue = + (png_byte)(pow((double)png_ptr->background.blue/255, g) * + 255.0 + 0.5); + } + + g = 1.0 / png_ptr->background_gamma; + + back_1.red = + (png_byte)(pow((double)png_ptr->background.red/255, g) * + 255.0 + 0.5); + back_1.green = + (png_byte)(pow((double)png_ptr->background.green/255, g) * + 255.0 + 0.5); + back_1.blue = + (png_byte)(pow((double)png_ptr->background.blue/255, g) * + 255.0 + 0.5); + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_uint_32 i; + + for (i = 0; i < (png_uint_32)num_palette; i++) + { + if (i < png_ptr->num_trans && png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff) + { + png_byte v, w; + + v = png_ptr->gamma_to_1[png_ptr->palette[i].red]; + png_composite(w, v, png_ptr->trans[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[png_ptr->palette[i].green]; + png_composite(w, v, png_ptr->trans[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[png_ptr->palette[i].blue]; + png_composite(w, v, png_ptr->trans[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } + else + { + int i; + + for (i = 0; i < num_palette; i++) + { + if (palette[i].red == (png_byte)png_ptr->trans_values.gray) + { + palette[i] = back; + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } + } + else +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (png_ptr->transformations & PNG_GAMMA) + { + int i; + + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + else +#endif +#endif +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->transformations & PNG_BACKGROUND) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_color back; + + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + + for (i = 0; i < (int)png_ptr->num_trans; i++) + { + if (png_ptr->trans[i] == 0) + { + palette[i].red = back.red; + palette[i].green = back.green; + palette[i].blue = back.blue; + } + else if (png_ptr->trans[i] != 0xff) + { + png_composite(palette[i].red, png_ptr->palette[i].red, + png_ptr->trans[i], back.red); + png_composite(palette[i].green, png_ptr->palette[i].green, + png_ptr->trans[i], back.green); + png_composite(palette[i].blue, png_ptr->palette[i].blue, + png_ptr->trans[i], back.blue); + } + } + } + else /* assume grayscale palette (what else could it be?) */ + { + int i; + + for (i = 0; i < num_palette; i++) + { + if (i == (png_byte)png_ptr->trans_values.gray) + { + palette[i].red = (png_byte)png_ptr->background.red; + palette[i].green = (png_byte)png_ptr->background.green; + palette[i].blue = (png_byte)png_ptr->background.blue; + } + } + } + } +#endif +} +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) +/* Replace any alpha or transparency with the supplied background color. + * "background" is already in the screen gamma, while "background_1" is + * at a gamma of 1.0. Paletted files have already been taken care of. + */ +void /* PRIVATE */ +png_do_background(png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background +#if defined(PNG_READ_GAMMA_SUPPORTED) + , png_color_16p background_1, + png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, + png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, + png_uint_16pp gamma_16_to_1, int gamma_shift +#endif + ) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + int shift; + + png_debug(1, "in png_do_background\n"); + if (background != NULL && +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || + (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_GRAY: + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row; + shift = 7; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x01) + == trans_values->gray) + { + *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 7; + sp++; + } + else + shift--; + } + break; + } + case 2: + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_values->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x03); + png_byte g = (png_byte)((gamma_table [p | (p << 2) | + (p << 4) | (p << 6)] >> 6) & 0x03); + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + if (!shift) + { + shift = 6; + sp++; + } + else + shift -= 2; + } + } + else +#endif + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_values->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 6; + sp++; + } + else + shift -= 2; + } + } + break; + } + case 4: + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_values->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x0f); + png_byte g = (png_byte)((gamma_table[p | + (p << 4)] >> 4) & 0x0f); + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + if (!shift) + { + shift = 4; + sp++; + } + else + shift -= 4; + } + } + else +#endif + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_values->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 4; + sp++; + } + else + shift -= 4; + } + } + break; + } + case 8: + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_values->gray) + { + *sp = (png_byte)background->gray; + } + else + { + *sp = gamma_table[*sp]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_values->gray) + { + *sp = (png_byte)background->gray; + } + } + } + break; + } + case 16: + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + if (v == trans_values->gray) + { + /* background is already in screen gamma */ + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + else + { + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + if (v == trans_values->gray) + { + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + } + } + break; + } + } + break; + } + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == trans_values->red && + *(sp + 1) == trans_values->green && + *(sp + 2) == trans_values->blue) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + else + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == trans_values->red && + *(sp + 1) == trans_values->green && + *(sp + 2) == trans_values->blue) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); + if (r == trans_values->red && g == trans_values->green && + b == trans_values->blue) + { + /* background is already in screen gamma */ + *sp = (png_byte)((background->red >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->red & 0xff); + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(sp + 3) = (png_byte)(background->green & 0xff); + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1)); + png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); + + if (r == trans_values->red && g == trans_values->green && + b == trans_values->blue) + { + *sp = (png_byte)((background->red >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->red & 0xff); + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(sp + 3) = (png_byte)(background->green & 0xff); + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(background->blue & 0xff); + } + } + } + } + break; + } + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + png_uint_16 a = *(sp + 1); + + if (a == 0xff) + { + *dp = gamma_table[*sp]; + } + else if (a == 0) + { + /* background is already in screen gamma */ + *dp = (png_byte)background->gray; + } + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->gray); + *dp = gamma_from_1[w]; + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + png_byte a = *(sp + 1); + + if (a == 0xff) + { + *dp = *sp; + } +#if defined(PNG_READ_GAMMA_SUPPORTED) + else if (a == 0) + { + *dp = (png_byte)background->gray; + } + else + { + png_composite(*dp, *sp, a, background_1->gray); + } +#else + *dp = (png_byte)background->gray; +#endif + } + } + } + else /* if (png_ptr->bit_depth == 16) */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + } +#if defined(PNG_READ_GAMMA_SUPPORTED) + else if (a == 0) +#else + else +#endif + { + /* background is already in screen gamma */ + *dp = (png_byte)((background->gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->gray & 0xff); + } +#if defined(PNG_READ_GAMMA_SUPPORTED) + else + { + png_uint_16 g, v, w; + + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(v, g, a, background_1->gray); + w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; + *dp = (png_byte)((w >> 8) & 0xff); + *(dp + 1) = (png_byte)(w & 0xff); + } +#endif + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + if (a == (png_uint_16)0xffff) + { + png_memcpy(dp, sp, 2); + } +#if defined(PNG_READ_GAMMA_SUPPORTED) + else if (a == 0) +#else + else +#endif + { + *dp = (png_byte)((background->gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->gray & 0xff); + } +#if defined(PNG_READ_GAMMA_SUPPORTED) + else + { + png_uint_16 g, v; + + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_composite_16(v, g, a, background_1->gray); + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + } +#endif + } + } + } + break; + } + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *dp = gamma_table[*sp]; + *(dp + 1) = gamma_table[*(sp + 1)]; + *(dp + 2) = gamma_table[*(sp + 2)]; + } + else if (a == 0) + { + /* background is already in screen gamma */ + *dp = (png_byte)background->red; + *(dp + 1) = (png_byte)background->green; + *(dp + 2) = (png_byte)background->blue; + } + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->red); + *dp = gamma_from_1[w]; + v = gamma_to_1[*(sp + 1)]; + png_composite(w, v, a, background_1->green); + *(dp + 1) = gamma_from_1[w]; + v = gamma_to_1[*(sp + 2)]; + png_composite(w, v, a, background_1->blue); + *(dp + 2) = gamma_from_1[w]; + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *dp = *sp; + *(dp + 1) = *(sp + 1); + *(dp + 2) = *(sp + 2); + } + else if (a == 0) + { + *dp = (png_byte)background->red; + *(dp + 1) = (png_byte)background->green; + *(dp + 2) = (png_byte)background->blue; + } + else + { + png_composite(*dp, *sp, a, background->red); + png_composite(*(dp + 1), *(sp + 1), a, + background->green); + png_composite(*(dp + 2), *(sp + 2), a, + background->blue); + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(dp + 2) = (png_byte)((v >> 8) & 0xff); + *(dp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(dp + 4) = (png_byte)((v >> 8) & 0xff); + *(dp + 5) = (png_byte)(v & 0xff); + } + else if (a == 0) + { + /* background is already in screen gamma */ + *dp = (png_byte)((background->red >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->red & 0xff); + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(dp + 3) = (png_byte)(background->green & 0xff); + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v, w, x; + + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(w, v, a, background_1->red); + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *dp = (png_byte)((x >> 8) & 0xff); + *(dp + 1) = (png_byte)(x & 0xff); + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + png_composite_16(w, v, a, background_1->green); + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *(dp + 2) = (png_byte)((x >> 8) & 0xff); + *(dp + 3) = (png_byte)(x & 0xff); + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + png_composite_16(w, v, a, background_1->blue); + x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; + *(dp + 4) = (png_byte)((x >> 8) & 0xff); + *(dp + 5) = (png_byte)(x & 0xff); + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + if (a == (png_uint_16)0xffff) + { + png_memcpy(dp, sp, 6); + } + else if (a == 0) + { + *dp = (png_byte)((background->red >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->red & 0xff); + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(dp + 3) = (png_byte)(background->green & 0xff); + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v; + + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + png_composite_16(v, r, a, background->red); + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + png_composite_16(v, g, a, background->green); + *(dp + 2) = (png_byte)((v >> 8) & 0xff); + *(dp + 3) = (png_byte)(v & 0xff); + png_composite_16(v, b, a, background->blue); + *(dp + 4) = (png_byte)((v >> 8) & 0xff); + *(dp + 5) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + } + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; + row_info->channels--; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + } + } +} +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) +/* Gamma correct the image, avoiding the alpha channel. Make sure + * you do this after you deal with the transparency issue on grayscale + * or RGB images. If your bit depth is 8, use gamma_table, if it + * is 16, use gamma_16_table and gamma_shift. Build these with + * build_gamma_table(). + */ +void /* PRIVATE */ +png_do_gamma(png_row_infop row_info, png_bytep row, + png_bytep gamma_table, png_uint_16pp gamma_16_table, + int gamma_shift) +{ + png_bytep sp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_gamma\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + ((row_info->bit_depth <= 8 && gamma_table != NULL) || + (row_info->bit_depth == 16 && gamma_16_table != NULL))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + sp++; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp += 2; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + case PNG_COLOR_TYPE_GRAY: + { + if (row_info->bit_depth == 2) + { + sp = row; + for (i = 0; i < row_width; i += 4) + { + int a = *sp & 0xc0; + int b = *sp & 0x30; + int c = *sp & 0x0c; + int d = *sp & 0x03; + + *sp = (png_byte)( + ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| + ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| + ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| + ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); + sp++; + } + } + if (row_info->bit_depth == 4) + { + sp = row; + for (i = 0; i < row_width; i += 2) + { + int msb = *sp & 0xf0; + int lsb = *sp & 0x0f; + + *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) + | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); + sp++; + } + } + else if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + } + } + else if (row_info->bit_depth == 16) + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + } + } +} +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) +/* Expands a palette row to an RGB or RGBA row depending + * upon whether you supply trans and num_trans. + */ +void /* PRIVATE */ +png_do_expand_palette(png_row_infop row_info, png_bytep row, + png_colorp palette, png_bytep trans, int num_trans) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand_palette\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 1; + else + *dp = 0; + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + case 2: + { + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)value; + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + case 4: + { + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((row_width & 0x01) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)value; + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift += 4; + + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + switch (row_info->bit_depth) + { + case 8: + { + if (trans != NULL) + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + + for (i = 0; i < row_width; i++) + { + if ((int)(*sp) >= num_trans) + *dp-- = 0xff; + else + *dp-- = trans[*sp]; + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + row_info->color_type = 6; + row_info->channels = 4; + } + else + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width * 3) - 1; + + for (i = 0; i < row_width; i++) + { + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + row_info->color_type = 2; + row_info->channels = 3; + } + break; + } + } + } +} + +/* If the bit depth < 8, it is expanded to 8. Also, if the + * transparency value is supplied, an alpha channel is built. + */ +void /* PRIVATE */ +png_do_expand(png_row_infop row_info, png_bytep row, + png_color_16p trans_value) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0); + + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + gray = (png_uint_16)(gray*0xff); + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 0xff; + else + *dp = 0; + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + case 2: + { + gray = (png_uint_16)(gray*0x55); + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)(value | (value << 2) | (value << 4) | + (value << 6)); + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + case 4: + { + gray = (png_uint_16)(gray*0x11); + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)(value | (value << 4)); + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift = 4; + + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (trans_value != NULL) + { + if (row_info->bit_depth == 8) + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (*sp == gray) + *dp-- = 0; + else + *dp-- = 0xff; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + sp = row + row_info->rowbytes - 1; + dp = row + (row_info->rowbytes << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (((png_uint_16)*(sp) | + ((png_uint_16)*(sp - 1) << 8)) == gray) + { + *dp-- = 0; + *dp-- = 0; + } + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + row_info->channels = 2; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_width); + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) + { + if (row_info->bit_depth == 8) + { + sp = row + (png_size_t)row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 2) == trans_value->red && + *(sp - 1) == trans_value->green && + *(sp - 0) == trans_value->blue) + *dp-- = 0; + else + *dp-- = 0xff; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + sp = row + row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 3) - 1; + for (i = 0; i < row_width; i++) + { + if ((((png_uint_16)*(sp - 4) | + ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) && + (((png_uint_16)*(sp - 2) | + ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) && + (((png_uint_16)*(sp - 0) | + ((png_uint_16)*(sp - 1) << 8)) == trans_value->blue)) + { + *dp-- = 0; + *dp-- = 0; + } + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + row_info->channels = 4; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + } + } +} +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +void /* PRIVATE */ +png_do_dither(png_row_infop row_info, png_bytep row, + png_bytep palette_lookup, png_bytep dither_lookup) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_dither\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB && + palette_lookup && row_info->bit_depth == 8) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + + /* this looks real messy, but the compiler will reduce + it down to a reasonable formula. For example, with + 5 bits per color, we get: + p = (((r >> 3) & 0x1f) << 10) | + (((g >> 3) & 0x1f) << 5) | + ((b >> 3) & 0x1f); + */ + p = (((r >> (8 - PNG_DITHER_RED_BITS)) & + ((1 << PNG_DITHER_RED_BITS) - 1)) << + (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | + (((g >> (8 - PNG_DITHER_GREEN_BITS)) & + ((1 << PNG_DITHER_GREEN_BITS) - 1)) << + (PNG_DITHER_BLUE_BITS)) | + ((b >> (8 - PNG_DITHER_BLUE_BITS)) & + ((1 << PNG_DITHER_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + palette_lookup != NULL && row_info->bit_depth == 8) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + sp++; + + p = (((r >> (8 - PNG_DITHER_RED_BITS)) & + ((1 << PNG_DITHER_RED_BITS) - 1)) << + (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | + (((g >> (8 - PNG_DITHER_GREEN_BITS)) & + ((1 << PNG_DITHER_GREEN_BITS) - 1)) << + (PNG_DITHER_BLUE_BITS)) | + ((b >> (8 - PNG_DITHER_BLUE_BITS)) & + ((1 << PNG_DITHER_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + } + else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && + dither_lookup && row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + *sp = dither_lookup[*sp]; + } + } + } +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +#if defined(PNG_READ_GAMMA_SUPPORTED) +static int png_gamma_shift[] = + {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0}; + +/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit + * tables, we don't make a full table if we are reducing to 8-bit in + * the future. Note also how the gamma_16 tables are segmented so that + * we don't need to allocate > 64K chunks for a full 16-bit table. + */ +void /* PRIVATE */ +png_build_gamma_table(png_structp png_ptr) +{ + png_debug(1, "in png_build_gamma_table\n"); + if(png_ptr->gamma != 0.0) + { + if (png_ptr->bit_depth <= 8) + { + int i; + double g; + + if (png_ptr->screen_gamma > .000001) + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + else + g = 1.0; + + png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + } + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) + { + + g = 1.0 / (png_ptr->gamma); + + png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + } + + + png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + if(png_ptr->screen_gamma > 0.000001) + g = 1.0 / png_ptr->screen_gamma; + else + g = png_ptr->gamma; /* probably doing rgb_to_gray */ + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + + } + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ + } + else + { + double g; + int i, j, shift, num; + int sig_bit; + png_uint_32 ig; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit = (int)png_ptr->sig_bit.red; + if ((int)png_ptr->sig_bit.green > sig_bit) + sig_bit = png_ptr->sig_bit.green; + if ((int)png_ptr->sig_bit.blue > sig_bit) + sig_bit = png_ptr->sig_bit.blue; + } + else + { + sig_bit = (int)png_ptr->sig_bit.gray; + } + + if (sig_bit > 0) + shift = 16 - sig_bit; + else + shift = 0; + + if (png_ptr->transformations & PNG_16_TO_8) + { + if (shift < (16 - PNG_MAX_GAMMA_8)) + shift = (16 - PNG_MAX_GAMMA_8); + } + + if (shift > 8) + shift = 8; + if (shift < 0) + shift = 0; + + png_ptr->gamma_shift = (png_byte)shift; + + num = (1 << (8 - shift)); + + if (png_ptr->screen_gamma > .000001) + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + else + g = 1.0; + + png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr, + (png_uint_32)(num * png_sizeof (png_uint_16p))); + + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) + { + double fin, fout; + png_uint_32 last, max; + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof (png_uint_16))); + } + + g = 1.0 / g; + last = 0; + for (i = 0; i < 256; i++) + { + fout = ((double)i + 0.5) / 256.0; + fin = pow(fout, g); + max = (png_uint_32)(fin * (double)((png_uint_32)num << 8)); + while (last <= max) + { + png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] + [(int)(last >> (8 - shift))] = (png_uint_16)( + (png_uint_16)i | ((png_uint_16)i << 8)); + last++; + } + } + while (last < ((png_uint_32)num << 8)) + { + png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] + [(int)(last >> (8 - shift))] = (png_uint_16)65535L; + last++; + } + } + else + { + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof (png_uint_16))); + + ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4); + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_table[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + } + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) + { + + g = 1.0 / (png_ptr->gamma); + + png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr, + (png_uint_32)(num * png_sizeof (png_uint_16p ))); + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof (png_uint_16))); + + ig = (((png_uint_32)i * + (png_uint_32)png_gamma_shift[shift]) >> 4); + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_to_1[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + + if(png_ptr->screen_gamma > 0.000001) + g = 1.0 / png_ptr->screen_gamma; + else + g = png_ptr->gamma; /* probably doing rgb_to_gray */ + + png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr, + (png_uint_32)(num * png_sizeof (png_uint_16p))); + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof (png_uint_16))); + + ig = (((png_uint_32)i * + (png_uint_32)png_gamma_shift[shift]) >> 4); + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_from_1[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ + } + } +} +#endif +/* To do: install integer version of png_build_gamma_table here */ +#endif + +#if defined(PNG_MNG_FEATURES_SUPPORTED) +/* undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_read_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_intrapixel\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff); + *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); + png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); + png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); + png_uint_32 red = (png_uint_32)((s0+s1+65536L) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2+s1+65536L) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp+1) = (png_byte)(red & 0xff); + *(rp+4) = (png_byte)((blue >> 8) & 0xff); + *(rp+5) = (png_byte)(blue & 0xff); + } + } + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ diff --git a/Utilities/FLTK/png/pngrutil.c b/Utilities/FLTK/png/pngrutil.c new file mode 100644 index 0000000000..4197bc7766 --- /dev/null +++ b/Utilities/FLTK/png/pngrutil.c @@ -0,0 +1,3124 @@ +/* pngrutil.c - utilities to read a PNG file + * + * libpng version 1.2.7 - September 12, 2004 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file contains routines that are only called from within + * libpng itself during the course of reading an image. + */ + +#define PNG_INTERNAL +#include "png.h" + +#if defined(_WIN32_WCE) +/* strtod() function is not supported on WindowsCE */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +__inline double strtod(const char *nptr, char **endptr) +{ + double result = 0; + int len; + wchar_t *str, *end; + + len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0); + str = (wchar_t *)malloc(len * sizeof(wchar_t)); + if ( NULL != str ) + { + MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len); + result = wcstod(str, &end); + len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL); + *endptr = (char *)nptr + (png_strlen(nptr) - len + 1); + free(str); + } + return result; +} +# endif +#endif + +png_uint_32 /* PRIVATE */ +png_get_uint_31(png_structp png_ptr, png_bytep buf) +{ + png_uint_32 i = png_get_uint_32(buf); + if (i > PNG_UINT_31_MAX) + png_error(png_ptr, "PNG unsigned integer out of range.\n"); + return (i); +} +#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED +/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ +png_uint_32 /* PRIVATE */ +png_get_uint_32(png_bytep buf) +{ + png_uint_32 i = ((png_uint_32)(*buf) << 24) + + ((png_uint_32)(*(buf + 1)) << 16) + + ((png_uint_32)(*(buf + 2)) << 8) + + (png_uint_32)(*(buf + 3)); + + return (i); +} + +#if defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_oFFs_SUPPORTED) +/* Grab a signed 32-bit integer from a buffer in big-endian format. The + * data is stored in the PNG file in two's complement format, and it is + * assumed that the machine format for signed integers is the same. */ +png_int_32 /* PRIVATE */ +png_get_int_32(png_bytep buf) +{ + png_int_32 i = ((png_int_32)(*buf) << 24) + + ((png_int_32)(*(buf + 1)) << 16) + + ((png_int_32)(*(buf + 2)) << 8) + + (png_int_32)(*(buf + 3)); + + return (i); +} +#endif /* PNG_READ_pCAL_SUPPORTED */ + +/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ +png_uint_16 /* PRIVATE */ +png_get_uint_16(png_bytep buf) +{ + png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) + + (png_uint_16)(*(buf + 1))); + + return (i); +} +#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */ + +/* Read data, and (optionally) run it through the CRC. */ +void /* PRIVATE */ +png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length) +{ + png_read_data(png_ptr, buf, length); + png_calculate_crc(png_ptr, buf, length); +} + +/* Optionally skip data and then check the CRC. Depending on whether we + are reading a ancillary or critical chunk, and how the program has set + things up, we may calculate the CRC on the data and print a message. + Returns '1' if there was a CRC error, '0' otherwise. */ +int /* PRIVATE */ +png_crc_finish(png_structp png_ptr, png_uint_32 skip) +{ + png_size_t i; + png_size_t istop = png_ptr->zbuf_size; + + for (i = (png_size_t)skip; i > istop; i -= istop) + { + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + } + if (i) + { + png_crc_read(png_ptr, png_ptr->zbuf, i); + } + + if (png_crc_error(png_ptr)) + { + if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */ + !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) || + (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */ + (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))) + { + png_chunk_warning(png_ptr, "CRC error"); + } + else + { + png_chunk_error(png_ptr, "CRC error"); + } + return (1); + } + + return (0); +} + +/* Compare the CRC stored in the PNG file with that calculated by libpng from + the data it has read thus far. */ +int /* PRIVATE */ +png_crc_error(png_structp png_ptr) +{ + png_byte crc_bytes[4]; + png_uint_32 crc; + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + + png_read_data(png_ptr, crc_bytes, 4); + + if (need_crc) + { + crc = png_get_uint_32(crc_bytes); + return ((int)(crc != png_ptr->crc)); + } + else + return (0); +} + +#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \ + defined(PNG_READ_iCCP_SUPPORTED) +/* + * Decompress trailing data in a chunk. The assumption is that chunkdata + * points at an allocated area holding the contents of a chunk with a + * trailing compressed part. What we get back is an allocated area + * holding the original prefix part and an uncompressed version of the + * trailing part (the malloc area passed in is freed). + */ +png_charp /* PRIVATE */ +png_decompress_chunk(png_structp png_ptr, int comp_type, + png_charp chunkdata, png_size_t chunklength, + png_size_t prefix_size, png_size_t *newlength) +{ + static char msg[] = "Error decoding compressed text"; + png_charp text; + png_size_t text_size; + + if (comp_type == PNG_COMPRESSION_TYPE_BASE) + { + int ret = Z_OK; + png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size); + png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + text_size = 0; + text = NULL; + + while (png_ptr->zstream.avail_in) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + if (png_ptr->zstream.msg != NULL) + png_warning(png_ptr, png_ptr->zstream.msg); + else + png_warning(png_ptr, msg); + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + if (text == NULL) + { + text_size = prefix_size + png_sizeof(msg) + 1; + text = (png_charp)png_malloc_warn(png_ptr, text_size); + if (text == NULL) + { + png_free(png_ptr,chunkdata); + png_error(png_ptr,"Not enough memory to decompress chunk"); + } + png_memcpy(text, chunkdata, prefix_size); + } + + text[text_size - 1] = 0x00; + + /* Copy what we can of the error message into the text chunk */ + text_size = (png_size_t)(chunklength - (text - chunkdata) - 1); + text_size = png_sizeof(msg) > text_size ? text_size : + png_sizeof(msg); + png_memcpy(text + prefix_size, msg, text_size + 1); + break; + } + if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END) + { + if (text == NULL) + { + text_size = prefix_size + + png_ptr->zbuf_size - png_ptr->zstream.avail_out; + text = (png_charp)png_malloc_warn(png_ptr, text_size + 1); + if (text == NULL) + { + png_free(png_ptr,chunkdata); + png_error(png_ptr,"Not enough memory to decompress chunk."); + } + png_memcpy(text + prefix_size, png_ptr->zbuf, + text_size - prefix_size); + png_memcpy(text, chunkdata, prefix_size); + *(text + text_size) = 0x00; + } + else + { + png_charp tmp; + + tmp = text; + text = (png_charp)png_malloc_warn(png_ptr, + (png_uint_32)(text_size + + png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1)); + if (text == NULL) + { + png_free(png_ptr, tmp); + png_free(png_ptr, chunkdata); + png_error(png_ptr,"Not enough memory to decompress chunk.."); + } + png_memcpy(text, tmp, text_size); + png_free(png_ptr, tmp); + png_memcpy(text + text_size, png_ptr->zbuf, + (png_ptr->zbuf_size - png_ptr->zstream.avail_out)); + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; + *(text + text_size) = 0x00; + } + if (ret == Z_STREAM_END) + break; + else + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + } + if (ret != Z_STREAM_END) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char umsg[50]; + + if (ret == Z_BUF_ERROR) + sprintf(umsg,"Buffer error in compressed datastream in %s chunk", + png_ptr->chunk_name); + else if (ret == Z_DATA_ERROR) + sprintf(umsg,"Data error in compressed datastream in %s chunk", + png_ptr->chunk_name); + else + sprintf(umsg,"Incomplete compressed datastream in %s chunk", + png_ptr->chunk_name); + png_warning(png_ptr, umsg); +#else + png_warning(png_ptr, + "Incomplete compressed datastream in chunk other than IDAT"); +#endif + text_size=prefix_size; + if (text == NULL) + { + text = (png_charp)png_malloc_warn(png_ptr, text_size+1); + if (text == NULL) + { + png_free(png_ptr, chunkdata); + png_error(png_ptr,"Not enough memory for text."); + } + png_memcpy(text, chunkdata, prefix_size); + } + *(text + text_size) = 0x00; + } + + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + png_free(png_ptr, chunkdata); + chunkdata = text; + *newlength=text_size; + } + else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */ + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char umsg[50]; + + sprintf(umsg, "Unknown zTXt compression type %d", comp_type); + png_warning(png_ptr, umsg); +#else + png_warning(png_ptr, "Unknown zTXt compression type"); +#endif + + *(chunkdata + prefix_size) = 0x00; + *newlength=prefix_size; + } + + return chunkdata; +} +#endif + +/* read and check the IDHR chunk */ +void /* PRIVATE */ +png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[13]; + png_uint_32 width, height; + int bit_depth, color_type, compression_type, filter_type; + int interlace_type; + + png_debug(1, "in png_handle_IHDR\n"); + + if (png_ptr->mode & PNG_HAVE_IHDR) + png_error(png_ptr, "Out of place IHDR"); + + /* check the length */ + if (length != 13) + png_error(png_ptr, "Invalid IHDR chunk"); + + png_ptr->mode |= PNG_HAVE_IHDR; + + png_crc_read(png_ptr, buf, 13); + png_crc_finish(png_ptr, 0); + + width = png_get_uint_31(png_ptr, buf); + height = png_get_uint_31(png_ptr, buf + 4); + bit_depth = buf[8]; + color_type = buf[9]; + compression_type = buf[10]; + filter_type = buf[11]; + interlace_type = buf[12]; + + /* set internal variables */ + png_ptr->width = width; + png_ptr->height = height; + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->interlaced = (png_byte)interlace_type; + png_ptr->color_type = (png_byte)color_type; +#if defined(PNG_MNG_FEATURES_SUPPORTED) + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + + /* find number of channels */ + switch (png_ptr->color_type) + { + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_PALETTE: + png_ptr->channels = 1; + break; + case PNG_COLOR_TYPE_RGB: + png_ptr->channels = 3; + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + png_ptr->channels = 2; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + png_ptr->channels = 4; + break; + } + + /* set up other useful info */ + png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * + png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width); + png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth); + png_debug1(3,"channels = %d\n", png_ptr->channels); + png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes); + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, + color_type, interlace_type, compression_type, filter_type); +} + +/* read and check the palette */ +void /* PRIVATE */ +png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_color palette[PNG_MAX_PALETTE_LENGTH]; + int num, i; +#ifndef PNG_NO_POINTER_INDEXING + png_colorp pal_ptr; +#endif + + png_debug(1, "in png_handle_PLTE\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before PLTE"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid PLTE after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + png_error(png_ptr, "Duplicate PLTE chunk"); + + png_ptr->mode |= PNG_HAVE_PLTE; + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring PLTE chunk in grayscale PNG"); + png_crc_finish(png_ptr, length); + return; + } +#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_crc_finish(png_ptr, length); + return; + } +#endif + + if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) + { + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_warning(png_ptr, "Invalid palette chunk"); + png_crc_finish(png_ptr, length); + return; + } + else + { + png_error(png_ptr, "Invalid palette chunk"); + } + } + + num = (int)length / 3; + +#ifndef PNG_NO_POINTER_INDEXING + for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + pal_ptr->red = buf[0]; + pal_ptr->green = buf[1]; + pal_ptr->blue = buf[2]; + } +#else + for (i = 0; i < num; i++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + /* don't depend upon png_color being any order */ + palette[i].red = buf[0]; + palette[i].green = buf[1]; + palette[i].blue = buf[2]; + } +#endif + + /* If we actually NEED the PLTE chunk (ie for a paletted image), we do + whatever the normal CRC configuration tells us. However, if we + have an RGB image, the PLTE can be considered ancillary, so + we will act as though it is. */ +#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#endif + { + png_crc_finish(png_ptr, 0); + } +#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) + else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ + { + /* If we don't want to use the data from an ancillary chunk, + we have two options: an error abort, or a warning and we + ignore the data in this chunk (which should be OK, since + it's considered ancillary for a RGB or RGBA image). */ + if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) + { + if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) + { + png_chunk_error(png_ptr, "CRC error"); + } + else + { + png_chunk_warning(png_ptr, "CRC error"); + return; + } + } + /* Otherwise, we (optionally) emit a warning and use the chunk. */ + else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) + { + png_chunk_warning(png_ptr, "CRC error"); + } + } +#endif + + png_set_PLTE(png_ptr, info_ptr, palette, num); + +#if defined(PNG_READ_tRNS_SUPPORTED) + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + if (png_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect tRNS chunk length"); + png_ptr->num_trans = (png_uint_16)num; + } + if (info_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect info tRNS chunk length"); + info_ptr->num_trans = (png_uint_16)num; + } + } + } +#endif + +} + +void /* PRIVATE */ +png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_debug(1, "in png_handle_IEND\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT)) + { + png_error(png_ptr, "No image in file"); + } + + png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); + + if (length != 0) + { + png_warning(png_ptr, "Incorrect IEND chunk length"); + } + png_crc_finish(png_ptr, length); + + if (&info_ptr == NULL) /* quiet compiler warnings about unused info_ptr */ + return; +} + +#if defined(PNG_READ_gAMA_SUPPORTED) +void /* PRIVATE */ +png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_fixed_point igamma; +#ifdef PNG_FLOATING_POINT_SUPPORTED + float file_gamma; +#endif + png_byte buf[4]; + + png_debug(1, "in png_handle_gAMA\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before gAMA"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid gAMA after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place gAMA chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) +#if defined(PNG_READ_sRGB_SUPPORTED) + && !(info_ptr->valid & PNG_INFO_sRGB) +#endif + ) + { + png_warning(png_ptr, "Duplicate gAMA chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 4) + { + png_warning(png_ptr, "Incorrect gAMA chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 4); + if (png_crc_finish(png_ptr, 0)) + return; + + igamma = (png_fixed_point)png_get_uint_32(buf); + /* check for zero gamma */ + if (igamma == 0) + { + png_warning(png_ptr, + "Ignoring gAMA chunk with gamma=0"); + return; + } + +#if defined(PNG_READ_sRGB_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sRGB) + if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) + { + png_warning(png_ptr, + "Ignoring incorrect gAMA value when sRGB is also present"); +#ifndef PNG_NO_CONSOLE_IO + fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma); +#endif + return; + } +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + file_gamma = (float)igamma / (float)100000.0; +# ifdef PNG_READ_GAMMA_SUPPORTED + png_ptr->gamma = file_gamma; +# endif + png_set_gAMA(png_ptr, info_ptr, file_gamma); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_gAMA_fixed(png_ptr, info_ptr, igamma); +#endif +} +#endif + +#if defined(PNG_READ_sBIT_SUPPORTED) +void /* PRIVATE */ +png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[4]; + + png_debug(1, "in png_handle_sBIT\n"); + + buf[0] = buf[1] = buf[2] = buf[3] = 0; + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sBIT"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sBIT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + { + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sBIT chunk"); + } + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) + { + png_warning(png_ptr, "Duplicate sBIT chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 3; + else + truelen = (png_size_t)png_ptr->channels; + + if (length != truelen || length > 4) + { + png_warning(png_ptr, "Incorrect sBIT chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + if (png_crc_finish(png_ptr, 0)) + return; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[1]; + png_ptr->sig_bit.blue = buf[2]; + png_ptr->sig_bit.alpha = buf[3]; + } + else + { + png_ptr->sig_bit.gray = buf[0]; + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[0]; + png_ptr->sig_bit.blue = buf[0]; + png_ptr->sig_bit.alpha = buf[1]; + } + png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); +} +#endif + +#if defined(PNG_READ_cHRM_SUPPORTED) +void /* PRIVATE */ +png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[4]; +#ifdef PNG_FLOATING_POINT_SUPPORTED + float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; +#endif + png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, + int_y_green, int_x_blue, int_y_blue; + + png_uint_32 uint_x, uint_y; + + png_debug(1, "in png_handle_cHRM\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before cHRM"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid cHRM after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Missing PLTE before cHRM"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM) +#if defined(PNG_READ_sRGB_SUPPORTED) + && !(info_ptr->valid & PNG_INFO_sRGB) +#endif + ) + { + png_warning(png_ptr, "Duplicate cHRM chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 32) + { + png_warning(png_ptr, "Incorrect cHRM chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 4); + uint_x = png_get_uint_32(buf); + + png_crc_read(png_ptr, buf, 4); + uint_y = png_get_uint_32(buf); + + if (uint_x > 80000L || uint_y > 80000L || + uint_x + uint_y > 100000L) + { + png_warning(png_ptr, "Invalid cHRM white point"); + png_crc_finish(png_ptr, 24); + return; + } + int_x_white = (png_fixed_point)uint_x; + int_y_white = (png_fixed_point)uint_y; + + png_crc_read(png_ptr, buf, 4); + uint_x = png_get_uint_32(buf); + + png_crc_read(png_ptr, buf, 4); + uint_y = png_get_uint_32(buf); + + if (uint_x > 80000L || uint_y > 80000L || + uint_x + uint_y > 100000L) + { + png_warning(png_ptr, "Invalid cHRM red point"); + png_crc_finish(png_ptr, 16); + return; + } + int_x_red = (png_fixed_point)uint_x; + int_y_red = (png_fixed_point)uint_y; + + png_crc_read(png_ptr, buf, 4); + uint_x = png_get_uint_32(buf); + + png_crc_read(png_ptr, buf, 4); + uint_y = png_get_uint_32(buf); + + if (uint_x > 80000L || uint_y > 80000L || + uint_x + uint_y > 100000L) + { + png_warning(png_ptr, "Invalid cHRM green point"); + png_crc_finish(png_ptr, 8); + return; + } + int_x_green = (png_fixed_point)uint_x; + int_y_green = (png_fixed_point)uint_y; + + png_crc_read(png_ptr, buf, 4); + uint_x = png_get_uint_32(buf); + + png_crc_read(png_ptr, buf, 4); + uint_y = png_get_uint_32(buf); + + if (uint_x > 80000L || uint_y > 80000L || + uint_x + uint_y > 100000L) + { + png_warning(png_ptr, "Invalid cHRM blue point"); + png_crc_finish(png_ptr, 0); + return; + } + int_x_blue = (png_fixed_point)uint_x; + int_y_blue = (png_fixed_point)uint_y; + +#ifdef PNG_FLOATING_POINT_SUPPORTED + white_x = (float)int_x_white / (float)100000.0; + white_y = (float)int_y_white / (float)100000.0; + red_x = (float)int_x_red / (float)100000.0; + red_y = (float)int_y_red / (float)100000.0; + green_x = (float)int_x_green / (float)100000.0; + green_y = (float)int_y_green / (float)100000.0; + blue_x = (float)int_x_blue / (float)100000.0; + blue_y = (float)int_y_blue / (float)100000.0; +#endif + +#if defined(PNG_READ_sRGB_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sRGB) + { + if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000)) + { + + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); +#ifndef PNG_NO_CONSOLE_IO +#ifdef PNG_FLOATING_POINT_SUPPORTED + fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n", + white_x, white_y, red_x, red_y); + fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n", + green_x, green_y, blue_x, blue_y); +#else + fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n", + int_x_white, int_y_white, int_x_red, int_y_red); + fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n", + int_x_green, int_y_green, int_x_blue, int_y_blue); +#endif +#endif /* PNG_NO_CONSOLE_IO */ + } + png_crc_finish(png_ptr, 0); + return; + } +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_cHRM(png_ptr, info_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_cHRM_fixed(png_ptr, info_ptr, + int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, + int_y_green, int_x_blue, int_y_blue); +#endif + if (png_crc_finish(png_ptr, 0)) + return; +} +#endif + +#if defined(PNG_READ_sRGB_SUPPORTED) +void /* PRIVATE */ +png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + int intent; + png_byte buf[1]; + + png_debug(1, "in png_handle_sRGB\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sRGB"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sRGB after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sRGB chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) + { + png_warning(png_ptr, "Duplicate sRGB chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 1) + { + png_warning(png_ptr, "Incorrect sRGB chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 1); + if (png_crc_finish(png_ptr, 0)) + return; + + intent = buf[0]; + /* check for bad intent */ + if (intent >= PNG_sRGB_INTENT_LAST) + { + png_warning(png_ptr, "Unknown sRGB intent"); + return; + } + +#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) + if ((info_ptr->valid & PNG_INFO_gAMA)) + { + png_fixed_point igamma; +#ifdef PNG_FIXED_POINT_SUPPORTED + igamma=info_ptr->int_gamma; +#else +# ifdef PNG_FLOATING_POINT_SUPPORTED + igamma=(png_fixed_point)(info_ptr->gamma * 100000.); +# endif +#endif + if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) + { + png_warning(png_ptr, + "Ignoring incorrect gAMA value when sRGB is also present"); +#ifndef PNG_NO_CONSOLE_IO +# ifdef PNG_FIXED_POINT_SUPPORTED + fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma); +# else +# ifdef PNG_FLOATING_POINT_SUPPORTED + fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma); +# endif +# endif +#endif + } + } +#endif /* PNG_READ_gAMA_SUPPORTED */ + +#ifdef PNG_READ_cHRM_SUPPORTED +#ifdef PNG_FIXED_POINT_SUPPORTED + if (info_ptr->valid & PNG_INFO_cHRM) + if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); + } +#endif /* PNG_FIXED_POINT_SUPPORTED */ +#endif /* PNG_READ_cHRM_SUPPORTED */ + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent); +} +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#if defined(PNG_READ_iCCP_SUPPORTED) +void /* PRIVATE */ +png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_charp chunkdata; + png_byte compression_type; + png_bytep pC; + png_charp profile; + png_uint_32 skip = 0; + png_uint_32 profile_size, profile_length; + png_size_t slength, prefix_length, data_length; + + png_debug(1, "in png_handle_iCCP\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iCCP"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid iCCP after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place iCCP chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)) + { + png_warning(png_ptr, "Duplicate iCCP chunk"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "iCCP chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + chunkdata = (png_charp)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, chunkdata); + return; + } + + chunkdata[slength] = 0x00; + + for (profile = chunkdata; *profile; profile++) + /* empty loop to find end of name */ ; + + ++profile; + + /* there should be at least one zero (the compression type byte) + following the separator, and we should be on it */ + if ( profile >= chunkdata + slength) + { + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "Malformed iCCP chunk"); + return; + } + + /* compression_type should always be zero */ + compression_type = *profile++; + if (compression_type) + { + png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk"); + compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8 + wrote nonzero) */ + } + + prefix_length = profile - chunkdata; + chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata, + slength, prefix_length, &data_length); + + profile_length = data_length - prefix_length; + + if ( prefix_length > data_length || profile_length < 4) + { + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "Profile size field missing from iCCP chunk"); + return; + } + + /* Check the profile_size recorded in the first 32 bits of the ICC profile */ + pC = (png_bytep)(chunkdata+prefix_length); + profile_size = ((*(pC ))<<24) | + ((*(pC+1))<<16) | + ((*(pC+2))<< 8) | + ((*(pC+3)) ); + + if(profile_size < profile_length) + profile_length = profile_size; + + if(profile_size > profile_length) + { + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "Ignoring truncated iCCP profile.\n"); + return; + } + + png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type, + chunkdata + prefix_length, profile_length); + png_free(png_ptr, chunkdata); +} +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#if defined(PNG_READ_sPLT_SUPPORTED) +void /* PRIVATE */ +png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_bytep chunkdata; + png_bytep entry_start; + png_sPLT_t new_palette; +#ifdef PNG_NO_POINTER_INDEXING + png_sPLT_entryp pp; +#endif + int data_length, entry_size, i; + png_uint_32 skip = 0; + png_size_t slength; + + png_debug(1, "in png_handle_sPLT\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sPLT"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sPLT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "sPLT chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + chunkdata = (png_bytep)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, chunkdata); + return; + } + + chunkdata[slength] = 0x00; + + for (entry_start = chunkdata; *entry_start; entry_start++) + /* empty loop to find end of name */ ; + ++entry_start; + + /* a sample depth should follow the separator, and we should be on it */ + if (entry_start > chunkdata + slength) + { + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "malformed sPLT chunk"); + return; + } + + new_palette.depth = *entry_start++; + entry_size = (new_palette.depth == 8 ? 6 : 10); + data_length = (slength - (entry_start - chunkdata)); + + /* integrity-check the data length */ + if (data_length % entry_size) + { + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "sPLT chunk has bad length"); + return; + } + + new_palette.nentries = (png_uint_32) (data_length / entry_size); + if ((png_uint_32) new_palette.nentries > (png_uint_32) (PNG_SIZE_MAX / + png_sizeof(png_sPLT_entry))) + { + png_warning(png_ptr, "sPLT chunk too long"); + return; + } + new_palette.entries = (png_sPLT_entryp)png_malloc_warn( + png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry)); + if (new_palette.entries == NULL) + { + png_warning(png_ptr, "sPLT chunk requires too much memory"); + return; + } + +#ifndef PNG_NO_POINTER_INDEXING + for (i = 0; i < new_palette.nentries; i++) + { + png_sPLT_entryp pp = new_palette.entries + i; + + if (new_palette.depth == 8) + { + pp->red = *entry_start++; + pp->green = *entry_start++; + pp->blue = *entry_start++; + pp->alpha = *entry_start++; + } + else + { + pp->red = png_get_uint_16(entry_start); entry_start += 2; + pp->green = png_get_uint_16(entry_start); entry_start += 2; + pp->blue = png_get_uint_16(entry_start); entry_start += 2; + pp->alpha = png_get_uint_16(entry_start); entry_start += 2; + } + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#else + pp = new_palette.entries; + for (i = 0; i < new_palette.nentries; i++) + { + + if (new_palette.depth == 8) + { + pp[i].red = *entry_start++; + pp[i].green = *entry_start++; + pp[i].blue = *entry_start++; + pp[i].alpha = *entry_start++; + } + else + { + pp[i].red = png_get_uint_16(entry_start); entry_start += 2; + pp[i].green = png_get_uint_16(entry_start); entry_start += 2; + pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; + pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; + } + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#endif + + /* discard all chunk data except the name and stash that */ + new_palette.name = (png_charp)chunkdata; + + png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); + + png_free(png_ptr, chunkdata); + png_free(png_ptr, new_palette.entries); +} +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#if defined(PNG_READ_tRNS_SUPPORTED) +void /* PRIVATE */ +png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_tRNS\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tRNS"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid tRNS after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_warning(png_ptr, "Duplicate tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + png_byte buf[2]; + + if (length != 2) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 2); + png_ptr->num_trans = 1; + png_ptr->trans_values.gray = png_get_uint_16(buf); + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_byte buf[6]; + + if (length != 6) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + png_crc_read(png_ptr, buf, (png_size_t)length); + png_ptr->num_trans = 1; + png_ptr->trans_values.red = png_get_uint_16(buf); + png_ptr->trans_values.green = png_get_uint_16(buf + 2); + png_ptr->trans_values.blue = png_get_uint_16(buf + 4); + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + /* Should be an error, but we can cope with it. */ + png_warning(png_ptr, "Missing PLTE before tRNS"); + } + if (length > (png_uint_32)png_ptr->num_palette || + length > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + if (length == 0) + { + png_warning(png_ptr, "Zero length tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + png_crc_read(png_ptr, readbuf, (png_size_t)length); + png_ptr->num_trans = (png_uint_16)length; + } + else + { + png_warning(png_ptr, "tRNS chunk not allowed with alpha channel"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_crc_finish(png_ptr, 0)) + return; + + png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, + &(png_ptr->trans_values)); +} +#endif + +#if defined(PNG_READ_bKGD_SUPPORTED) +void /* PRIVATE */ +png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[6]; + + png_debug(1, "in png_handle_bKGD\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before bKGD"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid bKGD after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before bKGD"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) + { + png_warning(png_ptr, "Duplicate bKGD chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 1; + else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + truelen = 6; + else + truelen = 2; + + if (length != truelen) + { + png_warning(png_ptr, "Incorrect bKGD chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + if (png_crc_finish(png_ptr, 0)) + return; + + /* We convert the index value into RGB components so that we can allow + * arbitrary RGB values for background when we have transparency, and + * so it is easy to determine the RGB values of the background color + * from the info_ptr struct. */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_ptr->background.index = buf[0]; + if(info_ptr->num_palette) + { + if(buf[0] > info_ptr->num_palette) + { + png_warning(png_ptr, "Incorrect bKGD chunk index value"); + return; + } + png_ptr->background.red = + (png_uint_16)png_ptr->palette[buf[0]].red; + png_ptr->background.green = + (png_uint_16)png_ptr->palette[buf[0]].green; + png_ptr->background.blue = + (png_uint_16)png_ptr->palette[buf[0]].blue; + } + } + else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ + { + png_ptr->background.red = + png_ptr->background.green = + png_ptr->background.blue = + png_ptr->background.gray = png_get_uint_16(buf); + } + else + { + png_ptr->background.red = png_get_uint_16(buf); + png_ptr->background.green = png_get_uint_16(buf + 2); + png_ptr->background.blue = png_get_uint_16(buf + 4); + } + + png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background)); +} +#endif + +#if defined(PNG_READ_hIST_SUPPORTED) +void /* PRIVATE */ +png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + unsigned int num, i; + png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_hIST\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before hIST"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid hIST after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before hIST"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) + { + png_warning(png_ptr, "Duplicate hIST chunk"); + png_crc_finish(png_ptr, length); + return; + } + + num = length / 2 ; + if (num != (unsigned int) png_ptr->num_palette || num > + (unsigned int) PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect hIST chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + for (i = 0; i < num; i++) + { + png_byte buf[2]; + + png_crc_read(png_ptr, buf, 2); + readbuf[i] = png_get_uint_16(buf); + } + + if (png_crc_finish(png_ptr, 0)) + return; + + png_set_hIST(png_ptr, info_ptr, readbuf); +} +#endif + +#if defined(PNG_READ_pHYs_SUPPORTED) +void /* PRIVATE */ +png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_uint_32 res_x, res_y; + int unit_type; + + png_debug(1, "in png_handle_pHYs\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pHYs"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pHYs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_warning(png_ptr, "Duplicate pHYs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect pHYs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + if (png_crc_finish(png_ptr, 0)) + return; + + res_x = png_get_uint_32(buf); + res_y = png_get_uint_32(buf + 4); + unit_type = buf[8]; + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type); +} +#endif + +#if defined(PNG_READ_oFFs_SUPPORTED) +void /* PRIVATE */ +png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_int_32 offset_x, offset_y; + int unit_type; + + png_debug(1, "in png_handle_oFFs\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before oFFs"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid oFFs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_warning(png_ptr, "Duplicate oFFs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect oFFs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + if (png_crc_finish(png_ptr, 0)) + return; + + offset_x = png_get_int_32(buf); + offset_y = png_get_int_32(buf + 4); + unit_type = buf[8]; + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type); +} +#endif + +#if defined(PNG_READ_pCAL_SUPPORTED) +/* read the pCAL chunk (described in the PNG Extensions document) */ +void /* PRIVATE */ +png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_charp purpose; + png_int_32 X0, X1; + png_byte type, nparams; + png_charp buf, units, endptr; + png_charpp params; + png_size_t slength; + int i; + + png_debug(1, "in png_handle_pCAL\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pCAL"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) + { + png_warning(png_ptr, "Duplicate pCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n", + length + 1); + purpose = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (purpose == NULL) + { + png_warning(png_ptr, "No memory for pCAL purpose."); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)purpose, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, purpose); + return; + } + + purpose[slength] = 0x00; /* null terminate the last string */ + + png_debug(3, "Finding end of pCAL purpose string\n"); + for (buf = purpose; *buf; buf++) + /* empty loop */ ; + + endptr = purpose + slength; + + /* We need to have at least 12 bytes after the purpose string + in order to get the parameter information. */ + if (endptr <= buf + 12) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, purpose); + return; + } + + png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n"); + X0 = png_get_int_32((png_bytep)buf+1); + X1 = png_get_int_32((png_bytep)buf+5); + type = buf[9]; + nparams = buf[10]; + units = buf + 11; + + png_debug(3, "Checking pCAL equation type and number of parameters\n"); + /* Check that we have the right number of parameters for known + equation types. */ + if ((type == PNG_EQUATION_LINEAR && nparams != 2) || + (type == PNG_EQUATION_BASE_E && nparams != 3) || + (type == PNG_EQUATION_ARBITRARY && nparams != 3) || + (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) + { + png_warning(png_ptr, "Invalid pCAL parameters for equation type"); + png_free(png_ptr, purpose); + return; + } + else if (type >= PNG_EQUATION_LAST) + { + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + } + + for (buf = units; *buf; buf++) + /* Empty loop to move past the units string. */ ; + + png_debug(3, "Allocating pCAL parameters array\n"); + params = (png_charpp)png_malloc_warn(png_ptr, (png_uint_32)(nparams + *png_sizeof(png_charp))) ; + if (params == NULL) + { + png_free(png_ptr, purpose); + png_warning(png_ptr, "No memory for pCAL params."); + return; + } + + /* Get pointers to the start of each parameter string. */ + for (i = 0; i < (int)nparams; i++) + { + buf++; /* Skip the null string terminator from previous parameter. */ + + png_debug1(3, "Reading pCAL parameter %d\n", i); + for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++) + /* Empty loop to move past each parameter string */ ; + + /* Make sure we haven't run out of data yet */ + if (buf > endptr) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, purpose); + png_free(png_ptr, params); + return; + } + } + + png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams, + units, params); + + png_free(png_ptr, purpose); + png_free(png_ptr, params); +} +#endif + +#if defined(PNG_READ_sCAL_SUPPORTED) +/* read the sCAL chunk */ +void /* PRIVATE */ +png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_charp buffer, ep; +#ifdef PNG_FLOATING_POINT_SUPPORTED + double width, height; + png_charp vp; +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_charp swidth, sheight; +#endif +#endif + png_size_t slength; + + png_debug(1, "in png_handle_sCAL\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sCAL"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) + { + png_warning(png_ptr, "Duplicate sCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n", + length + 1); + buffer = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (buffer == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk"); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)buffer, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, buffer); + return; + } + + buffer[slength] = 0x00; /* null terminate the last string */ + + ep = buffer + 1; /* skip unit byte */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + width = strtod(ep, &vp); + if (*vp) + { + png_warning(png_ptr, "malformed width string in sCAL chunk"); + return; + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); + if (swidth == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk width"); + return; + } + png_memcpy(swidth, ep, (png_size_t)png_strlen(ep)); +#endif +#endif + + for (ep = buffer; *ep; ep++) + /* empty loop */ ; + ep++; + +#ifdef PNG_FLOATING_POINT_SUPPORTED + height = strtod(ep, &vp); + if (*vp) + { + png_warning(png_ptr, "malformed height string in sCAL chunk"); + return; + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); + if (swidth == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk height"); + return; + } + png_memcpy(sheight, ep, (png_size_t)png_strlen(ep)); +#endif +#endif + + if (buffer + slength < ep +#ifdef PNG_FLOATING_POINT_SUPPORTED + || width <= 0. || height <= 0. +#endif + ) + { + png_warning(png_ptr, "Invalid sCAL data"); + png_free(png_ptr, buffer); +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); + png_free(png_ptr, sheight); +#endif + return; + } + + +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight); +#endif +#endif + + png_free(png_ptr, buffer); +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); + png_free(png_ptr, sheight); +#endif +} +#endif + +#if defined(PNG_READ_tIME_SUPPORTED) +void /* PRIVATE */ +png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[7]; + png_time mod_time; + + png_debug(1, "in png_handle_tIME\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Out of place tIME chunk"); + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) + { + png_warning(png_ptr, "Duplicate tIME chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + + if (length != 7) + { + png_warning(png_ptr, "Incorrect tIME chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 7); + if (png_crc_finish(png_ptr, 0)) + return; + + mod_time.second = buf[6]; + mod_time.minute = buf[5]; + mod_time.hour = buf[4]; + mod_time.day = buf[3]; + mod_time.month = buf[2]; + mod_time.year = png_get_uint_16(buf); + + png_set_tIME(png_ptr, info_ptr, &mod_time); +} +#endif + +#if defined(PNG_READ_tEXt_SUPPORTED) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp key; + png_charp text; + png_uint_32 skip = 0; + png_size_t slength; + int ret; + + png_debug(1, "in png_handle_tEXt\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tEXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + key = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (key == NULL) + { + png_warning(png_ptr, "No memory to process text chunk."); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)key, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, key); + return; + } + + key[slength] = 0x00; + + for (text = key; *text; text++) + /* empty loop to find end of key */ ; + + if (text != key + slength) + text++; + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)png_sizeof(png_text)); + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process text chunk."); + png_free(png_ptr, key); + return; + } + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; +#endif + text_ptr->text = text; + text_ptr->text_length = png_strlen(text); + + ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + if (ret) + png_warning(png_ptr, "Insufficient memory to process text chunk."); +} +#endif + +#if defined(PNG_READ_zTXt_SUPPORTED) +/* note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp chunkdata; + png_charp text; + int comp_type; + int ret; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_zTXt\n"); + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before zTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + there is no hard and fast rule to tell us where to stop. */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr,"zTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (chunkdata == NULL) + { + png_warning(png_ptr,"Out of memory processing zTXt chunk."); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)chunkdata, slength); + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, chunkdata); + return; + } + + chunkdata[slength] = 0x00; + + for (text = chunkdata; *text; text++) + /* empty loop */ ; + + /* zTXt must have some text after the chunkdataword */ + if (text == chunkdata + slength) + { + comp_type = PNG_TEXT_COMPRESSION_NONE; + png_warning(png_ptr, "Zero length zTXt chunk"); + } + else + { + comp_type = *(++text); + if (comp_type != PNG_TEXT_COMPRESSION_zTXt) + { + png_warning(png_ptr, "Unknown compression type in zTXt chunk"); + comp_type = PNG_TEXT_COMPRESSION_zTXt; + } + text++; /* skip the compression_method byte */ + } + prefix_len = text - chunkdata; + + chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata, + (png_size_t)length, prefix_len, &data_len); + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)png_sizeof(png_text)); + if (text_ptr == NULL) + { + png_warning(png_ptr,"Not enough memory to process zTXt chunk."); + png_free(png_ptr, chunkdata); + return; + } + text_ptr->compression = comp_type; + text_ptr->key = chunkdata; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; +#endif + text_ptr->text = chunkdata + prefix_len; + text_ptr->text_length = data_len; + + ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, chunkdata); + if (ret) + png_error(png_ptr, "Insufficient memory to store zTXt chunk."); +} +#endif + +#if defined(PNG_READ_iTXt_SUPPORTED) +/* note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp chunkdata; + png_charp key, lang, text, lang_key; + int comp_flag; + int comp_type = 0; + int ret; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_iTXt\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + there is no hard and fast rule to tell us where to stop. */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr,"iTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (chunkdata == NULL) + { + png_warning(png_ptr, "No memory to process iTXt chunk."); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)chunkdata, slength); + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, chunkdata); + return; + } + + chunkdata[slength] = 0x00; + + for (lang = chunkdata; *lang; lang++) + /* empty loop */ ; + lang++; /* skip NUL separator */ + + /* iTXt must have a language tag (possibly empty), two compression bytes, + translated keyword (possibly empty), and possibly some text after the + keyword */ + + if (lang >= chunkdata + slength) + { + comp_flag = PNG_TEXT_COMPRESSION_NONE; + png_warning(png_ptr, "Zero length iTXt chunk"); + } + else + { + comp_flag = *lang++; + comp_type = *lang++; + } + + for (lang_key = lang; *lang_key; lang_key++) + /* empty loop */ ; + lang_key++; /* skip NUL separator */ + + for (text = lang_key; *text; text++) + /* empty loop */ ; + text++; /* skip NUL separator */ + + prefix_len = text - chunkdata; + + key=chunkdata; + if (comp_flag) + chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata, + (size_t)length, prefix_len, &data_len); + else + data_len=png_strlen(chunkdata + prefix_len); + text_ptr = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)png_sizeof(png_text)); + if (text_ptr == NULL) + { + png_warning(png_ptr,"Not enough memory to process iTXt chunk."); + png_free(png_ptr, chunkdata); + return; + } + text_ptr->compression = (int)comp_flag + 1; + text_ptr->lang_key = chunkdata+(lang_key-key); + text_ptr->lang = chunkdata+(lang-key); + text_ptr->itxt_length = data_len; + text_ptr->text_length = 0; + text_ptr->key = chunkdata; + text_ptr->text = chunkdata + prefix_len; + + ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, chunkdata); + if (ret) + png_error(png_ptr, "Insufficient memory to store iTXt chunk."); +} +#endif + +/* This function is called when we haven't found a handler for a + chunk. If there isn't a problem with the chunk itself (ie bad + chunk name, CRC, or a critical chunk), the chunk is silently ignored + -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which + case it will be saved away to be written out later. */ +void /* PRIVATE */ +png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_uint_32 skip = 0; + + png_debug(1, "in png_handle_unknown\n"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IDAT; +#endif + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */ + png_ptr->mode |= PNG_AFTER_IDAT; + } + + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + } + +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) + { + png_unknown_chunk chunk; + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name); + chunk.data = (png_bytep)png_malloc(png_ptr, length); + chunk.size = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)chunk.data, length); +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) + if(png_ptr->read_user_chunk_fn != NULL) + { + /* callback to user unknown chunk handler */ + if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) + { + png_free(png_ptr, chunk.data); + png_chunk_error(png_ptr, "unknown critical chunk"); + } + png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1); + } + } + else +#endif + png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1); + png_free(png_ptr, chunk.data); + } + else +#endif + skip = length; + + png_crc_finish(png_ptr, skip); + +#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED) + if (&info_ptr == NULL) /* quiet compiler warnings about unused info_ptr */ + return; +#endif +} + +/* This function is called to verify that a chunk name is valid. + This function can't have the "critical chunk check" incorporated + into it, since in the future we will need to be able to call user + functions to handle unknown critical chunks after we check that + the chunk name itself is valid. */ + +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) + +void /* PRIVATE */ +png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name) +{ + png_debug(1, "in png_check_chunk_name\n"); + if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) || + isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3])) + { + png_chunk_error(png_ptr, "invalid chunk type"); + } +} + +/* Combines the row recently read in with the existing pixels in the + row. This routine takes care of alpha and transparency if requested. + This routine also handles the two methods of progressive display + of interlaced images, depending on the mask value. + The mask value describes which pixels are to be combined with + the row. The pattern always repeats every 8 pixels, so just 8 + bits are needed. A one indicates the pixel is to be combined, + a zero indicates the pixel is to be skipped. This is in addition + to any alpha or transparency value associated with the pixel. If + you want all pixels to be combined, pass 0xff (255) in mask. */ +#ifndef PNG_HAVE_ASSEMBLER_COMBINE_ROW +void /* PRIVATE */ +png_combine_row(png_structp png_ptr, png_bytep row, int mask) +{ + png_debug(1,"in png_combine_row\n"); + if (mask == 0xff) + { + png_memcpy(row, png_ptr->row_buf + 1, + PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)); + } + else + { + switch (png_ptr->row_info.pixel_depth) + { + case 1: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_inc, s_start, s_end; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 7; + s_inc = 1; + } + else +#endif + { + s_start = 7; + s_end = 0; + s_inc = -1; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + int value; + + value = (*sp >> shift) & 0x01; + *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + case 2: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 6; + s_inc = 2; + } + else +#endif + { + s_start = 6; + s_end = 0; + s_inc = -2; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0x03; + *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + case 4: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 4; + s_inc = 4; + } + else +#endif + { + s_start = 4; + s_end = 0; + s_inc = -4; + } + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0xf; + *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + default: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + png_byte m = 0x80; + + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + png_memcpy(dp, sp, pixel_bytes); + } + + sp += pixel_bytes; + dp += pixel_bytes; + + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + } + } +} +#endif /* !PNG_HAVE_ASSEMBLER_COMBINE_ROW */ + +#ifdef PNG_READ_INTERLACING_SUPPORTED +#ifndef PNG_HAVE_ASSEMBLER_READ_INTERLACE /* else in pngvcrd.c, pnggccrd.c */ +/* OLD pre-1.0.9 interface: +void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, + png_uint_32 transformations) + */ +void /* PRIVATE */ +png_do_read_interlace(png_structp png_ptr) +{ + png_row_infop row_info = &(png_ptr->row_info); + png_bytep row = png_ptr->row_buf + 1; + int pass = png_ptr->pass; + png_uint_32 transformations = png_ptr->transformations; +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + /* offset to next interlace block */ + const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; +#endif + + png_debug(1,"in png_do_read_interlace (stock C version)\n"); + if (row != NULL && row_info != NULL) + { + png_uint_32 final_width; + + final_width = row_info->width * png_pass_inc[pass]; + + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_byte v; + png_uint_32 i; + int j; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (int)((row_info->width + 7) & 0x07); + dshift = (int)((final_width + 7) & 0x07); + s_start = 7; + s_end = 0; + s_inc = -1; + } + else +#endif + { + sshift = 7 - (int)((row_info->width + 7) & 0x07); + dshift = 7 - (int)((final_width + 7) & 0x07); + s_start = 0; + s_end = 7; + s_inc = 1; + } + + for (i = 0; i < row_info->width; i++) + { + v = (png_byte)((*sp >> sshift) & 0x01); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + case 2: + { + png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); + png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_uint_32 i; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 3) & 0x03) << 1); + dshift = (int)(((final_width + 3) & 0x03) << 1); + s_start = 6; + s_end = 0; + s_inc = -2; + } + else +#endif + { + sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); + dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); + s_start = 0; + s_end = 6; + s_inc = 2; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v; + int j; + + v = (png_byte)((*sp >> sshift) & 0x03); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + case 4: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); + int sshift, dshift; + int s_start, s_end, s_inc; + png_uint_32 i; + int jstop = png_pass_inc[pass]; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 1) & 0x01) << 2); + dshift = (int)(((final_width + 1) & 0x01) << 2); + s_start = 4; + s_end = 0; + s_inc = -4; + } + else +#endif + { + sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); + dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); + s_start = 0; + s_end = 4; + s_inc = 4; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v = (png_byte)((*sp >> sshift) & 0xf); + int j; + + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + default: + { + png_size_t pixel_bytes = (row_info->pixel_depth >> 3); + png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes; + png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; + + int jstop = png_pass_inc[pass]; + png_uint_32 i; + + for (i = 0; i < row_info->width; i++) + { + png_byte v[8]; + int j; + + png_memcpy(v, sp, pixel_bytes); + for (j = 0; j < jstop; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + sp -= pixel_bytes; + } + break; + } + } + row_info->width = final_width; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width); + } +#if !defined(PNG_READ_PACKSWAP_SUPPORTED) + if (&transformations == NULL) /* silence compiler warning */ + return; +#endif +} +#endif /* !PNG_HAVE_ASSEMBLER_READ_INTERLACE */ +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + +#ifndef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW +void /* PRIVATE */ +png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, + png_bytep prev_row, int filter) +{ + png_debug(1, "in png_read_filter_row\n"); + png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter); + switch (filter) + { + case PNG_FILTER_VALUE_NONE: + break; + case PNG_FILTER_VALUE_SUB: + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp = row + bpp; + png_bytep lp = row; + + for (i = bpp; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_UP: + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_bytep rp = row; + png_bytep pp = prev_row; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_AVG: + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop = row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++) / 2 )) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *lp++) / 2 ) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_PAETH: + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_bytep cp = prev_row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop=row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) /* use leftover rp,pp */ + { + int a, b, c, pa, pb, pc, p; + + a = *lp++; + b = *pp++; + c = *cp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + /* + if (pa <= pb && pa <= pc) + p = a; + else if (pb <= pc) + p = b; + else + p = c; + */ + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + *rp = (png_byte)(((int)(*rp) + p) & 0xff); + rp++; + } + break; + } + default: + png_warning(png_ptr, "Ignoring bad adaptive filter type"); + *row=0; + break; + } +} +#endif /* !PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */ + +void /* PRIVATE */ +png_read_finish_row(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* start of interlace block in the y direction */ + const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* offset to next interlace block in the y direction */ + const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + png_debug(1, "in png_read_finish_row\n"); + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + do + { + png_ptr->pass++; + if (png_ptr->pass >= 7) + break; + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + if (!(png_ptr->num_rows)) + continue; + } + else /* if (png_ptr->transformations & PNG_INTERLACE) */ + break; + } while (png_ptr->iwidth == 0); + + if (png_ptr->pass < 7) + return; + } + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IDAT; +#endif + char extra; + int ret; + + png_ptr->zstream.next_out = (Byte *)&extra; + png_ptr->zstream.avail_out = (uInt)1; + for(;;) + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_byte chunk_length[4]; + + png_crc_finish(png_ptr, 0); + + png_read_data(png_ptr, chunk_length, 4); + png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + + } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret == Z_STREAM_END) + { + if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_warning(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression Error"); + + if (!(png_ptr->zstream.avail_out)) + { + png_warning(png_ptr, "Extra compressed data."); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + + } + png_ptr->zstream.avail_out = 0; + } + + if (png_ptr->idat_size || png_ptr->zstream.avail_in) + png_warning(png_ptr, "Extra compression data"); + + inflateReset(&png_ptr->zstream); + + png_ptr->mode |= PNG_AFTER_IDAT; +} + +void /* PRIVATE */ +png_read_start_row(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* start of interlace block in the y direction */ + const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* offset to next interlace block in the y direction */ + const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + int max_pixel_depth; + png_uint_32 row_bytes; + + png_debug(1, "in png_read_start_row\n"); + png_ptr->zstream.avail_in = 0; + png_init_read_transformations(png_ptr); + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + else + png_ptr->num_rows = png_ptr->height; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1; + + png_ptr->irowbytes = (png_size_t)row_bytes; + if((png_uint_32)png_ptr->irowbytes != row_bytes) + png_error(png_ptr, "Rowbytes overflow in png_read_start_row"); + } + else + { + png_ptr->num_rows = png_ptr->height; + png_ptr->iwidth = png_ptr->width; + png_ptr->irowbytes = png_ptr->rowbytes + 1; + } + max_pixel_depth = png_ptr->pixel_depth; + +#if defined(PNG_READ_PACK_SUPPORTED) + if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) + max_pixel_depth = 8; +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans) + max_pixel_depth = 32; + else + max_pixel_depth = 24; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth < 8) + max_pixel_depth = 8; + if (png_ptr->num_trans) + max_pixel_depth *= 2; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (png_ptr->num_trans) + { + max_pixel_depth *= 4; + max_pixel_depth /= 3; + } + } + } +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & (PNG_FILLER)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + max_pixel_depth = 32; + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth <= 8) + max_pixel_depth = 16; + else + max_pixel_depth = 32; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (max_pixel_depth <= 32) + max_pixel_depth = 32; + else + max_pixel_depth = 64; + } + } +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + { + if ( +#if defined(PNG_READ_EXPAND_SUPPORTED) + (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || +#endif +#if defined(PNG_READ_FILLER_SUPPORTED) + (png_ptr->transformations & (PNG_FILLER)) || +#endif + png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (max_pixel_depth <= 16) + max_pixel_depth = 32; + else + max_pixel_depth = 64; + } + else + { + if (max_pixel_depth <= 8) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 32; + else + max_pixel_depth = 24; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 64; + else + max_pixel_depth = 48; + } + } +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ +defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + if(png_ptr->transformations & PNG_USER_TRANSFORM) + { + int user_pixel_depth=png_ptr->user_transform_depth* + png_ptr->user_transform_channels; + if(user_pixel_depth > max_pixel_depth) + max_pixel_depth=user_pixel_depth; + } +#endif + + /* align the width on the next larger 8 pixels. Mainly used + for interlacing */ + row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7)); + /* calculate the maximum bytes needed, adding a byte and a pixel + for safety's sake */ + row_bytes = PNG_ROWBYTES(max_pixel_depth,row_bytes) + + 1 + ((max_pixel_depth + 7) >> 3); +#ifdef PNG_MAX_MALLOC_64K + if (row_bytes > (png_uint_32)65536L) + png_error(png_ptr, "This image requires a row greater than 64KB"); +#endif + png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64); + png_ptr->row_buf = png_ptr->big_row_buf+32; +#if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD) + png_ptr->row_buf_size = row_bytes; +#endif + +#ifdef PNG_MAX_MALLOC_64K + if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L) + png_error(png_ptr, "This image requires a row greater than 64KB"); +#endif + if ((png_uint_32)png_ptr->rowbytes + 1 > PNG_SIZE_MAX) + png_error(png_ptr, "Row has too many bytes to allocate in memory."); + png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)( + png_ptr->rowbytes + 1)); + + png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + png_debug1(3, "width = %lu,\n", png_ptr->width); + png_debug1(3, "height = %lu,\n", png_ptr->height); + png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth); + png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows); + png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes); + png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes); + + png_ptr->flags |= PNG_FLAG_ROW_INIT; +} diff --git a/Utilities/FLTK/png/pngset.c b/Utilities/FLTK/png/pngset.c new file mode 100644 index 0000000000..39c5bfa700 --- /dev/null +++ b/Utilities/FLTK/png/pngset.c @@ -0,0 +1,1219 @@ + +/* pngset.c - storage of image information into info struct + * + * libpng 1.2.7 - September 12, 2004 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * The functions here are used during reads to store data from the file + * into the info struct, and during writes to store application data + * into the info struct for writing into the file. This abstracts the + * info struct and allows us to change the structure in the future. + */ + +#define PNG_INTERNAL +#include "png.h" + +#if defined(PNG_bKGD_SUPPORTED) +void PNGAPI +png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background) +{ + png_debug1(1, "in %s storage function\n", "bKGD"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16)); + info_ptr->valid |= PNG_INFO_bKGD; +} +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_cHRM(png_structp png_ptr, png_infop info_ptr, + double white_x, double white_y, double red_x, double red_y, + double green_x, double green_y, double blue_x, double blue_y) +{ + png_debug1(1, "in %s storage function\n", "cHRM"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (white_x < 0.0 || white_y < 0.0 || + red_x < 0.0 || red_y < 0.0 || + green_x < 0.0 || green_y < 0.0 || + blue_x < 0.0 || blue_y < 0.0) + { + png_warning(png_ptr, + "Ignoring attempt to set negative chromaticity value"); + return; + } + if (white_x > 21474.83 || white_y > 21474.83 || + red_x > 21474.83 || red_y > 21474.83 || + green_x > 21474.83 || green_y > 21474.83 || + blue_x > 21474.83 || blue_y > 21474.83) + { + png_warning(png_ptr, + "Ignoring attempt to set chromaticity value exceeding 21474.83"); + return; + } + + info_ptr->x_white = (float)white_x; + info_ptr->y_white = (float)white_y; + info_ptr->x_red = (float)red_x; + info_ptr->y_red = (float)red_y; + info_ptr->x_green = (float)green_x; + info_ptr->y_green = (float)green_y; + info_ptr->x_blue = (float)blue_x; + info_ptr->y_blue = (float)blue_y; +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_x_white = (png_fixed_point)(white_x*100000.+0.5); + info_ptr->int_y_white = (png_fixed_point)(white_y*100000.+0.5); + info_ptr->int_x_red = (png_fixed_point)( red_x*100000.+0.5); + info_ptr->int_y_red = (png_fixed_point)( red_y*100000.+0.5); + info_ptr->int_x_green = (png_fixed_point)(green_x*100000.+0.5); + info_ptr->int_y_green = (png_fixed_point)(green_y*100000.+0.5); + info_ptr->int_x_blue = (png_fixed_point)( blue_x*100000.+0.5); + info_ptr->int_y_blue = (png_fixed_point)( blue_y*100000.+0.5); +#endif + info_ptr->valid |= PNG_INFO_cHRM; +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, + png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y) +{ + png_debug1(1, "in %s storage function\n", "cHRM"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (white_x < 0 || white_y < 0 || + red_x < 0 || red_y < 0 || + green_x < 0 || green_y < 0 || + blue_x < 0 || blue_y < 0) + { + png_warning(png_ptr, + "Ignoring attempt to set negative chromaticity value"); + return; + } + if (white_x > (double) PNG_UINT_31_MAX || + white_y > (double) PNG_UINT_31_MAX || + red_x > (double) PNG_UINT_31_MAX || + red_y > (double) PNG_UINT_31_MAX || + green_x > (double) PNG_UINT_31_MAX || + green_y > (double) PNG_UINT_31_MAX || + blue_x > (double) PNG_UINT_31_MAX || + blue_y > (double) PNG_UINT_31_MAX) + { + png_warning(png_ptr, + "Ignoring attempt to set chromaticity value exceeding 21474.83"); + return; + } + info_ptr->int_x_white = white_x; + info_ptr->int_y_white = white_y; + info_ptr->int_x_red = red_x; + info_ptr->int_y_red = red_y; + info_ptr->int_x_green = green_x; + info_ptr->int_y_green = green_y; + info_ptr->int_x_blue = blue_x; + info_ptr->int_y_blue = blue_y; +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->x_white = (float)(white_x/100000.); + info_ptr->y_white = (float)(white_y/100000.); + info_ptr->x_red = (float)( red_x/100000.); + info_ptr->y_red = (float)( red_y/100000.); + info_ptr->x_green = (float)(green_x/100000.); + info_ptr->y_green = (float)(green_y/100000.); + info_ptr->x_blue = (float)( blue_x/100000.); + info_ptr->y_blue = (float)( blue_y/100000.); +#endif + info_ptr->valid |= PNG_INFO_cHRM; +} +#endif +#endif + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma) +{ + double gamma; + png_debug1(1, "in %s storage function\n", "gAMA"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Check for overflow */ + if (file_gamma > 21474.83) + { + png_warning(png_ptr, "Limiting gamma to 21474.83"); + gamma=21474.83; + } + else + gamma=file_gamma; + info_ptr->gamma = (float)gamma; +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = (int)(gamma*100000.+.5); +#endif + info_ptr->valid |= PNG_INFO_gAMA; + if(gamma == 0.0) + png_warning(png_ptr, "Setting gamma=0"); +} +#endif +void PNGAPI +png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point + int_gamma) +{ + png_fixed_point gamma; + + png_debug1(1, "in %s storage function\n", "gAMA"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (int_gamma > (png_fixed_point) PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Limiting gamma to 21474.83"); + gamma=PNG_UINT_31_MAX; + } + else + { + if (int_gamma < 0) + { + png_warning(png_ptr, "Setting negative gamma to zero"); + gamma=0; + } + else + gamma=int_gamma; + } +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->gamma = (float)(gamma/100000.); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = gamma; +#endif + info_ptr->valid |= PNG_INFO_gAMA; + if(gamma == 0) + png_warning(png_ptr, "Setting gamma=0"); +} +#endif + +#if defined(PNG_hIST_SUPPORTED) +void PNGAPI +png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist) +{ + int i; + + png_debug1(1, "in %s storage function\n", "hIST"); + if (png_ptr == NULL || info_ptr == NULL) + return; + if (info_ptr->num_palette == 0) + { + png_warning(png_ptr, + "Palette size 0, hIST allocation skipped."); + return; + } + +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); +#endif + /* Changed from info->num_palette to 256 in version 1.2.1 */ + png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr, + (png_uint_32)(256 * png_sizeof (png_uint_16))); + if (png_ptr->hist == NULL) + { + png_warning(png_ptr, "Insufficient memory for hIST chunk data."); + return; + } + + for (i = 0; i < info_ptr->num_palette; i++) + png_ptr->hist[i] = hist[i]; + info_ptr->hist = png_ptr->hist; + info_ptr->valid |= PNG_INFO_hIST; + +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_HIST; +#else + png_ptr->flags |= PNG_FLAG_FREE_HIST; +#endif +} +#endif + +void PNGAPI +png_set_IHDR(png_structp png_ptr, png_infop info_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) +{ + png_debug1(1, "in %s storage function\n", "IHDR"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* check for width and height valid values */ + if (width == 0 || height == 0) + png_error(png_ptr, "Image width or height is zero in IHDR"); +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (width > png_ptr->user_width_max || height > png_ptr->user_height_max) + png_error(png_ptr, "image size exceeds user limits in IHDR"); +#else + if (width > PNG_USER_WIDTH_MAX || height > PNG_USER_HEIGHT_MAX) + png_error(png_ptr, "image size exceeds user limits in IHDR"); +#endif + if (width > PNG_UINT_31_MAX || height > PNG_UINT_31_MAX) + png_error(png_ptr, "Invalid image size in IHDR"); + if ( width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 64 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + png_warning(png_ptr, "Width is too large for libpng to process pixels"); + + /* check other values */ + if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && + bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth in IHDR"); + + if (color_type < 0 || color_type == 1 || + color_type == 5 || color_type > 6) + png_error(png_ptr, "Invalid color type in IHDR"); + + if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) || + ((color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) + png_error(png_ptr, "Invalid color type/bit depth combination in IHDR"); + + if (interlace_type >= PNG_INTERLACE_LAST) + png_error(png_ptr, "Unknown interlace method in IHDR"); + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + png_error(png_ptr, "Unknown compression method in IHDR"); + +#if defined(PNG_MNG_FEATURES_SUPPORTED) + /* Accept filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not read a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted) + png_warning(png_ptr,"MNG features are not allowed in a PNG datastream\n"); + if(filter_type != PNG_FILTER_TYPE_BASE) + { + if(!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA))) + png_error(png_ptr, "Unknown filter method in IHDR"); + if(png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) + png_warning(png_ptr, "Invalid filter method in IHDR"); + } +#else + if(filter_type != PNG_FILTER_TYPE_BASE) + png_error(png_ptr, "Unknown filter method in IHDR"); +#endif + + info_ptr->width = width; + info_ptr->height = height; + info_ptr->bit_depth = (png_byte)bit_depth; + info_ptr->color_type =(png_byte) color_type; + info_ptr->compression_type = (png_byte)compression_type; + info_ptr->filter_type = (png_byte)filter_type; + info_ptr->interlace_type = (png_byte)interlace_type; + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + else + info_ptr->channels = 1; + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); + + /* check for potential overflow */ + if ( width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 64 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + info_ptr->rowbytes = (png_size_t)0; + else + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,width); +} + +#if defined(PNG_oFFs_SUPPORTED) +void PNGAPI +png_set_oFFs(png_structp png_ptr, png_infop info_ptr, + png_int_32 offset_x, png_int_32 offset_y, int unit_type) +{ + png_debug1(1, "in %s storage function\n", "oFFs"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_offset = offset_x; + info_ptr->y_offset = offset_y; + info_ptr->offset_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_oFFs; +} +#endif + +#if defined(PNG_pCAL_SUPPORTED) +void PNGAPI +png_set_pCAL(png_structp png_ptr, png_infop info_ptr, + png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, + png_charp units, png_charpp params) +{ + png_uint_32 length; + int i; + + png_debug1(1, "in %s storage function\n", "pCAL"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + length = png_strlen(purpose) + 1; + png_debug1(3, "allocating purpose for info (%lu bytes)\n", length); + info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->pcal_purpose == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL purpose."); + return; + } + png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length); + + png_debug(3, "storing X0, X1, type, and nparams in info\n"); + info_ptr->pcal_X0 = X0; + info_ptr->pcal_X1 = X1; + info_ptr->pcal_type = (png_byte)type; + info_ptr->pcal_nparams = (png_byte)nparams; + + length = png_strlen(units) + 1; + png_debug1(3, "allocating units for info (%lu bytes)\n", length); + info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->pcal_units == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL units."); + return; + } + png_memcpy(info_ptr->pcal_units, units, (png_size_t)length); + + info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr, + (png_uint_32)((nparams + 1) * png_sizeof(png_charp))); + if (info_ptr->pcal_params == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL params."); + return; + } + + info_ptr->pcal_params[nparams] = NULL; + + for (i = 0; i < nparams; i++) + { + length = png_strlen(params[i]) + 1; + png_debug2(3, "allocating parameter %d for info (%lu bytes)\n", i, length); + info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->pcal_params[i] == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL parameter."); + return; + } + png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length); + } + + info_ptr->valid |= PNG_INFO_pCAL; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_PCAL; +#endif +} +#endif + +#if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_sCAL(png_structp png_ptr, png_infop info_ptr, + int unit, double width, double height) +{ + png_debug1(1, "in %s storage function\n", "sCAL"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->scal_unit = (png_byte)unit; + info_ptr->scal_pixel_width = width; + info_ptr->scal_pixel_height = height; + + info_ptr->valid |= PNG_INFO_sCAL; +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, + int unit, png_charp swidth, png_charp sheight) +{ + png_uint_32 length; + + png_debug1(1, "in %s storage function\n", "sCAL"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->scal_unit = (png_byte)unit; + + length = png_strlen(swidth) + 1; + png_debug1(3, "allocating unit for info (%d bytes)\n", length); + info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->scal_s_width == NULL) + { + png_warning(png_ptr, "Memory allocation failed while processing sCAL."); + } + png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length); + + length = png_strlen(sheight) + 1; + png_debug1(3, "allocating unit for info (%d bytes)\n", length); + info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->scal_s_height == NULL) + { + png_free (png_ptr, info_ptr->scal_s_width); + png_warning(png_ptr, "Memory allocation failed while processing sCAL."); + } + png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length); + + info_ptr->valid |= PNG_INFO_sCAL; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_SCAL; +#endif +} +#endif +#endif +#endif + +#if defined(PNG_pHYs_SUPPORTED) +void PNGAPI +png_set_pHYs(png_structp png_ptr, png_infop info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type) +{ + png_debug1(1, "in %s storage function\n", "pHYs"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_pixels_per_unit = res_x; + info_ptr->y_pixels_per_unit = res_y; + info_ptr->phys_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_pHYs; +} +#endif + +void PNGAPI +png_set_PLTE(png_structp png_ptr, png_infop info_ptr, + png_colorp palette, int num_palette) +{ + + png_debug1(1, "in %s storage function\n", "PLTE"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* + * It may not actually be necessary to set png_ptr->palette here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); +#endif + + /* Changed in libpng-1.2.1 to allocate 256 instead of num_palette entries, + in case of an invalid PNG file that has too-large sample values. */ + png_ptr->palette = (png_colorp)png_malloc(png_ptr, + 256 * png_sizeof(png_color)); + png_memset(png_ptr->palette, 0, 256 * png_sizeof(png_color)); + png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof (png_color)); + info_ptr->palette = png_ptr->palette; + info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; + +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_PLTE; +#else + png_ptr->flags |= PNG_FLAG_FREE_PLTE; +#endif + + info_ptr->valid |= PNG_INFO_PLTE; +} + +#if defined(PNG_sBIT_SUPPORTED) +void PNGAPI +png_set_sBIT(png_structp png_ptr, png_infop info_ptr, + png_color_8p sig_bit) +{ + png_debug1(1, "in %s storage function\n", "sBIT"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof (png_color_8)); + info_ptr->valid |= PNG_INFO_sBIT; +} +#endif + +#if defined(PNG_sRGB_SUPPORTED) +void PNGAPI +png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent) +{ + png_debug1(1, "in %s storage function\n", "sRGB"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->srgb_intent = (png_byte)intent; + info_ptr->valid |= PNG_INFO_sRGB; +} + +void PNGAPI +png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, + int intent) +{ +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED + float file_gamma; +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_fixed_point int_file_gamma; +#endif +#endif +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED + float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, + int_green_y, int_blue_x, int_blue_y; +#endif +#endif + png_debug1(1, "in %s storage function\n", "sRGB_gAMA_and_cHRM"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_set_sRGB(png_ptr, info_ptr, intent); + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED + file_gamma = (float).45455; + png_set_gAMA(png_ptr, info_ptr, file_gamma); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + int_file_gamma = 45455L; + png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); +#endif +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FIXED_POINT_SUPPORTED + int_white_x = 31270L; + int_white_y = 32900L; + int_red_x = 64000L; + int_red_y = 33000L; + int_green_x = 30000L; + int_green_y = 60000L; + int_blue_x = 15000L; + int_blue_y = 6000L; + + png_set_cHRM_fixed(png_ptr, info_ptr, + int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, int_green_y, + int_blue_x, int_blue_y); +#endif +#ifdef PNG_FLOATING_POINT_SUPPORTED + white_x = (float).3127; + white_y = (float).3290; + red_x = (float).64; + red_y = (float).33; + green_x = (float).30; + green_y = (float).60; + blue_x = (float).15; + blue_y = (float).06; + + png_set_cHRM(png_ptr, info_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); +#endif +#endif +} +#endif + + +#if defined(PNG_iCCP_SUPPORTED) +void PNGAPI +png_set_iCCP(png_structp png_ptr, png_infop info_ptr, + png_charp name, int compression_type, + png_charp profile, png_uint_32 proflen) +{ + png_charp new_iccp_name; + png_charp new_iccp_profile; + + png_debug1(1, "in %s storage function\n", "iCCP"); + if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) + return; + + new_iccp_name = (png_charp)png_malloc_warn(png_ptr, png_strlen(name)+1); + if (new_iccp_name == NULL) + { + png_warning(png_ptr, "Insufficient memory to process iCCP chunk."); + return; + } + png_strcpy(new_iccp_name, name); + new_iccp_profile = (png_charp)png_malloc_warn(png_ptr, proflen); + if (new_iccp_profile == NULL) + { + png_free (png_ptr, new_iccp_name); + png_warning(png_ptr, "Insufficient memory to process iCCP profile."); + return; + } + png_memcpy(new_iccp_profile, profile, (png_size_t)proflen); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); + + info_ptr->iccp_proflen = proflen; + info_ptr->iccp_name = new_iccp_name; + info_ptr->iccp_profile = new_iccp_profile; + /* Compression is always zero but is here so the API and info structure + * does not have to change if we introduce multiple compression types */ + info_ptr->iccp_compression = (png_byte)compression_type; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_ICCP; +#endif + info_ptr->valid |= PNG_INFO_iCCP; +} +#endif + +#if defined(PNG_TEXT_SUPPORTED) +void PNGAPI +png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, + int num_text) +{ + int ret; + ret=png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); + if (ret) + png_error(png_ptr, "Insufficient memory to store text"); +} + +int /* PRIVATE */ +png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, + int num_text) +{ + int i; + + png_debug1(1, "in %s storage function\n", (png_ptr->chunk_name[0] == '\0' ? + "text" : (png_const_charp)png_ptr->chunk_name)); + + if (png_ptr == NULL || info_ptr == NULL || num_text == 0) + return(0); + + /* Make sure we have enough space in the "text" array in info_struct + * to hold all of the incoming text_ptr objects. + */ + if (info_ptr->num_text + num_text > info_ptr->max_text) + { + if (info_ptr->text != NULL) + { + png_textp old_text; + int old_max; + + old_max = info_ptr->max_text; + info_ptr->max_text = info_ptr->num_text + num_text + 8; + old_text = info_ptr->text; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)(info_ptr->max_text * png_sizeof (png_text))); + if (info_ptr->text == NULL) + { + png_free(png_ptr, old_text); + return(1); + } + png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * + png_sizeof(png_text))); + png_free(png_ptr, old_text); + } + else + { + info_ptr->max_text = num_text + 8; + info_ptr->num_text = 0; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)(info_ptr->max_text * png_sizeof (png_text))); + if (info_ptr->text == NULL) + return(1); +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_TEXT; +#endif + } + png_debug1(3, "allocated %d entries for info_ptr->text\n", + info_ptr->max_text); + } + for (i = 0; i < num_text; i++) + { + png_size_t text_length,key_len; + png_size_t lang_len,lang_key_len; + png_textp textp = &(info_ptr->text[info_ptr->num_text]); + + if (text_ptr[i].key == NULL) + continue; + + key_len = png_strlen(text_ptr[i].key); + + if(text_ptr[i].compression <= 0) + { + lang_len = 0; + lang_key_len = 0; + } + else +#ifdef PNG_iTXt_SUPPORTED + { + /* set iTXt data */ + if (text_ptr[i].lang != NULL) + lang_len = png_strlen(text_ptr[i].lang); + else + lang_len = 0; + if (text_ptr[i].lang_key != NULL) + lang_key_len = png_strlen(text_ptr[i].lang_key); + else + lang_key_len = 0; + } +#else + { + png_warning(png_ptr, "iTXt chunk not supported."); + continue; + } +#endif + + if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') + { + text_length = 0; +#ifdef PNG_iTXt_SUPPORTED + if(text_ptr[i].compression > 0) + textp->compression = PNG_ITXT_COMPRESSION_NONE; + else +#endif + textp->compression = PNG_TEXT_COMPRESSION_NONE; + } + else + { + text_length = png_strlen(text_ptr[i].text); + textp->compression = text_ptr[i].compression; + } + + textp->key = (png_charp)png_malloc_warn(png_ptr, + (png_uint_32)(key_len + text_length + lang_len + lang_key_len + 4)); + if (textp->key == NULL) + return(1); + png_debug2(2, "Allocated %lu bytes at %x in png_set_text\n", + (png_uint_32)(key_len + lang_len + lang_key_len + text_length + 4), + (int)textp->key); + + png_memcpy(textp->key, text_ptr[i].key, + (png_size_t)(key_len)); + *(textp->key+key_len) = '\0'; +#ifdef PNG_iTXt_SUPPORTED + if (text_ptr[i].compression > 0) + { + textp->lang=textp->key + key_len + 1; + png_memcpy(textp->lang, text_ptr[i].lang, lang_len); + *(textp->lang+lang_len) = '\0'; + textp->lang_key=textp->lang + lang_len + 1; + png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); + *(textp->lang_key+lang_key_len) = '\0'; + textp->text=textp->lang_key + lang_key_len + 1; + } + else +#endif + { +#ifdef PNG_iTXt_SUPPORTED + textp->lang=NULL; + textp->lang_key=NULL; +#endif + textp->text=textp->key + key_len + 1; + } + if(text_length) + png_memcpy(textp->text, text_ptr[i].text, + (png_size_t)(text_length)); + *(textp->text+text_length) = '\0'; + +#ifdef PNG_iTXt_SUPPORTED + if(textp->compression > 0) + { + textp->text_length = 0; + textp->itxt_length = text_length; + } + else +#endif + { + textp->text_length = text_length; +#ifdef PNG_iTXt_SUPPORTED + textp->itxt_length = 0; +#endif + } + info_ptr->text[info_ptr->num_text]= *textp; + info_ptr->num_text++; + png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text); + } + return(0); +} +#endif + +#if defined(PNG_tIME_SUPPORTED) +void PNGAPI +png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time) +{ + png_debug1(1, "in %s storage function\n", "tIME"); + if (png_ptr == NULL || info_ptr == NULL || + (png_ptr->mode & PNG_WROTE_tIME)) + return; + + png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof (png_time)); + info_ptr->valid |= PNG_INFO_tIME; +} +#endif + +#if defined(PNG_tRNS_SUPPORTED) +void PNGAPI +png_set_tRNS(png_structp png_ptr, png_infop info_ptr, + png_bytep trans, int num_trans, png_color_16p trans_values) +{ + png_debug1(1, "in %s storage function\n", "tRNS"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (trans != NULL) + { + /* + * It may not actually be necessary to set png_ptr->trans here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); +#endif + /* Changed from num_trans to 256 in version 1.2.1 */ + png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans); +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_TRNS; +#else + png_ptr->flags |= PNG_FLAG_FREE_TRNS; +#endif + } + + if (trans_values != NULL) + { + png_memcpy(&(info_ptr->trans_values), trans_values, + png_sizeof(png_color_16)); + if (num_trans == 0) + num_trans = 1; + } + info_ptr->num_trans = (png_uint_16)num_trans; + info_ptr->valid |= PNG_INFO_tRNS; +} +#endif + +#if defined(PNG_sPLT_SUPPORTED) +void PNGAPI +png_set_sPLT(png_structp png_ptr, + png_infop info_ptr, png_sPLT_tp entries, int nentries) +{ + png_sPLT_tp np; + int i; + + np = (png_sPLT_tp)png_malloc_warn(png_ptr, + (info_ptr->splt_palettes_num + nentries) * png_sizeof(png_sPLT_t)); + if (np == NULL) + { + png_warning(png_ptr, "No memory for sPLT palettes."); + return; + } + + png_memcpy(np, info_ptr->splt_palettes, + info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t)); + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes=NULL; + + for (i = 0; i < nentries; i++) + { + png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; + png_sPLT_tp from = entries + i; + + to->name = (png_charp)png_malloc(png_ptr, + png_strlen(from->name) + 1); + /* TODO: use png_malloc_warn */ + png_strcpy(to->name, from->name); + to->entries = (png_sPLT_entryp)png_malloc(png_ptr, + from->nentries * png_sizeof(png_sPLT_t)); + /* TODO: use png_malloc_warn */ + png_memcpy(to->entries, from->entries, + from->nentries * png_sizeof(png_sPLT_t)); + to->nentries = from->nentries; + to->depth = from->depth; + } + + info_ptr->splt_palettes = np; + info_ptr->splt_palettes_num += nentries; + info_ptr->valid |= PNG_INFO_sPLT; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_SPLT; +#endif +} +#endif /* PNG_sPLT_SUPPORTED */ + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +void PNGAPI +png_set_unknown_chunks(png_structp png_ptr, + png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns) +{ + png_unknown_chunkp np; + int i; + + if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0) + return; + + np = (png_unknown_chunkp)png_malloc_warn(png_ptr, + (info_ptr->unknown_chunks_num + num_unknowns) * + png_sizeof(png_unknown_chunk)); + if (np == NULL) + { + png_warning(png_ptr, "Out of memory while processing unknown chunk."); + return; + } + + png_memcpy(np, info_ptr->unknown_chunks, + info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk)); + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks=NULL; + + for (i = 0; i < num_unknowns; i++) + { + png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i; + png_unknown_chunkp from = unknowns + i; + + png_strncpy((png_charp)to->name, (png_charp)from->name, 5); + to->data = (png_bytep)png_malloc_warn(png_ptr, from->size); + if (to->data == NULL) + { + png_warning(png_ptr, "Out of memory processing unknown chunk."); + } + else + { + png_memcpy(to->data, from->data, from->size); + to->size = from->size; + + /* note our location in the read or write sequence */ + to->location = (png_byte)(png_ptr->mode & 0xff); + } + } + + info_ptr->unknown_chunks = np; + info_ptr->unknown_chunks_num += num_unknowns; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_UNKN; +#endif +} +void PNGAPI +png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr, + int chunk, int location) +{ + if(png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk < + (int)info_ptr->unknown_chunks_num) + info_ptr->unknown_chunks[chunk].location = (png_byte)location; +} +#endif + +#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +void PNGAPI +png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted) +{ + /* This function is deprecated in favor of png_permit_mng_features() + and will be removed from libpng-2.0.0 */ + png_debug(1, "in png_permit_empty_plte, DEPRECATED.\n"); + if (png_ptr == NULL) + return; + png_ptr->mng_features_permitted = (png_byte) + ((png_ptr->mng_features_permitted & (~(PNG_FLAG_MNG_EMPTY_PLTE))) | + ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE))); +} +#endif + +#if defined(PNG_MNG_FEATURES_SUPPORTED) +png_uint_32 PNGAPI +png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features) +{ + png_debug(1, "in png_permit_mng_features\n"); + if (png_ptr == NULL) + return (png_uint_32)0; + png_ptr->mng_features_permitted = + (png_byte)(mng_features & PNG_ALL_MNG_FEATURES); + return (png_uint_32)png_ptr->mng_features_permitted; +} +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +void PNGAPI +png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep + chunk_list, int num_chunks) +{ + png_bytep new_list, p; + int i, old_num_chunks; + if (num_chunks == 0) + { + if(keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE) + png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + + if(keep == PNG_HANDLE_CHUNK_ALWAYS) + png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS; + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS; + return; + } + if (chunk_list == NULL) + return; + old_num_chunks=png_ptr->num_chunk_list; + new_list=(png_bytep)png_malloc(png_ptr, + (png_uint_32)(5*(num_chunks+old_num_chunks))); + if(png_ptr->chunk_list != NULL) + { + png_memcpy(new_list, png_ptr->chunk_list, + (png_size_t)(5*old_num_chunks)); + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + } + png_memcpy(new_list+5*old_num_chunks, chunk_list, + (png_size_t)(5*num_chunks)); + for (p=new_list+5*old_num_chunks+4, i=0; i<num_chunks; i++, p+=5) + *p=(png_byte)keep; + png_ptr->num_chunk_list=old_num_chunks+num_chunks; + png_ptr->chunk_list=new_list; +#ifdef PNG_FREE_ME_SUPPORTED + png_ptr->free_me |= PNG_FREE_LIST; +#endif +} +#endif + +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) +void PNGAPI +png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr, + png_user_chunk_ptr read_user_chunk_fn) +{ + png_debug(1, "in png_set_read_user_chunk_fn\n"); + png_ptr->read_user_chunk_fn = read_user_chunk_fn; + png_ptr->user_chunk_ptr = user_chunk_ptr; +} +#endif + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +void PNGAPI +png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) +{ + png_debug1(1, "in %s storage function\n", "rows"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if(info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + info_ptr->row_pointers = row_pointers; + if(row_pointers) + info_ptr->valid |= PNG_INFO_IDAT; +} +#endif + +#ifdef PNG_WRITE_SUPPORTED +void PNGAPI +png_set_compression_buffer_size(png_structp png_ptr, png_uint_32 size) +{ + if(png_ptr->zbuf) + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf_size = (png_size_t)size; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; +} +#endif + +void PNGAPI +png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask) +{ + if (png_ptr && info_ptr) + info_ptr->valid &= ~(mask); +} + + +#ifndef PNG_1_0_X +#ifdef PNG_ASSEMBLER_CODE_SUPPORTED +/* this function was added to libpng 1.2.0 and should always exist by default */ +void PNGAPI +png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags) +{ + png_uint_32 settable_asm_flags; + png_uint_32 settable_mmx_flags; + + settable_mmx_flags = +#ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW + PNG_ASM_FLAG_MMX_READ_COMBINE_ROW | +#endif +#ifdef PNG_HAVE_ASSEMBLER_READ_INTERLACE + PNG_ASM_FLAG_MMX_READ_INTERLACE | +#endif +#ifdef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW + PNG_ASM_FLAG_MMX_READ_FILTER_SUB | + PNG_ASM_FLAG_MMX_READ_FILTER_UP | + PNG_ASM_FLAG_MMX_READ_FILTER_AVG | + PNG_ASM_FLAG_MMX_READ_FILTER_PAETH | +#endif + 0; + + /* could be some non-MMX ones in the future, but not currently: */ + settable_asm_flags = settable_mmx_flags; + + if (!(png_ptr->asm_flags & PNG_ASM_FLAG_MMX_SUPPORT_COMPILED) || + !(png_ptr->asm_flags & PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU)) + { + /* clear all MMX flags if MMX isn't supported */ + settable_asm_flags &= ~settable_mmx_flags; + png_ptr->asm_flags &= ~settable_mmx_flags; + } + + /* we're replacing the settable bits with those passed in by the user, + * so first zero them out of the master copy, then logical-OR in the + * allowed subset that was requested */ + + png_ptr->asm_flags &= ~settable_asm_flags; /* zero them */ + png_ptr->asm_flags |= (asm_flags & settable_asm_flags); /* set them */ +} +#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ + +#ifdef PNG_ASSEMBLER_CODE_SUPPORTED +/* this function was added to libpng 1.2.0 */ +void PNGAPI +png_set_mmx_thresholds (png_structp png_ptr, + png_byte mmx_bitdepth_threshold, + png_uint_32 mmx_rowbytes_threshold) +{ + png_ptr->mmx_bitdepth_threshold = mmx_bitdepth_threshold; + png_ptr->mmx_rowbytes_threshold = mmx_rowbytes_threshold; +} +#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* this function was added to libpng 1.2.6 */ +void PNGAPI +png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max, + png_uint_32 user_height_max) +{ + /* Images with dimensions larger than these limits will be + * rejected by png_set_IHDR(). To accept any PNG datastream + * regardless of dimensions, set both limits to 0x7ffffffL. + */ + png_ptr->user_width_max = user_width_max; + png_ptr->user_height_max = user_height_max; +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + +#endif /* ?PNG_1_0_X */ diff --git a/Utilities/FLTK/png/pngtrans.c b/Utilities/FLTK/png/pngtrans.c new file mode 100644 index 0000000000..f3e5766289 --- /dev/null +++ b/Utilities/FLTK/png/pngtrans.c @@ -0,0 +1,644 @@ + +/* pngtrans.c - transforms the data in a row (used by both readers and writers) + * + * libpng 1.2.7 - September 12, 2004 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* turn on BGR-to-RGB mapping */ +void PNGAPI +png_set_bgr(png_structp png_ptr) +{ + png_debug(1, "in png_set_bgr\n"); + png_ptr->transformations |= PNG_BGR; +} +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* turn on 16 bit byte swapping */ +void PNGAPI +png_set_swap(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap\n"); + if (png_ptr->bit_depth == 16) + png_ptr->transformations |= PNG_SWAP_BYTES; +} +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* turn on pixel packing */ +void PNGAPI +png_set_packing(png_structp png_ptr) +{ + png_debug(1, "in png_set_packing\n"); + if (png_ptr->bit_depth < 8) + { + png_ptr->transformations |= PNG_PACK; + png_ptr->usr_bit_depth = 8; + } +} +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* turn on packed pixel swapping */ +void PNGAPI +png_set_packswap(png_structp png_ptr) +{ + png_debug(1, "in png_set_packswap\n"); + if (png_ptr->bit_depth < 8) + png_ptr->transformations |= PNG_PACKSWAP; +} +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +void PNGAPI +png_set_shift(png_structp png_ptr, png_color_8p true_bits) +{ + png_debug(1, "in png_set_shift\n"); + png_ptr->transformations |= PNG_SHIFT; + png_ptr->shift = *true_bits; +} +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +int PNGAPI +png_set_interlace_handling(png_structp png_ptr) +{ + png_debug(1, "in png_set_interlace handling\n"); + if (png_ptr->interlaced) + { + png_ptr->transformations |= PNG_INTERLACE; + return (7); + } + + return (1); +} +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte on read, or remove a filler or alpha byte on write. + * The filler type has changed in v0.95 to allow future 2-byte fillers + * for 48-bit input data, as well as to avoid problems with some compilers + * that don't like bytes as parameters. + */ +void PNGAPI +png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_filler\n"); + png_ptr->transformations |= PNG_FILLER; + png_ptr->filler = (png_byte)filler; + if (filler_loc == PNG_FILLER_AFTER) + png_ptr->flags |= PNG_FLAG_FILLER_AFTER; + else + png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; + + /* This should probably go in the "do_read_filler" routine. + * I attempted to do that in libpng-1.0.1a but that caused problems + * so I restored it in libpng-1.0.2a + */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_ptr->usr_channels = 4; + } + + /* Also I added this in libpng-1.0.2a (what happens when we expand + * a less-than-8-bit grayscale to GA? */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8) + { + png_ptr->usr_channels = 2; + } +} + +#if !defined(PNG_1_0_X) +/* Added to libpng-1.2.7 */ +void PNGAPI +png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_add_alpha\n"); + png_set_filler(png_ptr, filler, filler_loc); + png_ptr->transformations |= PNG_ADD_ALPHA; +} +#endif + +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +void PNGAPI +png_set_swap_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap_alpha\n"); + png_ptr->transformations |= PNG_SWAP_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +void PNGAPI +png_set_invert_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_alpha\n"); + png_ptr->transformations |= PNG_INVERT_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +void PNGAPI +png_set_invert_mono(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_mono\n"); + png_ptr->transformations |= PNG_INVERT_MONO; +} + +/* invert monochrome grayscale data */ +void /* PRIVATE */ +png_do_invert(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_invert\n"); + /* This test removed from libpng version 1.0.13 and 1.2.0: + * if (row_info->bit_depth == 1 && + */ +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row == NULL || row_info == NULL) + return; +#endif + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(~(*rp)); + rp++; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 8) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (i = 0; i < istop; i+=2) + { + *rp = (png_byte)(~(*rp)); + rp+=2; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 16) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (i = 0; i < istop; i+=4) + { + *rp = (png_byte)(~(*rp)); + *(rp+1) = (png_byte)(~(*(rp+1))); + rp+=4; + } + } +} +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* swaps byte order on 16 bit depth images */ +void /* PRIVATE */ +png_do_swap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_swap\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->bit_depth == 16) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop= row_info->width * row_info->channels; + + for (i = 0; i < istop; i++, rp += 2) + { + png_byte t = *rp; + *rp = *(rp + 1); + *(rp + 1) = t; + } + } +} +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +static png_byte onebppswaptable[256] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; + +static png_byte twobppswaptable[256] = { + 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0, + 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0, + 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4, + 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4, + 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8, + 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8, + 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC, + 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC, + 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1, + 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1, + 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5, + 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5, + 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9, + 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9, + 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD, + 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD, + 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2, + 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2, + 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6, + 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6, + 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA, + 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA, + 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE, + 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE, + 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3, + 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3, + 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7, + 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7, + 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB, + 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB, + 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF, + 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF +}; + +static png_byte fourbppswaptable[256] = { + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, + 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, + 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, + 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, + 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2, + 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, + 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, + 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, + 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, + 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, + 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, + 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, + 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, + 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, + 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7, + 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, + 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, + 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, + 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9, + 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, + 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA, + 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, + 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, + 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, + 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC, + 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, + 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, + 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, + 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE, + 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, + 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF +}; + +/* swaps pixel packing order within bytes */ +void /* PRIVATE */ +png_do_packswap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_packswap\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->bit_depth < 8) + { + png_bytep rp, end, table; + + end = row + row_info->rowbytes; + + if (row_info->bit_depth == 1) + table = onebppswaptable; + else if (row_info->bit_depth == 2) + table = twobppswaptable; + else if (row_info->bit_depth == 4) + table = fourbppswaptable; + else + return; + + for (rp = row; rp < end; rp++) + *rp = table[*rp]; + } +} +#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */ + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +/* remove filler or alpha byte(s) */ +void /* PRIVATE */ +png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) +{ + png_debug(1, "in png_do_strip_filler\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + png_bytep sp=row; + png_bytep dp=row; + png_uint_32 row_width=row_info->width; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB && + row_info->channels == 4) + { + if (row_info->bit_depth == 8) + { + /* This converts from RGBX or RGBA to RGB */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + dp+=3; sp+=4; + for (i = 1; i < row_width; i++) + { + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + sp++; + } + } + /* This converts from XRGB or ARGB to RGB */ + else + { + for (i = 0; i < row_width; i++) + { + sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + } + else /* if (row_info->bit_depth == 16) */ + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */ + sp += 8; dp += 6; + for (i = 1; i < row_width; i++) + { + /* This could be (although png_memcpy is probably slower): + png_memcpy(dp, sp, 6); + sp += 8; + dp += 6; + */ + + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + sp += 2; + } + } + else + { + /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */ + for (i = 0; i < row_width; i++) + { + /* This could be (although png_memcpy is probably slower): + png_memcpy(dp, sp, 6); + sp += 8; + dp += 6; + */ + + sp+=2; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 48; + row_info->rowbytes = row_width * 6; + } + row_info->channels = 3; + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY && + row_info->channels == 2) + { + if (row_info->bit_depth == 8) + { + /* This converts from GX or GA to G */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + for (i = 0; i < row_width; i++) + { + *dp++ = *sp++; + sp++; + } + } + /* This converts from XG or AG to G */ + else + { + for (i = 0; i < row_width; i++) + { + sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + else /* if (row_info->bit_depth == 16) */ + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This converts from GGXX or GGAA to GG */ + sp += 4; dp += 2; + for (i = 1; i < row_width; i++) + { + *dp++ = *sp++; + *dp++ = *sp++; + sp += 2; + } + } + else + { + /* This converts from XXGG or AAGG to GG */ + for (i = 0; i < row_width; i++) + { + sp += 2; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + row_info->channels = 1; + } + } +} +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* swaps red and blue bytes within a pixel */ +void /* PRIVATE */ +png_do_bgr(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_bgr\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 3) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 4) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + } + else if (row_info->bit_depth == 16) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 6) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 8) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + } + } +} +#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +void PNGAPI +png_set_user_transform_info(png_structp png_ptr, png_voidp + user_transform_ptr, int user_transform_depth, int user_transform_channels) +{ + png_debug(1, "in png_set_user_transform_info\n"); +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + png_ptr->user_transform_ptr = user_transform_ptr; + png_ptr->user_transform_depth = (png_byte)user_transform_depth; + png_ptr->user_transform_channels = (png_byte)user_transform_channels; +#else + if(user_transform_ptr || user_transform_depth || user_transform_channels) + png_warning(png_ptr, + "This version of libpng does not support user transform info"); +#endif +} +#endif + +/* This function returns a pointer to the user_transform_ptr associated with + * the user transform functions. The application should free any memory + * associated with this pointer before png_write_destroy and png_read_destroy + * are called. + */ +png_voidp PNGAPI +png_get_user_transform_ptr(png_structp png_ptr) +{ +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + return ((png_voidp)png_ptr->user_transform_ptr); +#else + if(png_ptr) + return (NULL); + return (NULL); +#endif +} diff --git a/Utilities/FLTK/png/pngwio.c b/Utilities/FLTK/png/pngwio.c new file mode 100644 index 0000000000..d569b6851f --- /dev/null +++ b/Utilities/FLTK/png/pngwio.c @@ -0,0 +1,228 @@ + +/* pngwio.c - functions for data output + * + * libpng 1.2.7 - September 12, 2004 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file provides a location for all output. Users who need + * special handling are expected to write functions that have the same + * arguments as these and perform similar functions, but that possibly + * use different output methods. Note that you shouldn't change these + * functions, but rather write replacement functions and then change + * them at run time with png_set_write_fn(...). + */ + +#define PNG_INTERNAL +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Write the data to whatever output you are using. The default routine + writes to a file pointer. Note that this routine sometimes gets called + with very small lengths, so you should implement some kind of simple + buffering if you are using unbuffered writes. This should never be asked + to write more than 64K on a 16 bit machine. */ + +void /* PRIVATE */ +png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + if (png_ptr->write_data_fn != NULL ) + (*(png_ptr->write_data_fn))(png_ptr, data, length); + else + png_error(png_ptr, "Call to NULL write function"); +} + +#if !defined(PNG_NO_STDIO) +/* This is the function that does the actual writing of data. If you are + not writing to a standard C stream, you should create a replacement + write_data function and use it at run time with png_set_write_fn(), rather + than changing the library. */ +#ifndef USE_FAR_KEYWORD +void PNGAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + +#if defined(_WIN32_WCE) + if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) + check = 0; +#else + check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); +#endif + if (check != length) + png_error(png_ptr, "Write Error"); +} +#else +/* this is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +void PNGAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + near_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)near_data == data) + { +#if defined(_WIN32_WCE) + if ( !WriteFile(io_ptr, near_data, length, &check, NULL) ) + check = 0; +#else + check = fwrite(near_data, 1, length, io_ptr); +#endif + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t written, remaining, err; + check = 0; + remaining = length; + do + { + written = MIN(NEAR_BUF_SIZE, remaining); + png_memcpy(buf, data, written); /* copy far buffer to near buffer */ +#if defined(_WIN32_WCE) + if ( !WriteFile(io_ptr, buf, written, &err, NULL) ) + err = 0; +#else + err = fwrite(buf, 1, written, io_ptr); +#endif + if (err != written) + break; + else + check += err; + data += written; + remaining -= written; + } + while (remaining != 0); + } + if (check != length) + png_error(png_ptr, "Write Error"); +} + +#endif +#endif + +/* This function is called to output any data pending writing (normally + to disk). After png_flush is called, there should be no data pending + writing in any buffers. */ +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +void /* PRIVATE */ +png_flush(png_structp png_ptr) +{ + if (png_ptr->output_flush_fn != NULL) + (*(png_ptr->output_flush_fn))(png_ptr); +} + +#if !defined(PNG_NO_STDIO) +void PNGAPI +png_default_flush(png_structp png_ptr) +{ +#if !defined(_WIN32_WCE) + png_FILE_p io_ptr; + io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); + if (io_ptr != NULL) + fflush(io_ptr); +#endif +} +#endif +#endif + +/* This function allows the application to supply new output functions for + libpng if standard C streams aren't being used. + + This function takes as its arguments: + png_ptr - pointer to a png output data structure + io_ptr - pointer to user supplied structure containing info about + the output functions. May be NULL. + write_data_fn - pointer to a new output function that takes as its + arguments a pointer to a png_struct, a pointer to + data to be written, and a 32-bit unsigned int that is + the number of bytes to be written. The new write + function should call png_error(png_ptr, "Error msg") + to exit and output any fatal error messages. + flush_data_fn - pointer to a new flush function that takes as its + arguments a pointer to a png_struct. After a call to + the flush function, there should be no data in any buffers + or pending transmission. If the output method doesn't do + any buffering of ouput, a function prototype must still be + supplied although it doesn't have to do anything. If + PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile + time, output_flush_fn will be ignored, although it must be + supplied for compatibility. */ +void PNGAPI +png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) +{ + png_ptr->io_ptr = io_ptr; + +#if !defined(PNG_NO_STDIO) + if (write_data_fn != NULL) + png_ptr->write_data_fn = write_data_fn; + else + png_ptr->write_data_fn = png_default_write_data; +#else + png_ptr->write_data_fn = write_data_fn; +#endif + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +#if !defined(PNG_NO_STDIO) + if (output_flush_fn != NULL) + png_ptr->output_flush_fn = output_flush_fn; + else + png_ptr->output_flush_fn = png_default_flush; +#else + png_ptr->output_flush_fn = output_flush_fn; +#endif +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + + /* It is an error to read while writing a png file */ + if (png_ptr->read_data_fn != NULL) + { + png_ptr->read_data_fn = NULL; + png_warning(png_ptr, + "Attempted to set both read_data_fn and write_data_fn in"); + png_warning(png_ptr, + "the same structure. Resetting read_data_fn to NULL."); + } +} + +#if defined(USE_FAR_KEYWORD) +#if defined(_MSC_VER) +void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + FP_OFF(near_ptr) = FP_OFF(ptr); + far_ptr = (void FAR *)near_ptr; + if(check != 0) + if(FP_SEG(ptr) != FP_SEG(far_ptr)) + png_error(png_ptr,"segment lost in conversion"); + return(near_ptr); +} +# else +void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + near_ptr = (void FAR *)ptr; + far_ptr = (void FAR *)near_ptr; + if(check != 0) + if(far_ptr != ptr) + png_error(png_ptr,"segment lost in conversion"); + return(near_ptr); +} +# endif +# endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/Utilities/FLTK/png/pngwrite.c b/Utilities/FLTK/png/pngwrite.c new file mode 100644 index 0000000000..6cb539b46b --- /dev/null +++ b/Utilities/FLTK/png/pngwrite.c @@ -0,0 +1,1464 @@ + +/* pngwrite.c - general routines to write a PNG file + * + * libpng 1.2.7 - September 12, 2004 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +/* get internal access to png.h */ +#define PNG_INTERNAL +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Writes all the PNG information. This is the suggested way to use the + * library. If you have a new chunk to add, make a function to write it, + * and put it in the correct location here. If you want the chunk written + * after the image data, put it in png_write_end(). I strongly encourage + * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing + * the chunk, as that will keep the code from breaking if you want to just + * write a plain PNG file. If you have long comments, I suggest writing + * them in png_write_end(), and compressing them. + */ +void PNGAPI +png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_info_before_PLTE\n"); + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + { + png_write_sig(png_ptr); /* write PNG signature */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) + if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted)) + { + png_warning(png_ptr,"MNG features are not allowed in a PNG datastream\n"); + png_ptr->mng_features_permitted=0; + } +#endif + /* write IHDR information. */ + png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, + info_ptr->filter_type, +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + info_ptr->interlace_type); +#else + 0); +#endif + /* the rest of these check to see if the valid field has the appropriate + flag set, and if it does, writes the chunk. */ +#if defined(PNG_WRITE_gAMA_SUPPORTED) + if (info_ptr->valid & PNG_INFO_gAMA) + { +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_write_gAMA(png_ptr, info_ptr->gamma); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma); +# endif +#endif + } +#endif +#if defined(PNG_WRITE_sRGB_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sRGB) + png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); +#endif +#if defined(PNG_WRITE_iCCP_SUPPORTED) + if (info_ptr->valid & PNG_INFO_iCCP) + png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE, + info_ptr->iccp_profile, (int)info_ptr->iccp_proflen); +#endif +#if defined(PNG_WRITE_sBIT_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sBIT) + png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); +#endif +#if defined(PNG_WRITE_cHRM_SUPPORTED) + if (info_ptr->valid & PNG_INFO_cHRM) + { +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_write_cHRM(png_ptr, + info_ptr->x_white, info_ptr->y_white, + info_ptr->x_red, info_ptr->y_red, + info_ptr->x_green, info_ptr->y_green, + info_ptr->x_blue, info_ptr->y_blue); +#else +# ifdef PNG_FIXED_POINT_SUPPORTED + png_write_cHRM_fixed(png_ptr, + info_ptr->int_x_white, info_ptr->int_y_white, + info_ptr->int_x_red, info_ptr->int_y_red, + info_ptr->int_x_green, info_ptr->int_y_green, + info_ptr->int_x_blue, info_ptr->int_y_blue); +# endif +#endif + } +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks\n"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep=png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && !(up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; + } +} + +void PNGAPI +png_write_info(png_structp png_ptr, png_infop info_ptr) +{ +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) + int i; +#endif + + png_debug(1, "in png_write_info\n"); + + png_write_info_before_PLTE(png_ptr, info_ptr); + + if (info_ptr->valid & PNG_INFO_PLTE) + png_write_PLTE(png_ptr, info_ptr->palette, + (png_uint_32)info_ptr->num_palette); + else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Valid palette required for paletted images\n"); + +#if defined(PNG_WRITE_tRNS_SUPPORTED) + if (info_ptr->valid & PNG_INFO_tRNS) + { +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) + /* invert the alpha channel (in tRNS) */ + if ((png_ptr->transformations & PNG_INVERT_ALPHA) && + info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + int j; + for (j=0; j<(int)info_ptr->num_trans; j++) + info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]); + } +#endif + png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values), + info_ptr->num_trans, info_ptr->color_type); + } +#endif +#if defined(PNG_WRITE_bKGD_SUPPORTED) + if (info_ptr->valid & PNG_INFO_bKGD) + png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); +#endif +#if defined(PNG_WRITE_hIST_SUPPORTED) + if (info_ptr->valid & PNG_INFO_hIST) + png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); +#endif +#if defined(PNG_WRITE_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, + info_ptr->offset_unit_type); +#endif +#if defined(PNG_WRITE_pCAL_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pCAL) + png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, + info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, + info_ptr->pcal_units, info_ptr->pcal_params); +#endif +#if defined(PNG_WRITE_sCAL_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sCAL) +#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) + png_write_sCAL(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_pixel_width, info_ptr->scal_pixel_height); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_s_width, info_ptr->scal_s_height); +#else + png_warning(png_ptr, + "png_write_sCAL not supported; sCAL chunk not written.\n"); +#endif +#endif +#endif +#if defined(PNG_WRITE_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, + info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); +#endif +#if defined(PNG_WRITE_tIME_SUPPORTED) + if (info_ptr->valid & PNG_INFO_tIME) + { + png_write_tIME(png_ptr, &(info_ptr->mod_time)); + png_ptr->mode |= PNG_WROTE_tIME; + } +#endif +#if defined(PNG_WRITE_sPLT_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sPLT) + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); +#endif +#if defined(PNG_WRITE_TEXT_SUPPORTED) + /* Check to see if we need to write text chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing header text chunk %d, type %d\n", i, + info_ptr->text[i].compression); + /* an internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#if defined(PNG_WRITE_iTXt_SUPPORTED) + /* write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text\n"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + /* If we want a compressed text chunk */ + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) + { +#if defined(PNG_WRITE_zTXt_SUPPORTED) + /* write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text\n"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#if defined(PNG_WRITE_tEXt_SUPPORTED) + /* write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, + 0); +#else + png_warning(png_ptr, "Unable to write uncompressed text\n"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + } +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks\n"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep=png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && (up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif +} + +/* Writes the end of the PNG file. If you don't want to write comments or + * time information, you can pass NULL for info. If you already wrote these + * in png_write_info(), do not write them again here. If you have long + * comments, I suggest writing them here, and compressing them. + */ +void PNGAPI +png_write_end(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_end\n"); + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "No IDATs written into file"); + + /* see if user wants us to write information chunks */ + if (info_ptr != NULL) + { +#if defined(PNG_WRITE_TEXT_SUPPORTED) + int i; /* local index variable */ +#endif +#if defined(PNG_WRITE_tIME_SUPPORTED) + /* check to see if user has supplied a time chunk */ + if ((info_ptr->valid & PNG_INFO_tIME) && + !(png_ptr->mode & PNG_WROTE_tIME)) + png_write_tIME(png_ptr, &(info_ptr->mod_time)); +#endif +#if defined(PNG_WRITE_TEXT_SUPPORTED) + /* loop through comment chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing trailer text chunk %d, type %d\n", i, + info_ptr->text[i].compression); + /* an internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#if defined(PNG_WRITE_iTXt_SUPPORTED) + /* write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text\n"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) + { +#if defined(PNG_WRITE_zTXt_SUPPORTED) + /* write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text\n"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#if defined(PNG_WRITE_tEXt_SUPPORTED) + /* write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0); +#else + png_warning(png_ptr, "Unable to write uncompressed text\n"); +#endif + + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + } +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks\n"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep=png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && (up->location & PNG_AFTER_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + } + + png_ptr->mode |= PNG_AFTER_IDAT; + + /* write end of PNG file */ + png_write_IEND(png_ptr); +#if 0 +/* This flush, added in libpng-1.0.8, causes some applications to crash + because they do not set png_ptr->output_flush_fn */ + png_flush(png_ptr); +#endif +} + +#if defined(PNG_WRITE_tIME_SUPPORTED) +#if !defined(_WIN32_WCE) +/* "time.h" functions are not supported on WindowsCE */ +void PNGAPI +png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime) +{ + png_debug(1, "in png_convert_from_struct_tm\n"); + ptime->year = (png_uint_16)(1900 + ttime->tm_year); + ptime->month = (png_byte)(ttime->tm_mon + 1); + ptime->day = (png_byte)ttime->tm_mday; + ptime->hour = (png_byte)ttime->tm_hour; + ptime->minute = (png_byte)ttime->tm_min; + ptime->second = (png_byte)ttime->tm_sec; +} + +void PNGAPI +png_convert_from_time_t(png_timep ptime, time_t ttime) +{ + struct tm *tbuf; + + png_debug(1, "in png_convert_from_time_t\n"); + tbuf = gmtime(&ttime); + png_convert_from_struct_tm(ptime, tbuf); +} +#endif +#endif + +/* Initialize png_ptr structure, and allocate any memory needed */ +png_structp PNGAPI +png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); +} + +/* Alternate initialize png_ptr structure, and allocate any memory needed */ +png_structp PNGAPI +png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + png_structp png_ptr; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + int i; + png_debug(1, "in png_create_write_struct\n"); +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); +#else + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); +#endif /* PNG_USER_MEM_SUPPORTED */ + if (png_ptr == NULL) + return (NULL); + +#if !defined(PNG_1_0_X) +#ifdef PNG_ASSEMBLER_CODE_SUPPORTED + png_init_mmx_flags(png_ptr); /* 1.2.0 addition */ +#endif +#endif /* PNG_1_0_X */ + + /* added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max=PNG_USER_WIDTH_MAX; + png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; +#endif + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_ptr->jmpbuf)) +#endif + { + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf=NULL; + png_destroy_struct(png_ptr); + return (NULL); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); +#endif +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#endif /* PNG_USER_MEM_SUPPORTED */ + png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); + + i=0; + do + { + if(user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first digit. + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[80]; + if (user_png_ver) + { + sprintf(msg, "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + sprintf(msg, "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); +#endif +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "Incompatible libpng version in application and library"); + } + } + + /* initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + + png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, + png_flush_ptr_NULL); + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, + 1, png_doublep_NULL, png_doublep_NULL); +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* Applications that neglect to set up their own setjmp() and then encounter + a png_error() will longjmp here. Since the jmpbuf is then meaningless we + abort instead of returning. */ +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) + PNG_ABORT(); + png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); +#else + if (setjmp(png_ptr->jmpbuf)) + PNG_ABORT(); +#endif +#endif + return (png_ptr); +} + +/* Initialize png_ptr structure, and allocate any memory needed */ +#undef png_write_init +void PNGAPI +png_write_init(png_structp png_ptr) +{ + /* We only come here via pre-1.0.7-compiled applications */ + png_write_init_2(png_ptr, "1.0.6 or earlier", 0, 0); +} + +void PNGAPI +png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size, png_size_t png_info_size) +{ + /* We only come here via pre-1.0.12-compiled applications */ +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + if(png_sizeof(png_struct) > png_struct_size || + png_sizeof(png_info) > png_info_size) + { + char msg[80]; + png_ptr->warning_fn=NULL; + if (user_png_ver) + { + sprintf(msg, "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + sprintf(msg, "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); + } +#endif + if(png_sizeof(png_struct) > png_struct_size) + { + png_ptr->error_fn=NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "The png struct allocated by the application for writing is too small."); + } + if(png_sizeof(png_info) > png_info_size) + { + png_ptr->error_fn=NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "The info struct allocated by the application for writing is too small."); + } + png_write_init_3(&png_ptr, user_png_ver, png_struct_size); +} + + +void PNGAPI +png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size) +{ + png_structp png_ptr=*ptr_ptr; +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* to save current jump buffer */ +#endif + int i = 0; + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + { +#ifdef PNG_LEGACY_SUPPORTED + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; +#else + png_ptr->warning_fn=NULL; + png_warning(png_ptr, + "Application uses deprecated png_write_init() and should be recompiled."); + break; +#endif + } + } while (png_libpng_ver[i++]); + + png_debug(1, "in png_write_init_3\n"); + +#ifdef PNG_SETJMP_SUPPORTED + /* save jump buffer and error functions */ + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); +#endif + + if (png_sizeof(png_struct) > png_struct_size) + { + png_destroy_struct(png_ptr); + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); + *ptr_ptr = png_ptr; + } + + /* reset all variables to 0 */ + png_memset(png_ptr, 0, png_sizeof (png_struct)); + + /* added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max=PNG_USER_WIDTH_MAX; + png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; +#endif + +#if !defined(PNG_1_0_X) +#ifdef PNG_ASSEMBLER_CODE_SUPPORTED + png_init_mmx_flags(png_ptr); /* 1.2.0 addition */ +#endif +#endif /* PNG_1_0_X */ + +#ifdef PNG_SETJMP_SUPPORTED + /* restore jump buffer */ + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); +#endif + + png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, + png_flush_ptr_NULL); + + /* initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, + 1, png_doublep_NULL, png_doublep_NULL); +#endif +} + +/* Write a few rows of image data. If the image is interlaced, + * either you will have to write the 7 sub images, or, if you + * have called png_set_interlace_handling(), you will have to + * "write" the image seven times. + */ +void PNGAPI +png_write_rows(png_structp png_ptr, png_bytepp row, + png_uint_32 num_rows) +{ + png_uint_32 i; /* row counter */ + png_bytepp rp; /* row pointer */ + + png_debug(1, "in png_write_rows\n"); + /* loop through the rows */ + for (i = 0, rp = row; i < num_rows; i++, rp++) + { + png_write_row(png_ptr, *rp); + } +} + +/* Write the image. You only need to call this function once, even + * if you are writing an interlaced image. + */ +void PNGAPI +png_write_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i; /* row index */ + int pass, num_pass; /* pass variables */ + png_bytepp rp; /* points to current row */ + + png_debug(1, "in png_write_image\n"); +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + /* intialize interlace handling. If image is not interlaced, + this will set pass to 1 */ + num_pass = png_set_interlace_handling(png_ptr); +#else + num_pass = 1; +#endif + /* loop through passes */ + for (pass = 0; pass < num_pass; pass++) + { + /* loop through image */ + for (i = 0, rp = image; i < png_ptr->height; i++, rp++) + { + png_write_row(png_ptr, *rp); + } + } +} + +/* called by user to write a row of image data */ +void PNGAPI +png_write_row(png_structp png_ptr, png_bytep row) +{ + png_debug2(1, "in png_write_row (row %ld, pass %d)\n", + png_ptr->row_number, png_ptr->pass); + /* initialize transformations and other stuff if first time */ + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* make sure we wrote the header info */ + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + png_error(png_ptr, + "png_write_info was never called before png_write_row."); + + /* check for transforms that have been set but were defined out */ +#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined."); +#endif + + png_write_start_row(png_ptr); + } + +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + /* if interlaced and not interested in row, return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 3: + if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 4: + if ((png_ptr->row_number & 0x03) != 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 5: + if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 6: + if (!(png_ptr->row_number & 0x01)) + { + png_write_finish_row(png_ptr); + return; + } + break; + } + } +#endif + + /* set up row info for transformations */ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->usr_width; + png_ptr->row_info.channels = png_ptr->usr_channels; + png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth; + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + png_debug1(3, "row_info->color_type = %d\n", png_ptr->row_info.color_type); + png_debug1(3, "row_info->width = %lu\n", png_ptr->row_info.width); + png_debug1(3, "row_info->channels = %d\n", png_ptr->row_info.channels); + png_debug1(3, "row_info->bit_depth = %d\n", png_ptr->row_info.bit_depth); + png_debug1(3, "row_info->pixel_depth = %d\n", png_ptr->row_info.pixel_depth); + png_debug1(3, "row_info->rowbytes = %lu\n", png_ptr->row_info.rowbytes); + + /* Copy user's row into buffer, leaving room for filter byte. */ + png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row, + png_ptr->row_info.rowbytes); + +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + /* handle interlacing */ + if (png_ptr->interlaced && png_ptr->pass < 6 && + (png_ptr->transformations & PNG_INTERLACE)) + { + png_do_write_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass); + /* this should always get caught above, but still ... */ + if (!(png_ptr->row_info.width)) + { + png_write_finish_row(png_ptr); + return; + } + } +#endif + + /* handle other transformations */ + if (png_ptr->transformations) + png_do_write_transformations(png_ptr); + +#if defined(PNG_MNG_FEATURES_SUPPORTED) + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + /* Find a filter if necessary, filter the row and write it out. */ + png_write_find_filter(png_ptr, &(png_ptr->row_info)); + + if (png_ptr->write_row_fn != NULL) + (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +/* Set the automatic flush interval or 0 to turn flushing off */ +void PNGAPI +png_set_flush(png_structp png_ptr, int nrows) +{ + png_debug(1, "in png_set_flush\n"); + png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); +} + +/* flush the current output buffers now */ +void PNGAPI +png_write_flush(png_structp png_ptr) +{ + int wrote_IDAT; + + png_debug(1, "in png_write_flush\n"); + /* We have already written out all of the data */ + if (png_ptr->row_number >= png_ptr->num_rows) + return; + + do + { + int ret; + + /* compress the data */ + ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH); + wrote_IDAT = 0; + + /* check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + + if (!(png_ptr->zstream.avail_out)) + { + /* write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + wrote_IDAT = 1; + } + } while(wrote_IDAT == 1); + + /* If there is any data left to be output, write it into a new IDAT */ + if (png_ptr->zbuf_size != png_ptr->zstream.avail_out) + { + /* write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + png_ptr->flush_rows = 0; + png_flush(png_ptr); +} +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + +/* free all memory used by the write */ +void PNGAPI +png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn = NULL; + png_voidp mem_ptr = NULL; +#endif + + png_debug(1, "in png_destroy_write_struct\n"); + if (png_ptr_ptr != NULL) + { + png_ptr = *png_ptr_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + } + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + png_ptr->num_chunk_list=0; + } +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } + + if (png_ptr != NULL) + { + png_write_destroy(png_ptr); +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = NULL; + } +} + + +/* Free any memory used in png_ptr struct (old method) */ +void /* PRIVATE */ +png_write_destroy(png_structp png_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* save jump buffer */ +#endif + png_error_ptr error_fn; + png_error_ptr warning_fn; + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_write_destroy\n"); + /* free any memory zlib uses */ + deflateEnd(&png_ptr->zstream); + + /* free our memory. png_free checks NULL for us. */ + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->row_buf); + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->sub_row); + png_free(png_ptr, png_ptr->up_row); + png_free(png_ptr, png_ptr->avg_row); + png_free(png_ptr, png_ptr->paeth_row); + +#if defined(PNG_TIME_RFC1123_SUPPORTED) + png_free(png_ptr, png_ptr->time_buffer); +#endif + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + png_free(png_ptr, png_ptr->prev_filters); + png_free(png_ptr, png_ptr->filter_weights); + png_free(png_ptr, png_ptr->inv_filter_weights); + png_free(png_ptr, png_ptr->filter_costs); + png_free(png_ptr, png_ptr->inv_filter_costs); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* reset structure */ + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; + warning_fn = png_ptr->warning_fn; + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, png_sizeof (png_struct)); + + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; + png_ptr->error_ptr = error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr->free_fn = free_fn; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); +#endif +} + +/* Allow the application to select one or more row filters to use. */ +void PNGAPI +png_set_filter(png_structp png_ptr, int method, int filters) +{ + png_debug(1, "in png_set_filter\n"); +#if defined(PNG_MNG_FEATURES_SUPPORTED) + if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (method == PNG_INTRAPIXEL_DIFFERENCING)) + method = PNG_FILTER_TYPE_BASE; +#endif + if (method == PNG_FILTER_TYPE_BASE) + { + switch (filters & (PNG_ALL_FILTERS | 0x07)) + { + case 5: + case 6: + case 7: png_warning(png_ptr, "Unknown row filter for method 0"); + case PNG_FILTER_VALUE_NONE: png_ptr->do_filter=PNG_FILTER_NONE; break; + case PNG_FILTER_VALUE_SUB: png_ptr->do_filter=PNG_FILTER_SUB; break; + case PNG_FILTER_VALUE_UP: png_ptr->do_filter=PNG_FILTER_UP; break; + case PNG_FILTER_VALUE_AVG: png_ptr->do_filter=PNG_FILTER_AVG; break; + case PNG_FILTER_VALUE_PAETH: png_ptr->do_filter=PNG_FILTER_PAETH;break; + default: png_ptr->do_filter = (png_byte)filters; break; + } + + /* If we have allocated the row_buf, this means we have already started + * with the image and we should have allocated all of the filter buffers + * that have been selected. If prev_row isn't already allocated, then + * it is too late to start using the filters that need it, since we + * will be missing the data in the previous row. If an application + * wants to start and stop using particular filters during compression, + * it should start out with all of the filters, and then add and + * remove them after the start of compression. + */ + if (png_ptr->row_buf != NULL) + { + if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Up filter after starting"); + png_ptr->do_filter &= ~PNG_FILTER_UP; + } + else + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Average filter after starting"); + png_ptr->do_filter &= ~PNG_FILTER_AVG; + } + else + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_PAETH) && + png_ptr->paeth_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Paeth filter after starting"); + png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); + } + else + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } + + if (png_ptr->do_filter == PNG_NO_FILTERS) + png_ptr->do_filter = PNG_FILTER_NONE; + } + } + else + png_error(png_ptr, "Unknown custom filter method"); +} + +/* This allows us to influence the way in which libpng chooses the "best" + * filter for the current scanline. While the "minimum-sum-of-absolute- + * differences metric is relatively fast and effective, there is some + * question as to whether it can be improved upon by trying to keep the + * filtered data going to zlib more consistent, hopefully resulting in + * better compression. + */ +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* GRR 970116 */ +void PNGAPI +png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, + int num_weights, png_doublep filter_weights, + png_doublep filter_costs) +{ + int i; + + png_debug(1, "in png_set_filter_heuristics\n"); + if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST) + { + png_warning(png_ptr, "Unknown filter heuristic method"); + return; + } + + if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT) + { + heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; + } + + if (num_weights < 0 || filter_weights == NULL || + heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) + { + num_weights = 0; + } + + png_ptr->num_prev_filters = (png_byte)num_weights; + png_ptr->heuristic_method = (png_byte)heuristic_method; + + if (num_weights > 0) + { + if (png_ptr->prev_filters == NULL) + { + png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_byte) * num_weights)); + + /* To make sure that the weighting starts out fairly */ + for (i = 0; i < num_weights; i++) + { + png_ptr->prev_filters[i] = 255; + } + } + + if (png_ptr->filter_weights == NULL) + { + png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + + png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + for (i = 0; i < num_weights; i++) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + } + + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] < 0.0) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + else + { + png_ptr->inv_filter_weights[i] = + (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5); + png_ptr->filter_weights[i] = + (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5); + } + } + } + + /* If, in the future, there are other filter methods, this would + * need to be based on png_ptr->filter. + */ + if (png_ptr->filter_costs == NULL) + { + png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + + png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + } + + /* Here is where we set the relative costs of the different filters. We + * should take the desired compression level into account when setting + * the costs, so that Paeth, for instance, has a high relative cost at low + * compression levels, while it has a lower relative cost at higher + * compression settings. The filter types are in order of increasing + * relative cost, so it would be possible to do this with an algorithm. + */ + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + if (filter_costs == NULL || filter_costs[i] < 0.0) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + else if (filter_costs[i] >= 1.0) + { + png_ptr->inv_filter_costs[i] = + (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5); + png_ptr->filter_costs[i] = + (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5); + } + } +} +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +void PNGAPI +png_set_compression_level(png_structp png_ptr, int level) +{ + png_debug(1, "in png_set_compression_level\n"); + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL; + png_ptr->zlib_level = level; +} + +void PNGAPI +png_set_compression_mem_level(png_structp png_ptr, int mem_level) +{ + png_debug(1, "in png_set_compression_mem_level\n"); + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL; + png_ptr->zlib_mem_level = mem_level; +} + +void PNGAPI +png_set_compression_strategy(png_structp png_ptr, int strategy) +{ + png_debug(1, "in png_set_compression_strategy\n"); + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; + png_ptr->zlib_strategy = strategy; +} + +void PNGAPI +png_set_compression_window_bits(png_structp png_ptr, int window_bits) +{ + if (window_bits > 15) + png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); + else if (window_bits < 8) + png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); +#ifndef WBITS_8_OK + /* avoid libpng bug with 256-byte windows */ + if (window_bits == 8) + { + png_warning(png_ptr, "Compression window is being reset to 512"); + window_bits=9; + } +#endif + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS; + png_ptr->zlib_window_bits = window_bits; +} + +void PNGAPI +png_set_compression_method(png_structp png_ptr, int method) +{ + png_debug(1, "in png_set_compression_method\n"); + if (method != 8) + png_warning(png_ptr, "Only compression method 8 is supported by PNG"); + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD; + png_ptr->zlib_method = method; +} + +void PNGAPI +png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn) +{ + png_ptr->write_row_fn = write_row_fn; +} + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +void PNGAPI +png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + write_user_transform_fn) +{ + png_debug(1, "in png_set_write_user_transform_fn\n"); + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->write_user_transform_fn = write_user_transform_fn; +} +#endif + + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +void PNGAPI +png_write_png(png_structp png_ptr, png_infop info_ptr, + int transforms, voidp params) +{ +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) + /* invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + + /* Write the file header information. */ + png_write_info(png_ptr, info_ptr); + + /* ------ these transformations don't touch the info structure ------- */ + +#if defined(PNG_WRITE_INVERT_SUPPORTED) + /* invert monochrome pixels */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && (info_ptr->valid & PNG_INFO_sBIT)) + png_set_shift(png_ptr, &info_ptr->sig_bit); +#endif + +#if defined(PNG_WRITE_PACK_SUPPORTED) + /* pack pixels into bytes */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) + /* swap location of alpha bytes from ARGB to RGBA */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) + /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into + * RGB (4 channels -> 3 channels). The second parameter is not used. + */ + if (transforms & PNG_TRANSFORM_STRIP_FILLER) + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); +#endif + +#if defined(PNG_WRITE_BGR_SUPPORTED) + /* flip BGR pixels to RGB */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#if defined(PNG_WRITE_SWAP_SUPPORTED) + /* swap bytes of 16-bit files to most significant byte first */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) + /* swap bits of 1, 2, 4 bit packed pixel formats */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + + /* ----------------------- end of transformations ------------------- */ + + /* write the bits */ + if (info_ptr->valid & PNG_INFO_IDAT) + png_write_image(png_ptr, info_ptr->row_pointers); + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); + + if(transforms == 0 || params == NULL) + /* quiet compiler warnings */ return; +} +#endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/Utilities/FLTK/png/pngwtran.c b/Utilities/FLTK/png/pngwtran.c new file mode 100644 index 0000000000..d2bf5bc784 --- /dev/null +++ b/Utilities/FLTK/png/pngwtran.c @@ -0,0 +1,563 @@ + +/* pngwtran.c - transforms the data in a row for PNG writers + * + * libpng version 1.2.7 - September 12, 2004 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Transform the data according to the user's wishes. The order of + * transformations is significant. + */ +void /* PRIVATE */ +png_do_write_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_write_transformations\n"); + + if (png_ptr == NULL) + return; + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + if(png_ptr->write_user_transform_fn != NULL) + (*(png_ptr->write_user_transform_fn)) /* user write transform function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_uint_32 rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#endif +#if defined(PNG_WRITE_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->flags); +#endif +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->bit_depth); +#endif +#if defined(PNG_WRITE_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +} + +#if defined(PNG_WRITE_PACK_SUPPORTED) +/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The + * row_info bit depth should be 8 (one pixel per byte). The channels + * should be 1 (this only happens on grayscale and paletted images). + */ +void /* PRIVATE */ +png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) +{ + png_debug(1, "in png_do_pack\n"); + if (row_info->bit_depth == 8 && +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->channels == 1) + { + switch ((int)bit_depth) + { + case 1: + { + png_bytep sp, dp; + int mask, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + mask = 0x80; + v = 0; + + for (i = 0; i < row_width; i++) + { + if (*sp != 0) + v |= mask; + sp++; + if (mask > 1) + mask >>= 1; + else + { + mask = 0x80; + *dp = (png_byte)v; + dp++; + v = 0; + } + } + if (mask != 0x80) + *dp = (png_byte)v; + break; + } + case 2: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 6; + v = 0; + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x03); + v |= (value << shift); + if (shift == 0) + { + shift = 6; + *dp = (png_byte)v; + dp++; + v = 0; + } + else + shift -= 2; + sp++; + } + if (shift != 6) + *dp = (png_byte)v; + break; + } + case 4: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 4; + v = 0; + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x0f); + v |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp = (png_byte)v; + dp++; + v = 0; + } + else + shift -= 4; + + sp++; + } + if (shift != 4) + *dp = (png_byte)v; + break; + } + } + row_info->bit_depth = (png_byte)bit_depth; + row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Shift pixel values to take advantage of whole range. Pass the + * true number of bits in bit_depth. The row should be packed + * according to row_info->bit_depth. Thus, if you had a row of + * bit depth 4, but the pixels only had values from 0 to 7, you + * would pass 3 as bit_depth, and this routine would translate the + * data to 0 to 15. + */ +void /* PRIVATE */ +png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) +{ + png_debug(1, "in png_do_shift\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL && +#else + if ( +#endif + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift_start[4], shift_dec[4]; + int channels = 0; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift_start[channels] = row_info->bit_depth - bit_depth->red; + shift_dec[channels] = bit_depth->red; + channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->green; + shift_dec[channels] = bit_depth->green; + channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->blue; + shift_dec[channels] = bit_depth->blue; + channels++; + } + else + { + shift_start[channels] = row_info->bit_depth - bit_depth->gray; + shift_dec[channels] = bit_depth->gray; + channels++; + } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift_start[channels] = row_info->bit_depth - bit_depth->alpha; + shift_dec[channels] = bit_depth->alpha; + channels++; + } + + /* with low row depths, could only be grayscale, so one channel */ + if (row_info->bit_depth < 8) + { + png_bytep bp = row; + png_uint_32 i; + png_byte mask; + png_uint_32 row_bytes = row_info->rowbytes; + + if (bit_depth->gray == 1 && row_info->bit_depth == 2) + mask = 0x55; + else if (row_info->bit_depth == 4 && bit_depth->gray == 3) + mask = 0x11; + else + mask = 0xff; + + for (i = 0; i < row_bytes; i++, bp++) + { + png_uint_16 v; + int j; + + v = *bp; + *bp = 0; + for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + else + *bp |= (png_byte)((v >> (-j)) & mask); + } + } + } + else if (row_info->bit_depth == 8) + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (i = 0; i < istop; i++, bp++) + { + + png_uint_16 v; + int j; + int c = (int)(i%channels); + + v = *bp; + *bp = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + else + *bp |= (png_byte)((v >> (-j)) & 0xff); + } + } + } + else + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (bp = row, i = 0; i < istop; i++) + { + int c = (int)(i%channels); + png_uint_16 value, v; + int j; + + v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1)); + value = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + value |= (png_uint_16)((v << j) & (png_uint_16)0xffff); + else + value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff); + } + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + } + } +} +#endif + +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +void /* PRIVATE */ +png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_swap_alpha\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This converts from ARGB to RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + /* This converts from AARRGGBB to RRGGBBAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from AG to GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + /* This converts from AAGG to GGAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } + } + } +} +#endif + +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +void /* PRIVATE */ +png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_invert_alpha\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This inverts the alpha channel in RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + /* This inverts the alpha channel in RRGGBBAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This inverts the alpha channel in GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + /* This inverts the alpha channel in GGAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + } + } +} +#endif + +#if defined(PNG_MNG_FEATURES_SUPPORTED) +/* undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_write_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_intrapixel\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((*rp - *(rp+1))&0xff); + *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); + png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); + png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); + png_uint_32 red = (png_uint_32)((s0-s1) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2-s1) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp+1) = (png_byte)(red & 0xff); + *(rp+4) = (png_byte)((blue >> 8) & 0xff); + *(rp+5) = (png_byte)(blue & 0xff); + } + } + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/Utilities/FLTK/png/pngwutil.c b/Utilities/FLTK/png/pngwutil.c new file mode 100644 index 0000000000..87f028f9a8 --- /dev/null +++ b/Utilities/FLTK/png/pngwutil.c @@ -0,0 +1,2726 @@ + +/* pngwutil.c - utilities to write a PNG file + * + * libpng version 1.2.7 - September 12, 2004 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Place a 32-bit number into a buffer in PNG byte order. We work + * with unsigned numbers for convenience, although one supported + * ancillary chunk uses signed (two's complement) numbers. + */ +void /* PRIVATE */ +png_save_uint_32(png_bytep buf, png_uint_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} + +#if defined(PNG_WRITE_pCAL_SUPPORTED) || defined(PNG_WRITE_oFFs_SUPPORTED) +/* The png_save_int_32 function assumes integers are stored in two's + * complement format. If this isn't the case, then this routine needs to + * be modified to write data in two's complement format. + */ +void /* PRIVATE */ +png_save_int_32(png_bytep buf, png_int_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +void /* PRIVATE */ +png_save_uint_16(png_bytep buf, unsigned int i) +{ + buf[0] = (png_byte)((i >> 8) & 0xff); + buf[1] = (png_byte)(i & 0xff); +} + +/* Write a PNG chunk all at once. The type is an array of ASCII characters + * representing the chunk name. The array must be at least 4 bytes in + * length, and does not need to be null terminated. To be safe, pass the + * pre-defined chunk names here, and if you need a new one, define it + * where the others are defined. The length is the length of the data. + * All the data must be present. If that is not possible, use the + * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() + * functions instead. + */ +void PNGAPI +png_write_chunk(png_structp png_ptr, png_bytep chunk_name, + png_bytep data, png_size_t length) +{ + png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length); + png_write_chunk_data(png_ptr, data, length); + png_write_chunk_end(png_ptr); +} + +/* Write the start of a PNG chunk. The type is the chunk type. + * The total_length is the sum of the lengths of all the data you will be + * passing in png_write_chunk_data(). + */ +void PNGAPI +png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name, + png_uint_32 length) +{ + png_byte buf[4]; + png_debug2(0, "Writing %s chunk (%lu bytes)\n", chunk_name, length); + + /* write the length */ + png_save_uint_32(buf, length); + png_write_data(png_ptr, buf, (png_size_t)4); + + /* write the chunk name */ + png_write_data(png_ptr, chunk_name, (png_size_t)4); + /* reset the crc and run it over the chunk name */ + png_reset_crc(png_ptr); + png_calculate_crc(png_ptr, chunk_name, (png_size_t)4); +} + +/* Write the data of a PNG chunk started with png_write_chunk_start(). + * Note that multiple calls to this function are allowed, and that the + * sum of the lengths from these calls *must* add up to the total_length + * given to png_write_chunk_start(). + */ +void PNGAPI +png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + /* write the data, and run the CRC over it */ + if (data != NULL && length > 0) + { + png_calculate_crc(png_ptr, data, length); + png_write_data(png_ptr, data, length); + } +} + +/* Finish a chunk started with png_write_chunk_start(). */ +void PNGAPI +png_write_chunk_end(png_structp png_ptr) +{ + png_byte buf[4]; + + /* write the crc */ + png_save_uint_32(buf, png_ptr->crc); + + png_write_data(png_ptr, buf, (png_size_t)4); +} + +/* Simple function to write the signature. If we have already written + * the magic bytes of the signature, or more likely, the PNG stream is + * being embedded into another stream and doesn't need its own signature, + * we should call png_set_sig_bytes() to tell libpng how many of the + * bytes have already been written. + */ +void /* PRIVATE */ +png_write_sig(png_structp png_ptr) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + /* write the rest of the 8 byte signature */ + png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], + (png_size_t)8 - png_ptr->sig_bytes); + if(png_ptr->sig_bytes < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; +} + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED) +/* + * This pair of functions encapsulates the operation of (a) compressing a + * text string, and (b) issuing it later as a series of chunk data writes. + * The compression_state structure is shared context for these functions + * set up by the caller in order to make the whole mess thread-safe. + */ + +typedef struct +{ + char *input; /* the uncompressed input data */ + int input_len; /* its length */ + int num_output_ptr; /* number of output pointers used */ + int max_output_ptr; /* size of output_ptr */ + png_charpp output_ptr; /* array of pointers to output */ +} compression_state; + +/* compress given text into storage in the png_ptr structure */ +static int /* PRIVATE */ +png_text_compress(png_structp png_ptr, + png_charp text, png_size_t text_len, int compression, + compression_state *comp) +{ + int ret; + + comp->num_output_ptr = comp->max_output_ptr = 0; + comp->output_ptr = NULL; + comp->input = NULL; + + /* we may just want to pass the text right through */ + if (compression == PNG_TEXT_COMPRESSION_NONE) + { + comp->input = text; + comp->input_len = text_len; + return((int)text_len); + } + + if (compression >= PNG_TEXT_COMPRESSION_LAST) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[50]; + sprintf(msg, "Unknown compression type %d", compression); + png_warning(png_ptr, msg); +#else + png_warning(png_ptr, "Unknown compression type"); +#endif + } + + /* We can't write the chunk until we find out how much data we have, + * which means we need to run the compressor first and save the + * output. This shouldn't be a problem, as the vast majority of + * comments should be reasonable, but we will set up an array of + * malloc'd pointers to be sure. + * + * If we knew the application was well behaved, we could simplify this + * greatly by assuming we can always malloc an output buffer large + * enough to hold the compressed text ((1001 * text_len / 1000) + 12) + * and malloc this directly. The only time this would be a bad idea is + * if we can't malloc more than 64K and we have 64K of random input + * data, or if the input string is incredibly large (although this + * wouldn't cause a failure, just a slowdown due to swapping). + */ + + /* set up the compression buffers */ + png_ptr->zstream.avail_in = (uInt)text_len; + png_ptr->zstream.next_in = (Bytef *)text; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf; + + /* this is the same compression loop as in png_write_row() */ + do + { + /* compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + if (ret != Z_OK) + { + /* error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + /* check to see if we need more room */ + if (!png_ptr->zstream.avail_out && png_ptr->zstream.avail_in) + { + /* make sure the output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_charpp old_ptr; + + old_ptr = comp->output_ptr; + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * + png_sizeof (png_charpp))); + png_memcpy(comp->output_ptr, old_ptr, old_max + * png_sizeof (png_charp)); + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * + png_sizeof (png_charp))); + } + + /* save the data */ + comp->output_ptr[comp->num_output_ptr] = (png_charp)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + comp->num_output_ptr++; + + /* and reset the buffer */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + /* continue until we don't have any more to compress */ + } while (png_ptr->zstream.avail_in); + + /* finish the compression */ + do + { + /* tell zlib we are finished */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + + if (ret == Z_OK) + { + /* check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + /* check to make sure our output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_charpp old_ptr; + + old_ptr = comp->output_ptr; + /* This could be optimized to realloc() */ + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * + png_sizeof (png_charpp))); + png_memcpy(comp->output_ptr, old_ptr, + old_max * png_sizeof (png_charp)); + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * + png_sizeof (png_charp))); + } + + /* save off the data */ + comp->output_ptr[comp->num_output_ptr] = + (png_charp)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size); + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + comp->num_output_ptr++; + + /* and reset the buffer pointers */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + } + else if (ret != Z_STREAM_END) + { + /* we got an error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* text length is number of buffers plus last buffer */ + text_len = png_ptr->zbuf_size * comp->num_output_ptr; + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; + + return((int)text_len); +} + +/* ship the compressed text out via chunk writes */ +static void /* PRIVATE */ +png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) +{ + int i; + + /* handle the no-compression case */ + if (comp->input) + { + png_write_chunk_data(png_ptr, (png_bytep)comp->input, + (png_size_t)comp->input_len); + return; + } + + /* write saved output buffers, if any */ + for (i = 0; i < comp->num_output_ptr; i++) + { + png_write_chunk_data(png_ptr,(png_bytep)comp->output_ptr[i], + png_ptr->zbuf_size); + png_free(png_ptr, comp->output_ptr[i]); + comp->output_ptr[i]=NULL; + } + if (comp->max_output_ptr != 0) + png_free(png_ptr, comp->output_ptr); + comp->output_ptr=NULL; + /* write anything left in zbuf */ + if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) + png_write_chunk_data(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + /* reset zlib for another zTXt/iTXt or the image data */ + deflateReset(&png_ptr->zstream); + +} +#endif + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. Note that the rest of this code depends upon this + * information being correct. + */ +void /* PRIVATE */ +png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, + int bit_depth, int color_type, int compression_type, int filter_type, + int interlace_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IHDR; +#endif + png_byte buf[13]; /* buffer to store the IHDR info */ + + png_debug(1, "in png_write_IHDR\n"); + /* Check that we have valid input data from the application info */ + switch (color_type) + { + case PNG_COLOR_TYPE_GRAY: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: + case 16: png_ptr->channels = 1; break; + default: png_error(png_ptr,"Invalid bit depth for grayscale image"); + } + break; + case PNG_COLOR_TYPE_RGB: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for RGB image"); + png_ptr->channels = 3; + break; + case PNG_COLOR_TYPE_PALETTE: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: png_ptr->channels = 1; break; + default: png_error(png_ptr, "Invalid bit depth for paletted image"); + } + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); + png_ptr->channels = 2; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for RGBA image"); + png_ptr->channels = 4; + break; + default: + png_error(png_ptr, "Invalid image color type specified"); + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Invalid compression type specified"); + compression_type = PNG_COMPRESSION_TYPE_BASE; + } + + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ( +#if defined(PNG_MNG_FEATURES_SUPPORTED) + !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && +#endif + filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Invalid filter type specified"); + filter_type = PNG_FILTER_TYPE_BASE; + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + if (interlace_type != PNG_INTERLACE_NONE && + interlace_type != PNG_INTERLACE_ADAM7) + { + png_warning(png_ptr, "Invalid interlace type specified"); + interlace_type = PNG_INTERLACE_ADAM7; + } +#else + interlace_type=PNG_INTERLACE_NONE; +#endif + + /* save off the relevent information */ + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->color_type = (png_byte)color_type; + png_ptr->interlaced = (png_byte)interlace_type; +#if defined(PNG_MNG_FEATURES_SUPPORTED) + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + png_ptr->width = width; + png_ptr->height = height; + + png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); + /* set the usr info, so any transformations can modify it */ + png_ptr->usr_width = png_ptr->width; + png_ptr->usr_bit_depth = png_ptr->bit_depth; + png_ptr->usr_channels = png_ptr->channels; + + /* pack the header information into the buffer */ + png_save_uint_32(buf, width); + png_save_uint_32(buf + 4, height); + buf[8] = (png_byte)bit_depth; + buf[9] = (png_byte)color_type; + buf[10] = (png_byte)compression_type; + buf[11] = (png_byte)filter_type; + buf[12] = (png_byte)interlace_type; + + /* write the chunk */ + png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13); + + /* initialize zlib with PNG info */ + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + if (!(png_ptr->do_filter)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || + png_ptr->bit_depth < 8) + png_ptr->do_filter = PNG_FILTER_NONE; + else + png_ptr->do_filter = PNG_ALL_FILTERS; + } + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)) + { + if (png_ptr->do_filter != PNG_FILTER_NONE) + png_ptr->zlib_strategy = Z_FILTERED; + else + png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; + } + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) + png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL)) + png_ptr->zlib_mem_level = 8; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS)) + png_ptr->zlib_window_bits = 15; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) + png_ptr->zlib_method = 8; + deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, + png_ptr->zlib_method, png_ptr->zlib_window_bits, + png_ptr->zlib_mem_level, png_ptr->zlib_strategy); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + png_ptr->mode = PNG_HAVE_IHDR; +} + +/* write the palette. We are careful not to trust png_color to be in the + * correct order for PNG, so people can redefine it to any convenient + * structure. + */ +void /* PRIVATE */ +png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_PLTE; +#endif + png_uint_32 i; + png_colorp pal_ptr; + png_byte buf[3]; + + png_debug(1, "in png_write_PLTE\n"); + if (( +#if defined(PNG_MNG_FEATURES_SUPPORTED) + !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && +#endif + num_pal == 0) || num_pal > 256) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_error(png_ptr, "Invalid number of colors in palette"); + } + else + { + png_warning(png_ptr, "Invalid number of colors in palette"); + return; + } + } + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring request to write a PLTE chunk in grayscale PNG"); + return; + } + + png_ptr->num_palette = (png_uint_16)num_pal; + png_debug1(3, "num_palette = %d\n", png_ptr->num_palette); + + png_write_chunk_start(png_ptr, (png_bytep)png_PLTE, num_pal * 3); +#ifndef PNG_NO_POINTER_INDEXING + for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) + { + buf[0] = pal_ptr->red; + buf[1] = pal_ptr->green; + buf[2] = pal_ptr->blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } +#else + /* This is a little slower but some buggy compilers need to do this instead */ + pal_ptr=palette; + for (i = 0; i < num_pal; i++) + { + buf[0] = pal_ptr[i].red; + buf[1] = pal_ptr[i].green; + buf[2] = pal_ptr[i].blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } +#endif + png_write_chunk_end(png_ptr); + png_ptr->mode |= PNG_HAVE_PLTE; +} + +/* write an IDAT chunk */ +void /* PRIVATE */ +png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IDAT; +#endif + png_debug(1, "in png_write_IDAT\n"); + + /* Optimize the CMF field in the zlib stream. */ + /* This hack of the zlib stream is compliant to the stream specification. */ + if (!(png_ptr->mode & PNG_HAVE_IDAT) && + png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) + { + unsigned int z_cmf = data[0]; /* zlib compression method and flags */ + if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) + { + /* Avoid memory underflows and multiplication overflows. */ + /* The conditions below are practically always satisfied; + however, they still must be checked. */ + if (length >= 2 && + png_ptr->height < 16384 && png_ptr->width < 16384) + { + png_uint_32 uncompressed_idat_size = png_ptr->height * + ((png_ptr->width * + png_ptr->channels * png_ptr->bit_depth + 15) >> 3); + unsigned int z_cinfo = z_cmf >> 4; + unsigned int half_z_window_size = 1 << (z_cinfo + 7); + while (uncompressed_idat_size <= half_z_window_size && + half_z_window_size >= 256) + { + z_cinfo--; + half_z_window_size >>= 1; + } + z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); + if (data[0] != (png_byte)z_cmf) + { + data[0] = (png_byte)z_cmf; + data[1] &= 0xe0; + data[1] += (png_byte)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f); + } + } + } + else + png_error(png_ptr, + "Invalid zlib compression method or flags in IDAT"); + } + + png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length); + png_ptr->mode |= PNG_HAVE_IDAT; +} + +/* write an IEND chunk */ +void /* PRIVATE */ +png_write_IEND(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IEND; +#endif + png_debug(1, "in png_write_IEND\n"); + png_write_chunk(png_ptr, (png_bytep)png_IEND, png_bytep_NULL, + (png_size_t)0); + png_ptr->mode |= PNG_HAVE_IEND; +} + +#if defined(PNG_WRITE_gAMA_SUPPORTED) +/* write a gAMA chunk */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void /* PRIVATE */ +png_write_gAMA(png_structp png_ptr, double file_gamma) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_gAMA; +#endif + png_uint_32 igamma; + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA\n"); + /* file_gamma is saved in 1/100,000ths */ + igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5); + png_save_uint_32(buf, igamma); + png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_gAMA; +#endif + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA\n"); + /* file_gamma is saved in 1/100,000ths */ + png_save_uint_32(buf, (png_uint_32)file_gamma); + png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); +} +#endif +#endif + +#if defined(PNG_WRITE_sRGB_SUPPORTED) +/* write a sRGB chunk */ +void /* PRIVATE */ +png_write_sRGB(png_structp png_ptr, int srgb_intent) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sRGB; +#endif + png_byte buf[1]; + + png_debug(1, "in png_write_sRGB\n"); + if(srgb_intent >= PNG_sRGB_INTENT_LAST) + png_warning(png_ptr, + "Invalid sRGB rendering intent specified"); + buf[0]=(png_byte)srgb_intent; + png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1); +} +#endif + +#if defined(PNG_WRITE_iCCP_SUPPORTED) +/* write an iCCP chunk */ +void /* PRIVATE */ +png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, + png_charp profile, int profile_len) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_iCCP; +#endif + png_size_t name_len; + png_charp new_name; + compression_state comp; + + png_debug(1, "in png_write_iCCP\n"); + if (name == NULL || (name_len = png_check_keyword(png_ptr, name, + &new_name)) == 0) + { + png_warning(png_ptr, "Empty keyword in iCCP chunk"); + return; + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + png_warning(png_ptr, "Unknown compression type in iCCP chunk"); + + if (profile == NULL) + profile_len = 0; + + if (profile_len) + profile_len = png_text_compress(png_ptr, profile, (png_size_t)profile_len, + PNG_COMPRESSION_TYPE_BASE, &comp); + + /* make sure we include the NULL after the name and the compression type */ + png_write_chunk_start(png_ptr, (png_bytep)png_iCCP, + (png_uint_32)name_len+profile_len+2); + new_name[name_len+1]=0x00; + png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 2); + + if (profile_len) + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#if defined(PNG_WRITE_sPLT_SUPPORTED) +/* write a sPLT chunk */ +void /* PRIVATE */ +png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sPLT; +#endif + png_size_t name_len; + png_charp new_name; + png_byte entrybuf[10]; + int entry_size = (spalette->depth == 8 ? 6 : 10); + int palette_size = entry_size * spalette->nentries; + png_sPLT_entryp ep; +#ifdef PNG_NO_POINTER_INDEXING + int i; +#endif + + png_debug(1, "in png_write_sPLT\n"); + if (spalette->name == NULL || (name_len = png_check_keyword(png_ptr, + spalette->name, &new_name))==0) + { + png_warning(png_ptr, "Empty keyword in sPLT chunk"); + return; + } + + /* make sure we include the NULL after the name */ + png_write_chunk_start(png_ptr, (png_bytep)png_sPLT, + (png_uint_32)(name_len + 2 + palette_size)); + png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 1); + png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, 1); + + /* loop through each palette entry, writing appropriately */ +#ifndef PNG_NO_POINTER_INDEXING + for (ep = spalette->entries; ep<spalette->entries+spalette->nentries; ep++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep->red; + entrybuf[1] = (png_byte)ep->green; + entrybuf[2] = (png_byte)ep->blue; + entrybuf[3] = (png_byte)ep->alpha; + png_save_uint_16(entrybuf + 4, ep->frequency); + } + else + { + png_save_uint_16(entrybuf + 0, ep->red); + png_save_uint_16(entrybuf + 2, ep->green); + png_save_uint_16(entrybuf + 4, ep->blue); + png_save_uint_16(entrybuf + 6, ep->alpha); + png_save_uint_16(entrybuf + 8, ep->frequency); + } + png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); + } +#else + ep=spalette->entries; + for (i=0; i>spalette->nentries; i++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep[i].red; + entrybuf[1] = (png_byte)ep[i].green; + entrybuf[2] = (png_byte)ep[i].blue; + entrybuf[3] = (png_byte)ep[i].alpha; + png_save_uint_16(entrybuf + 4, ep[i].frequency); + } + else + { + png_save_uint_16(entrybuf + 0, ep[i].red); + png_save_uint_16(entrybuf + 2, ep[i].green); + png_save_uint_16(entrybuf + 4, ep[i].blue); + png_save_uint_16(entrybuf + 6, ep[i].alpha); + png_save_uint_16(entrybuf + 8, ep[i].frequency); + } + png_write_chunk_data(png_ptr, entrybuf, entry_size); + } +#endif + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#if defined(PNG_WRITE_sBIT_SUPPORTED) +/* write the sBIT chunk */ +void /* PRIVATE */ +png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sBIT; +#endif + png_byte buf[4]; + png_size_t size; + + png_debug(1, "in png_write_sBIT\n"); + /* make sure we don't depend upon the order of PNG_COLOR_8 */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + png_byte maxbits; + + maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : + png_ptr->usr_bit_depth); + if (sbit->red == 0 || sbit->red > maxbits || + sbit->green == 0 || sbit->green > maxbits || + sbit->blue == 0 || sbit->blue > maxbits) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[0] = sbit->red; + buf[1] = sbit->green; + buf[2] = sbit->blue; + size = 3; + } + else + { + if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[0] = sbit->gray; + size = 1; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[size++] = sbit->alpha; + } + + png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size); +} +#endif + +#if defined(PNG_WRITE_cHRM_SUPPORTED) +/* write the cHRM chunk */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void /* PRIVATE */ +png_write_cHRM(png_structp png_ptr, double white_x, double white_y, + double red_x, double red_y, double green_x, double green_y, + double blue_x, double blue_y) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_cHRM; +#endif + png_byte buf[32]; + png_uint_32 itemp; + + png_debug(1, "in png_write_cHRM\n"); + /* each value is saved in 1/100,000ths */ + if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 || + white_x + white_y > 1.0) + { + png_warning(png_ptr, "Invalid cHRM white point specified"); +#if !defined(PNG_NO_CONSOLE_IO) + fprintf(stderr,"white_x=%f, white_y=%f\n",white_x, white_y); +#endif + return; + } + itemp = (png_uint_32)(white_x * 100000.0 + 0.5); + png_save_uint_32(buf, itemp); + itemp = (png_uint_32)(white_y * 100000.0 + 0.5); + png_save_uint_32(buf + 4, itemp); + + if (red_x < 0 || red_x > 0.8 || red_y < 0 || red_y > 0.8 || + red_x + red_y > 1.0) + { + png_warning(png_ptr, "Invalid cHRM red point specified"); + return; + } + itemp = (png_uint_32)(red_x * 100000.0 + 0.5); + png_save_uint_32(buf + 8, itemp); + itemp = (png_uint_32)(red_y * 100000.0 + 0.5); + png_save_uint_32(buf + 12, itemp); + + if (green_x < 0 || green_x > 0.8 || green_y < 0 || green_y > 0.8 || + green_x + green_y > 1.0) + { + png_warning(png_ptr, "Invalid cHRM green point specified"); + return; + } + itemp = (png_uint_32)(green_x * 100000.0 + 0.5); + png_save_uint_32(buf + 16, itemp); + itemp = (png_uint_32)(green_y * 100000.0 + 0.5); + png_save_uint_32(buf + 20, itemp); + + if (blue_x < 0 || blue_x > 0.8 || blue_y < 0 || blue_y > 0.8 || + blue_x + blue_y > 1.0) + { + png_warning(png_ptr, "Invalid cHRM blue point specified"); + return; + } + itemp = (png_uint_32)(blue_x * 100000.0 + 0.5); + png_save_uint_32(buf + 24, itemp); + itemp = (png_uint_32)(blue_y * 100000.0 + 0.5); + png_save_uint_32(buf + 28, itemp); + + png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, + png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y, + png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x, + png_fixed_point blue_y) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_cHRM; +#endif + png_byte buf[32]; + + png_debug(1, "in png_write_cHRM\n"); + /* each value is saved in 1/100,000ths */ + if (white_x > 80000L || white_y > 80000L || white_x + white_y > 100000L) + { + png_warning(png_ptr, "Invalid fixed cHRM white point specified"); +#if !defined(PNG_NO_CONSOLE_IO) + fprintf(stderr,"white_x=%ld, white_y=%ld\n",white_x, white_y); +#endif + return; + } + png_save_uint_32(buf, (png_uint_32)white_x); + png_save_uint_32(buf + 4, (png_uint_32)white_y); + + if (red_x > 80000L || red_y > 80000L || red_x + red_y > 100000L) + { + png_warning(png_ptr, "Invalid cHRM fixed red point specified"); + return; + } + png_save_uint_32(buf + 8, (png_uint_32)red_x); + png_save_uint_32(buf + 12, (png_uint_32)red_y); + + if (green_x > 80000L || green_y > 80000L || green_x + green_y > 100000L) + { + png_warning(png_ptr, "Invalid fixed cHRM green point specified"); + return; + } + png_save_uint_32(buf + 16, (png_uint_32)green_x); + png_save_uint_32(buf + 20, (png_uint_32)green_y); + + if (blue_x > 80000L || blue_y > 80000L || blue_x + blue_y > 100000L) + { + png_warning(png_ptr, "Invalid fixed cHRM blue point specified"); + return; + } + png_save_uint_32(buf + 24, (png_uint_32)blue_x); + png_save_uint_32(buf + 28, (png_uint_32)blue_y); + + png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); +} +#endif +#endif + +#if defined(PNG_WRITE_tRNS_SUPPORTED) +/* write the tRNS chunk */ +void /* PRIVATE */ +png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran, + int num_trans, int color_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_tRNS; +#endif + png_byte buf[6]; + + png_debug(1, "in png_write_tRNS\n"); + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) + { + png_warning(png_ptr,"Invalid number of transparent colors specified"); + return; + } + /* write the chunk out as it is */ + png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans, (png_size_t)num_trans); + } + else if (color_type == PNG_COLOR_TYPE_GRAY) + { + /* one 16 bit value */ + if(tran->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); + return; + } + png_save_uint_16(buf, tran->gray); + png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2); + } + else if (color_type == PNG_COLOR_TYPE_RGB) + { + /* three 16 bit values */ + png_save_uint_16(buf, tran->red); + png_save_uint_16(buf + 2, tran->green); + png_save_uint_16(buf + 4, tran->blue); + if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); + return; + } + png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6); + } + else + { + png_warning(png_ptr, "Can't write tRNS with an alpha channel"); + } +} +#endif + +#if defined(PNG_WRITE_bKGD_SUPPORTED) +/* write the background chunk */ +void /* PRIVATE */ +png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_bKGD; +#endif + png_byte buf[6]; + + png_debug(1, "in png_write_bKGD\n"); + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if ( +#if defined(PNG_MNG_FEATURES_SUPPORTED) + (png_ptr->num_palette || + (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && +#endif + back->index > png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid background palette index"); + return; + } + buf[0] = back->index; + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1); + } + else if (color_type & PNG_COLOR_MASK_COLOR) + { + png_save_uint_16(buf, back->red); + png_save_uint_16(buf + 2, back->green); + png_save_uint_16(buf + 4, back->blue); + if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); + return; + } + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6); + } + else + { + if(back->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); + return; + } + png_save_uint_16(buf, back->gray); + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2); + } +} +#endif + +#if defined(PNG_WRITE_hIST_SUPPORTED) +/* write the histogram */ +void /* PRIVATE */ +png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_hIST; +#endif + int i; + png_byte buf[3]; + + png_debug(1, "in png_write_hIST\n"); + if (num_hist > (int)png_ptr->num_palette) + { + png_debug2(3, "num_hist = %d, num_palette = %d\n", num_hist, + png_ptr->num_palette); + png_warning(png_ptr, "Invalid number of histogram entries specified"); + return; + } + + png_write_chunk_start(png_ptr, (png_bytep)png_hIST, (png_uint_32)(num_hist * 2)); + for (i = 0; i < num_hist; i++) + { + png_save_uint_16(buf, hist[i]); + png_write_chunk_data(png_ptr, buf, (png_size_t)2); + } + png_write_chunk_end(png_ptr); +} +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, + * and if invalid, correct the keyword rather than discarding the entire + * chunk. The PNG 1.0 specification requires keywords 1-79 characters in + * length, forbids leading or trailing whitespace, multiple internal spaces, + * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. + * + * The new_key is allocated to hold the corrected keyword and must be freed + * by the calling routine. This avoids problems with trying to write to + * static keywords without having to have duplicate copies of the strings. + */ +png_size_t /* PRIVATE */ +png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) +{ + png_size_t key_len; + png_charp kp, dp; + int kflag; + int kwarn=0; + + png_debug(1, "in png_check_keyword\n"); + *new_key = NULL; + + if (key == NULL || (key_len = png_strlen(key)) == 0) + { + png_warning(png_ptr, "zero length keyword"); + return ((png_size_t)0); + } + + png_debug1(2, "Keyword to be checked is '%s'\n", key); + + *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2)); + if (*new_key == NULL) + { + png_warning(png_ptr, "Out of memory while procesing keyword"); + return ((png_size_t)0); + } + + /* Replace non-printing characters with a blank and print a warning */ + for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++) + { + if (*kp < 0x20 || (*kp > 0x7E && (png_byte)*kp < 0xA1)) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[40]; + + sprintf(msg, "invalid keyword character 0x%02X", *kp); + png_warning(png_ptr, msg); +#else + png_warning(png_ptr, "invalid character in keyword"); +#endif + *dp = ' '; + } + else + { + *dp = *kp; + } + } + *dp = '\0'; + + /* Remove any trailing white space. */ + kp = *new_key + key_len - 1; + if (*kp == ' ') + { + png_warning(png_ptr, "trailing spaces removed from keyword"); + + while (*kp == ' ') + { + *(kp--) = '\0'; + key_len--; + } + } + + /* Remove any leading white space. */ + kp = *new_key; + if (*kp == ' ') + { + png_warning(png_ptr, "leading spaces removed from keyword"); + + while (*kp == ' ') + { + kp++; + key_len--; + } + } + + png_debug1(2, "Checking for multiple internal spaces in '%s'\n", kp); + + /* Remove multiple internal spaces. */ + for (kflag = 0, dp = *new_key; *kp != '\0'; kp++) + { + if (*kp == ' ' && kflag == 0) + { + *(dp++) = *kp; + kflag = 1; + } + else if (*kp == ' ') + { + key_len--; + kwarn=1; + } + else + { + *(dp++) = *kp; + kflag = 0; + } + } + *dp = '\0'; + if(kwarn) + png_warning(png_ptr, "extra interior spaces removed from keyword"); + + if (key_len == 0) + { + png_free(png_ptr, *new_key); + *new_key=NULL; + png_warning(png_ptr, "Zero length keyword"); + } + + if (key_len > 79) + { + png_warning(png_ptr, "keyword length must be 1 - 79 characters"); + new_key[79] = '\0'; + key_len = 79; + } + + return (key_len); +} +#endif + +#if defined(PNG_WRITE_tEXt_SUPPORTED) +/* write a tEXt chunk */ +void /* PRIVATE */ +png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, + png_size_t text_len) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_tEXt; +#endif + png_size_t key_len; + png_charp new_key; + + png_debug(1, "in png_write_tEXt\n"); + if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) + { + png_warning(png_ptr, "Empty keyword in tEXt chunk"); + return; + } + + if (text == NULL || *text == '\0') + text_len = 0; + else + text_len = png_strlen(text); + + /* make sure we include the 0 after the key */ + png_write_chunk_start(png_ptr, (png_bytep)png_tEXt, (png_uint_32)key_len+text_len+1); + /* + * We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); + if (text_len) + png_write_chunk_data(png_ptr, (png_bytep)text, text_len); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_key); +} +#endif + +#if defined(PNG_WRITE_zTXt_SUPPORTED) +/* write a compressed text chunk */ +void /* PRIVATE */ +png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text, + png_size_t text_len, int compression) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_zTXt; +#endif + png_size_t key_len; + char buf[1]; + png_charp new_key; + compression_state comp; + + png_debug(1, "in png_write_zTXt\n"); + + if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) + { + png_warning(png_ptr, "Empty keyword in zTXt chunk"); + return; + } + + if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE) + { + png_write_tEXt(png_ptr, new_key, text, (png_size_t)0); + png_free(png_ptr, new_key); + return; + } + + text_len = png_strlen(text); + + png_free(png_ptr, new_key); + + /* compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression, + &comp); + + /* write start of chunk */ + png_write_chunk_start(png_ptr, (png_bytep)png_zTXt, (png_uint_32) + (key_len+text_len+2)); + /* write key */ + png_write_chunk_data(png_ptr, (png_bytep)key, key_len + 1); + buf[0] = (png_byte)compression; + /* write compression */ + png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1); + /* write the compressed data */ + png_write_compressed_data_out(png_ptr, &comp); + + /* close the chunk */ + png_write_chunk_end(png_ptr); +} +#endif + +#if defined(PNG_WRITE_iTXt_SUPPORTED) +/* write an iTXt chunk */ +void /* PRIVATE */ +png_write_iTXt(png_structp png_ptr, int compression, png_charp key, + png_charp lang, png_charp lang_key, png_charp text) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_iTXt; +#endif + png_size_t lang_len, key_len, lang_key_len, text_len; + png_charp new_lang, new_key; + png_byte cbuf[2]; + compression_state comp; + + png_debug(1, "in png_write_iTXt\n"); + + if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) + { + png_warning(png_ptr, "Empty keyword in iTXt chunk"); + return; + } + if (lang == NULL || (lang_len = png_check_keyword(png_ptr, lang, &new_lang))==0) + { + png_warning(png_ptr, "Empty language field in iTXt chunk"); + new_lang = NULL; + lang_len = 0; + } + + if (lang_key == NULL) + lang_key_len = 0; + else + lang_key_len = png_strlen(lang_key); + + if (text == NULL) + text_len = 0; + else + text_len = png_strlen(text); + + /* compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression-2, + &comp); + + + /* make sure we include the compression flag, the compression byte, + * and the NULs after the key, lang, and lang_key parts */ + + png_write_chunk_start(png_ptr, (png_bytep)png_iTXt, + (png_uint_32)( + 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ + + key_len + + lang_len + + lang_key_len + + text_len)); + + /* + * We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); + + /* set the compression flag */ + if (compression == PNG_ITXT_COMPRESSION_NONE || \ + compression == PNG_TEXT_COMPRESSION_NONE) + cbuf[0] = 0; + else /* compression == PNG_ITXT_COMPRESSION_zTXt */ + cbuf[0] = 1; + /* set the compression method */ + cbuf[1] = 0; + png_write_chunk_data(png_ptr, cbuf, 2); + + cbuf[0] = 0; + png_write_chunk_data(png_ptr, (new_lang ? (png_bytep)new_lang : cbuf), lang_len + 1); + png_write_chunk_data(png_ptr, (lang_key ? (png_bytep)lang_key : cbuf), lang_key_len + 1); + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_key); + if (new_lang) + png_free(png_ptr, new_lang); +} +#endif + +#if defined(PNG_WRITE_oFFs_SUPPORTED) +/* write the oFFs chunk */ +void /* PRIVATE */ +png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, + int unit_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_oFFs; +#endif + png_byte buf[9]; + + png_debug(1, "in png_write_oFFs\n"); + if (unit_type >= PNG_OFFSET_LAST) + png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); + + png_save_int_32(buf, x_offset); + png_save_int_32(buf + 4, y_offset); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9); +} +#endif + +#if defined(PNG_WRITE_pCAL_SUPPORTED) +/* write the pCAL chunk (described in the PNG extensions document) */ +void /* PRIVATE */ +png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, + png_int_32 X1, int type, int nparams, png_charp units, png_charpp params) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_pCAL; +#endif + png_size_t purpose_len, units_len, total_len; + png_uint_32p params_len; + png_byte buf[10]; + png_charp new_purpose; + int i; + + png_debug1(1, "in png_write_pCAL (%d parameters)\n", nparams); + if (type >= PNG_EQUATION_LAST) + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + + purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1; + png_debug1(3, "pCAL purpose length = %d\n", (int)purpose_len); + units_len = png_strlen(units) + (nparams == 0 ? 0 : 1); + png_debug1(3, "pCAL units length = %d\n", (int)units_len); + total_len = purpose_len + units_len + 10; + + params_len = (png_uint_32p)png_malloc(png_ptr, (png_uint_32)(nparams + *png_sizeof(png_uint_32))); + + /* Find the length of each parameter, making sure we don't count the + null terminator for the last parameter. */ + for (i = 0; i < nparams; i++) + { + params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); + png_debug2(3, "pCAL parameter %d length = %lu\n", i, params_len[i]); + total_len += (png_size_t)params_len[i]; + } + + png_debug1(3, "pCAL total length = %d\n", (int)total_len); + png_write_chunk_start(png_ptr, (png_bytep)png_pCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, (png_bytep)new_purpose, purpose_len); + png_save_int_32(buf, X0); + png_save_int_32(buf + 4, X1); + buf[8] = (png_byte)type; + buf[9] = (png_byte)nparams; + png_write_chunk_data(png_ptr, buf, (png_size_t)10); + png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len); + + png_free(png_ptr, new_purpose); + + for (i = 0; i < nparams; i++) + { + png_write_chunk_data(png_ptr, (png_bytep)params[i], + (png_size_t)params_len[i]); + } + + png_free(png_ptr, params_len); + png_write_chunk_end(png_ptr); +} +#endif + +#if defined(PNG_WRITE_sCAL_SUPPORTED) +/* write the sCAL chunk */ +#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) +void /* PRIVATE */ +png_write_sCAL(png_structp png_ptr, int unit, double width,double height) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sCAL; +#endif + png_size_t total_len; + char wbuf[32], hbuf[32]; + png_byte bunit = unit; + + png_debug(1, "in png_write_sCAL\n"); + +#if defined(_WIN32_WCE) +/* sprintf() function is not supported on WindowsCE */ + { + wchar_t wc_buf[32]; + swprintf(wc_buf, TEXT("%12.12e"), width); + WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, wbuf, 32, NULL, NULL); + swprintf(wc_buf, TEXT("%12.12e"), height); + WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, hbuf, 32, NULL, NULL); + } +#else + sprintf(wbuf, "%12.12e", width); + sprintf(hbuf, "%12.12e", height); +#endif + total_len = 1 + png_strlen(wbuf)+1 + png_strlen(hbuf); + + png_debug1(3, "sCAL total length = %d\n", (int)total_len); + png_write_chunk_start(png_ptr, (png_bytep)png_sCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, (png_bytep)&bunit, 1); + png_write_chunk_data(png_ptr, (png_bytep)wbuf, png_strlen(wbuf)+1); + png_write_chunk_data(png_ptr, (png_bytep)hbuf, png_strlen(hbuf)); + + png_write_chunk_end(png_ptr); +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width, + png_charp height) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sCAL; +#endif + png_size_t total_len; + char wbuf[32], hbuf[32]; + png_byte bunit = unit; + + png_debug(1, "in png_write_sCAL_s\n"); + + png_strcpy(wbuf,(const char *)width); + png_strcpy(hbuf,(const char *)height); + total_len = 1 + png_strlen(wbuf)+1 + png_strlen(hbuf); + + png_debug1(3, "sCAL total length = %d\n", total_len); + png_write_chunk_start(png_ptr, (png_bytep)png_sCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, (png_bytep)&bunit, 1); + png_write_chunk_data(png_ptr, (png_bytep)wbuf, png_strlen(wbuf)+1); + png_write_chunk_data(png_ptr, (png_bytep)hbuf, png_strlen(hbuf)); + + png_write_chunk_end(png_ptr); +} +#endif +#endif +#endif + +#if defined(PNG_WRITE_pHYs_SUPPORTED) +/* write the pHYs chunk */ +void /* PRIVATE */ +png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, + png_uint_32 y_pixels_per_unit, + int unit_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_pHYs; +#endif + png_byte buf[9]; + + png_debug(1, "in png_write_pHYs\n"); + if (unit_type >= PNG_RESOLUTION_LAST) + png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); + + png_save_uint_32(buf, x_pixels_per_unit); + png_save_uint_32(buf + 4, y_pixels_per_unit); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, (png_bytep)png_pHYs, buf, (png_size_t)9); +} +#endif + +#if defined(PNG_WRITE_tIME_SUPPORTED) +/* Write the tIME chunk. Use either png_convert_from_struct_tm() + * or png_convert_from_time_t(), or fill in the structure yourself. + */ +void /* PRIVATE */ +png_write_tIME(png_structp png_ptr, png_timep mod_time) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_tIME; +#endif + png_byte buf[7]; + + png_debug(1, "in png_write_tIME\n"); + if (mod_time->month > 12 || mod_time->month < 1 || + mod_time->day > 31 || mod_time->day < 1 || + mod_time->hour > 23 || mod_time->second > 60) + { + png_warning(png_ptr, "Invalid time specified for tIME chunk"); + return; + } + + png_save_uint_16(buf, mod_time->year); + buf[2] = mod_time->month; + buf[3] = mod_time->day; + buf[4] = mod_time->hour; + buf[5] = mod_time->minute; + buf[6] = mod_time->second; + + png_write_chunk(png_ptr, (png_bytep)png_tIME, buf, (png_size_t)7); +} +#endif + +/* initializes the row writing capability of libpng */ +void /* PRIVATE */ +png_write_start_row(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + png_size_t buf_size; + + png_debug(1, "in png_write_start_row\n"); + buf_size = (png_size_t)(PNG_ROWBYTES( + png_ptr->usr_channels*png_ptr->usr_bit_depth,png_ptr->width)+1); + + /* set up row buffer */ + png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size); + png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; + + /* set up filtering buffer, if using this filter */ + if (png_ptr->do_filter & PNG_FILTER_SUB) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + /* We only need to keep the previous row if we are using one of these. */ + if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) + { + /* set up previous row buffer */ + png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size); + png_memset(png_ptr->prev_row, 0, buf_size); + + if (png_ptr->do_filter & PNG_FILTER_UP) + { + png_ptr->up_row = (png_bytep )png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + + if (png_ptr->do_filter & PNG_FILTER_AVG) + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + + if (png_ptr->do_filter & PNG_FILTER_PAETH) + { + png_ptr->paeth_row = (png_bytep )png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* if interlaced, we need to set up width and height of pass */ + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - + png_pass_start[0]) / png_pass_inc[0]; + } + else + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + } + else +#endif + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; +} + +/* Internal use only. Called when finished processing a row of data. */ +void /* PRIVATE */ +png_write_finish_row(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + int ret; + + png_debug(1, "in png_write_finish_row\n"); + /* next row */ + png_ptr->row_number++; + + /* see if we are done */ + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* if interlaced, go to next pass */ + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + if (png_ptr->transformations & PNG_INTERLACE) + { + png_ptr->pass++; + } + else + { + /* loop until we find a non-zero width or height pass */ + do + { + png_ptr->pass++; + if (png_ptr->pass >= 7) + break; + png_ptr->usr_width = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + if (png_ptr->transformations & PNG_INTERLACE) + break; + } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); + + } + + /* reset the row above the image for the next pass */ + if (png_ptr->pass < 7) + { + if (png_ptr->prev_row != NULL) + png_memset(png_ptr->prev_row, 0, + (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* + png_ptr->usr_bit_depth,png_ptr->width))+1); + return; + } + } +#endif + + /* if we get here, we've just written the last row, so we need + to flush the compressor */ + do + { + /* tell the compressor we are done */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + /* check for an error */ + if (ret == Z_OK) + { + /* check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else if (ret != Z_STREAM_END) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* write any extra space */ + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - + png_ptr->zstream.avail_out); + } + + deflateReset(&png_ptr->zstream); +} + +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Pick out the correct pixels for the interlace pass. + * The basic idea here is to go through the row with a source + * pointer and a destination pointer (sp and dp), and copy the + * correct pixels for the pass. As the row gets compacted, + * sp will always be >= dp, so we should never overwrite anything. + * See the default: case for the easiest code to understand. + */ +void /* PRIVATE */ +png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; +#endif + + png_debug(1, "in png_do_write_interlace\n"); + /* we don't have to do anything on the last pass (6) */ +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL && pass < 6) +#else + if (pass < 6) +#endif + { + /* each pixel depth is handled separately */ + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + d = 0; + shift = 7; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 3); + value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; + d |= (value << shift); + + if (shift == 0) + { + shift = 7; + *dp++ = (png_byte)d; + d = 0; + } + else + shift--; + + } + if (shift != 7) + *dp = (png_byte)d; + break; + } + case 2: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 6; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 2); + value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; + d |= (value << shift); + + if (shift == 0) + { + shift = 6; + *dp++ = (png_byte)d; + d = 0; + } + else + shift -= 2; + } + if (shift != 6) + *dp = (png_byte)d; + break; + } + case 4: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 4; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 1); + value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; + d |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp++ = (png_byte)d; + d = 0; + } + else + shift -= 4; + } + if (shift != 4) + *dp = (png_byte)d; + break; + } + default: + { + png_bytep sp; + png_bytep dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + png_size_t pixel_bytes; + + /* start at the beginning */ + dp = row; + /* find out how many bytes each pixel takes up */ + pixel_bytes = (row_info->pixel_depth >> 3); + /* loop through the row, only looking at the pixels that + matter */ + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + /* find out where the original pixel is */ + sp = row + (png_size_t)i * pixel_bytes; + /* move the pixel */ + if (dp != sp) + png_memcpy(dp, sp, pixel_bytes); + /* next pixel */ + dp += pixel_bytes; + } + break; + } + } + /* set new row width */ + row_info->width = (row_info->width + + png_pass_inc[pass] - 1 - + png_pass_start[pass]) / + png_pass_inc[pass]; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +/* This filters the row, chooses which filter to use, if it has not already + * been specified by the application, and then writes the row out with the + * chosen filter. + */ +#define PNG_MAXSUM (~((png_uint_32)0) >> 1) +#define PNG_HISHIFT 10 +#define PNG_LOMASK ((png_uint_32)0xffffL) +#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) +void /* PRIVATE */ +png_write_find_filter(png_structp png_ptr, png_row_infop row_info) +{ + png_bytep prev_row, best_row, row_buf; + png_uint_32 mins, bpp; + png_byte filter_to_do = png_ptr->do_filter; + png_uint_32 row_bytes = row_info->rowbytes; +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + int num_p_filters = (int)png_ptr->num_prev_filters; +#endif + + png_debug(1, "in png_write_find_filter\n"); + /* find out how many bytes offset each pixel is */ + bpp = (row_info->pixel_depth + 7) >> 3; + + prev_row = png_ptr->prev_row; + best_row = row_buf = png_ptr->row_buf; + mins = PNG_MAXSUM; + + /* The prediction method we use is to find which method provides the + * smallest value when summing the absolute values of the distances + * from zero, using anything >= 128 as negative numbers. This is known + * as the "minimum sum of absolute differences" heuristic. Other + * heuristics are the "weighted minimum sum of absolute differences" + * (experimental and can in theory improve compression), and the "zlib + * predictive" method (not implemented yet), which does test compressions + * of lines using different filter methods, and then chooses the + * (series of) filter(s) that give minimum compressed data size (VERY + * computationally expensive). + * + * GRR 980525: consider also + * (1) minimum sum of absolute differences from running average (i.e., + * keep running sum of non-absolute differences & count of bytes) + * [track dispersion, too? restart average if dispersion too large?] + * (1b) minimum sum of absolute differences from sliding average, probably + * with window size <= deflate window (usually 32K) + * (2) minimum sum of squared differences from zero or running average + * (i.e., ~ root-mean-square approach) + */ + + + /* We don't need to test the 'no filter' case if this is the only filter + * that has been chosen, as it doesn't actually do anything to the data. + */ + if ((filter_to_do & PNG_FILTER_NONE) && + filter_to_do != PNG_FILTER_NONE) + { + png_bytep rp; + png_uint_32 sum = 0; + png_uint_32 i; + int v; + + for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) + { + v = *rp; + sum += (v < 128) ? v : 256 - v; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + png_uint_32 sumhi, sumlo; + int j; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ + + /* Reduce the sum if we match any of the previous rows */ + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + /* Factor in the cost of this filter (this is here for completeness, + * but it makes no sense to have a "cost" for the NONE filter, as + * it has the minimum possible computational cost - none). + */ + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + mins = sum; + } + + /* sub filter */ + if (filter_to_do == PNG_FILTER_SUB) + /* it's the only filter so no testing is needed */ + { + png_bytep rp, lp, dp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + *dp = *rp; + } + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + } + best_row = png_ptr->sub_row; + } + + else if (filter_to_do & PNG_FILTER_SUB) + { + png_bytep rp, dp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + /* We temporarily increase the "minimum sum" by the factor we + * would reduce the sum of this filter, so that we can do the + * early exit comparison without scaling the sum each time. + */ + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + v = *dp = *rp; + + sum += (v < 128) ? v : 256 - v; + } + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->sub_row; + } + } + + /* up filter */ + if (filter_to_do == PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_uint_32 i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; + i++, rp++, pp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); + } + best_row = png_ptr->up_row; + } + + else if (filter_to_do & PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->up_row; + } + } + + /* avg filter */ + if (filter_to_do == PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + } + for (lp = row_buf + 1; i < row_bytes; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) + & 0xff); + } + best_row = png_ptr->avg_row; + } + + else if (filter_to_do & PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + for (lp = row_buf + 1; i < row_bytes; i++) + { + v = *dp++ = + (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->avg_row; + } + } + + /* Paeth filter */ + if (filter_to_do == PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + } + best_row = png_ptr->paeth_row; + } + + else if (filter_to_do & PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + +#ifndef PNG_SLOW_PAETH + p = b - c; + pc = a - c; +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; +#else /* PNG_SLOW_PAETH */ + p = a + b - c; + pa = abs(p - a); + pb = abs(p - b); + pc = abs(p - c); + if (pa <= pb && pa <= pc) + p = a; + else if (pb <= pc) + p = b; + else + p = c; +#endif /* PNG_SLOW_PAETH */ + + v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + best_row = png_ptr->paeth_row; + } + } + + /* Do the actual writing of the filtered row data from the chosen filter. */ + + png_write_filtered_row(png_ptr, best_row); + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + /* Save the type of filter we picked this time for future calculations */ + if (png_ptr->num_prev_filters > 0) + { + int j; + for (j = 1; j < num_p_filters; j++) + { + png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; + } + png_ptr->prev_filters[j] = best_row[0]; + } +#endif +} + + +/* Do the actual writing of a previously filtered row. */ +void /* PRIVATE */ +png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) +{ + png_debug(1, "in png_write_filtered_row\n"); + png_debug1(2, "filter = %d\n", filtered_row[0]); + /* set up the zlib input buffer */ + + png_ptr->zstream.next_in = filtered_row; + png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1; + /* repeat until we have compressed all the data */ + do + { + int ret; /* return of zlib */ + + /* compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + /* check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + + /* see if it is time to write another IDAT */ + if (!(png_ptr->zstream.avail_out)) + { + /* write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + /* repeat until all data has been compressed */ + } while (png_ptr->zstream.avail_in); + + /* swap the current and previous rows */ + if (png_ptr->prev_row != NULL) + { + png_bytep tptr; + + tptr = png_ptr->prev_row; + png_ptr->prev_row = png_ptr->row_buf; + png_ptr->row_buf = tptr; + } + + /* finish row - updates counters and flushes zlib if last row */ + png_write_finish_row(png_ptr); + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) + png_ptr->flush_rows++; + + if (png_ptr->flush_dist > 0 && + png_ptr->flush_rows >= png_ptr->flush_dist) + { + png_write_flush(png_ptr); + } +#endif +} +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/Utilities/FLTK/src/CMakeLists.txt b/Utilities/FLTK/src/CMakeLists.txt new file mode 100644 index 0000000000..addde02f44 --- /dev/null +++ b/Utilities/FLTK/src/CMakeLists.txt @@ -0,0 +1,217 @@ +SET(CPPFILES + Fl.cxx + Fl_Adjuster.cxx + Fl_Bitmap.cxx + Fl_Browser.cxx + Fl_Browser_.cxx + Fl_Browser_load.cxx + Fl_Box.cxx + Fl_Button.cxx + Fl_Chart.cxx + Fl_Check_Browser.cxx + Fl_Check_Button.cxx + Fl_Choice.cxx + Fl_Clock.cxx + Fl_Color_Chooser.cxx + Fl_Counter.cxx + Fl_Dial.cxx + Fl_Double_Window.cxx + Fl_File_Browser.cxx + Fl_File_Chooser.cxx + Fl_File_Chooser2.cxx + Fl_File_Icon.cxx + Fl_File_Input.cxx + Fl_Group.cxx + Fl_Help_View.cxx + Fl_Image.cxx + Fl_Input.cxx + Fl_Input_.cxx + Fl_Light_Button.cxx + Fl_Menu.cxx + Fl_Menu_.cxx + Fl_Menu_Bar.cxx + Fl_Sys_Menu_Bar.cxx + Fl_Menu_Button.cxx + Fl_Menu_Window.cxx + Fl_Menu_add.cxx + Fl_Menu_global.cxx + Fl_Multi_Label.cxx + Fl_Overlay_Window.cxx + Fl_Pack.cxx + Fl_Pixmap.cxx + Fl_Positioner.cxx + Fl_Preferences.cxx + Fl_Progress.cxx + Fl_Repeat_Button.cxx + Fl_Return_Button.cxx + Fl_Roller.cxx + Fl_Round_Button.cxx + Fl_Scroll.cxx + Fl_Scrollbar.cxx + Fl_Shared_Image.cxx + Fl_Single_Window.cxx + Fl_Slider.cxx + Fl_Tabs.cxx + Fl_Text_Buffer.cxx + Fl_Text_Display.cxx + Fl_Text_Editor.cxx + Fl_Tile.cxx + Fl_Tiled_Image.cxx + Fl_Tooltip.cxx + Fl_Valuator.cxx + Fl_Value_Input.cxx + Fl_Value_Output.cxx + Fl_Value_Slider.cxx + Fl_Widget.cxx + Fl_Window.cxx + Fl_Window_fullscreen.cxx + Fl_Window_hotspot.cxx + Fl_Window_iconize.cxx + Fl_Wizard.cxx + Fl_XBM_Image.cxx + Fl_XPM_Image.cxx + Fl_abort.cxx + Fl_add_idle.cxx + Fl_arg.cxx + Fl_compose.cxx + Fl_display.cxx + Fl_get_key.cxx + Fl_get_system_colors.cxx + Fl_grab.cxx + Fl_lock.cxx + Fl_own_colormap.cxx + Fl_visual.cxx + Fl_x.cxx + filename_absolute.cxx + filename_expand.cxx + filename_ext.cxx + filename_isdir.cxx + filename_list.cxx + filename_match.cxx + filename_setext.cxx + fl_arc.cxx + fl_arci.cxx + fl_ask.cxx + fl_boxtype.cxx + fl_color.cxx + fl_cursor.cxx + fl_curve.cxx + fl_diamond_box.cxx + fl_dnd.cxx + fl_draw.cxx + fl_draw_image.cxx + fl_draw_pixmap.cxx + fl_engraved_label.cxx + fl_file_dir.cxx + fl_font.cxx + fl_labeltype.cxx + fl_line_style.cxx + fl_oval_box.cxx + fl_overlay.cxx + fl_overlay_visual.cxx + fl_plastic.cxx + fl_read_image.cxx + fl_rect.cxx + fl_round_box.cxx + fl_rounded_box.cxx + fl_set_font.cxx + fl_set_fonts.cxx + fl_scroll_area.cxx + fl_shadow_box.cxx + fl_shortcut.cxx + fl_show_colormap.cxx + fl_symbols.cxx + fl_vertex.cxx + screen_xywh.cxx + ) +SET(FLCPPFILES + forms_compatability.cxx + forms_bitmap.cxx + forms_free.cxx + forms_fselect.cxx + forms_pixmap.cxx + forms_timer.cxx + ) +SET(GLCPPFILES + Fl_Gl_Choice.cxx + Fl_Gl_Overlay.cxx + Fl_Gl_Window.cxx + gl_draw.cxx + gl_start.cxx + glut_compatability.cxx + glut_font.cxx + ) +SET(IMGCPPFILES + fl_images_core.cxx + Fl_BMP_Image.cxx + Fl_File_Icon2.cxx + Fl_GIF_Image.cxx + Fl_Help_Dialog.cxx + Fl_JPEG_Image.cxx + Fl_PNG_Image.cxx + Fl_PNM_Image.cxx + ) + +SET(CFILES + fl_call_main.c + flstring.c + scandir.c + numericsort.c + vsnprintf.c + ) + +ADD_LIBRARY(fltk ${CPPFILES} ${CFILES}) +#INSTALL_TARGETS(/lib fltk) +INSTALL(TARGETS fltk + RUNTIME DESTINATION ${OTB_INSTALL_BIN_DIR} COMPONENT RuntimeLibraries + LIBRARY DESTINATION ${OTB_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries + ARCHIVE DESTINATION ${OTB_INSTALL_LIB_DIR} COMPONENT Development) +SET_TARGET_PROPERTIES(fltk + PROPERTIES + VERSION ${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR} + SOVERSION ${FLTK_VERSION_PATCH}) + +TARGET_LINK_LIBRARIES(fltk ${FLTK_PLATFORM_DEPENDENT_LIBS} ${CMAKE_THREAD_LIBS_INIT}) + +IF(X11_FOUND) + TARGET_LINK_LIBRARIES(fltk ${X11_LIBRARIES}) +ENDIF(X11_FOUND) + +IF(OPENGL_FOUND) + ADD_LIBRARY(fltk_gl ${GLCPPFILES}) +# INSTALL_TARGETS(/lib fltk_gl) + INSTALL(TARGETS fltk_gl + RUNTIME DESTINATION ${OTB_INSTALL_BIN_DIR} COMPONENT RuntimeLibraries + LIBRARY DESTINATION ${OTB_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries + ARCHIVE DESTINATION ${OTB_INSTALL_LIB_DIR} COMPONENT Development) + TARGET_LINK_LIBRARIES(fltk_gl fltk ${OPENGL_LIBRARIES}) + SET_TARGET_PROPERTIES(fltk_gl + PROPERTIES + VERSION ${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR} + SOVERSION ${FLTK_VERSION_PATCH}) +ENDIF(OPENGL_FOUND) + +ADD_LIBRARY(fltk_forms ${FLCPPFILES}) +#INSTALL_TARGETS(/lib fltk_forms) +INSTALL(TARGETS fltk_forms + RUNTIME DESTINATION ${OTB_INSTALL_BIN_DIR} COMPONENT RuntimeLibraries + LIBRARY DESTINATION ${OTB_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries + ARCHIVE DESTINATION ${OTB_INSTALL_LIB_DIR} COMPONENT Development) +TARGET_LINK_LIBRARIES(fltk_forms fltk) +SET_TARGET_PROPERTIES(fltk_forms + PROPERTIES + VERSION ${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR} + SOVERSION ${FLTK_VERSION_PATCH}) + +ADD_LIBRARY(fltk_images ${IMGCPPFILES}) +#INSTALL_TARGETS(/lib fltk_images) +INSTALL(TARGETS fltk_images + RUNTIME DESTINATION ${OTB_INSTALL_BIN_DIR} COMPONENT RuntimeLibraries + LIBRARY DESTINATION ${OTB_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries + ARCHIVE DESTINATION ${OTB_INSTALL_LIB_DIR} COMPONENT Development) +TARGET_LINK_LIBRARIES(fltk_images fltk ${FLTK_PNG_LIBRARIES} + ${FLTK_JPEG_LIBRARIES} ${FLTK_ZLIB_LIBRARIES}) +SET_TARGET_PROPERTIES(fltk_images + PROPERTIES + VERSION ${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR} + SOVERSION ${FLTK_VERSION_PATCH}) diff --git a/Utilities/FLTK/src/Fl.cxx b/Utilities/FLTK/src/Fl.cxx new file mode 100644 index 0000000000..17967a7831 --- /dev/null +++ b/Utilities/FLTK/src/Fl.cxx @@ -0,0 +1,1203 @@ +// +// "$Id$" +// +// Main event handling code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2006 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// warning: the Apple Quartz version still uses some Quickdraw calls, +// mostly to get around the single active context in QD and +// to implement clipping. This should be changed into pure +// Quartz calls in the near future. + +#include <FL/Fl.H> +#include <FL/Fl_Window.H> +#include <FL/x.H> +#include <FL/Fl_Tooltip.H> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include "flstring.h" + +#ifdef DEBUG +# include <stdio.h> +#endif // DEBUG + +#ifdef WIN32 +# include <ole2.h> +void fl_free_fonts(void); +HBRUSH fl_brush_action(int action); +void fl_cleanup_pens(void); +void fl_release_dc(HWND,HDC); +void fl_cleanup_dc_list(void); +#endif // WIN32 + +// +// Globals... +// + +Fl_Widget *Fl::belowmouse_, + *Fl::pushed_, + *Fl::focus_, + *Fl::selection_owner_; +int Fl::damage_, + Fl::e_number, + Fl::e_x, + Fl::e_y, + Fl::e_x_root, + Fl::e_y_root, + Fl::e_dx, + Fl::e_dy, + Fl::e_state, + Fl::e_clicks, + Fl::e_is_click, + Fl::e_keysym; +char *Fl::e_text = (char *)""; +int Fl::e_length; +int Fl::visible_focus_ = 1, + Fl::dnd_text_ops_ = 1; + + +// +// 'Fl::version()' - Return the API version number... +// + +double +Fl::version() { + return FL_VERSION; +} + + +// +// 'Fl:event_inside()' - Return whether or not the mouse event is inside +// the given rectangle. +// + +int Fl::event_inside(int xx,int yy,int ww,int hh) /*const*/ { + int mx = e_x - xx; + int my = e_y - yy; + return (mx >= 0 && mx < ww && my >= 0 && my < hh); +} + +int Fl::event_inside(const Fl_Widget *o) /*const*/ { + int mx = e_x - o->x(); + int my = e_y - o->y(); + return (mx >= 0 && mx < o->w() && my >= 0 && my < o->h()); +} + +// +// +// timer support +// + +#ifdef WIN32 + +/// implementation in Fl_win32.cxx + +#elif defined(__APPLE__) + +/// implementation in Fl_mac.cxx + +#else + +// +// X11 timers +// + + +//////////////////////////////////////////////////////////////// +// Timeouts are stored in a sorted list, so only the first one needs +// to be checked to see if any should be called. + +struct Timeout { + double time; + void (*cb)(void*); + void* arg; + Timeout* next; +}; +static Timeout* first_timeout, *free_timeout; +static int first_timeout_count, free_timeout_count; + +#include <sys/time.h> + +// I avoid the overhead of getting the current time when we have no +// timeouts by setting this flag instead of getting the time. +// In this case calling elapse_timeouts() does nothing, but records +// the current time, and the next call will actualy elapse time. +static char reset_clock = 1; + +static void elapse_timeouts() { + static struct timeval prevclock; + struct timeval newclock; + gettimeofday(&newclock, NULL); + double elapsed = newclock.tv_sec - prevclock.tv_sec + + (newclock.tv_usec - prevclock.tv_usec)/1000000.0; + prevclock.tv_sec = newclock.tv_sec; + prevclock.tv_usec = newclock.tv_usec; + if (reset_clock) { + reset_clock = 0; + } else if (elapsed > 0) { + for (Timeout* t = first_timeout; t; t = t->next) t->time -= elapsed; + } +} + +// Continuously-adjusted error value, this is a number <= 0 for how late +// we were at calling the last timeout. This appears to make repeat_timeout +// very accurate even when processing takes a significant portion of the +// time interval: +static double missed_timeout_by; + +void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void *argp) { + elapse_timeouts(); + repeat_timeout(time, cb, argp); +} + +void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp) { + time += missed_timeout_by; if (time < -.05) time = 0; + Timeout* t = free_timeout; + if (t) { + free_timeout = t->next; + --free_timeout_count; + } else { + t = new Timeout; + } + t->time = time; + t->cb = cb; + t->arg = argp; + // insert-sort the new timeout: + Timeout** p = &first_timeout; + while (*p && (*p)->time <= time) p = &((*p)->next); + t->next = *p; + *p = t; +} + +int Fl::has_timeout(Fl_Timeout_Handler cb, void *argp) { + for (Timeout* t = first_timeout; t; t = t->next) + if (t->cb == cb && t->arg == argp) return 1; + return 0; +} + +void Fl::remove_timeout(Fl_Timeout_Handler cb, void *argp) { + // This version removes all matching timeouts, not just the first one. + // This may change in the future. + for (Timeout** p = &first_timeout; *p;) { + Timeout* t = *p; + if (t->cb == cb && (t->arg == argp || !argp)) { + *p = t->next; + t->next = free_timeout; + free_timeout = t; + } else { + p = &(t->next); + } + } +} + +#endif + +//////////////////////////////////////////////////////////////// +// Checks are just stored in a list. They are called in the reverse +// order that they were added (this may change in the future). +// This is a bit messy because I want to allow checks to be added, +// removed, and have wait() called from inside them, to do this +// next_check points at the next unprocessed one for the outermost +// call to Fl::wait(). + +struct Check { + void (*cb)(void*); + void* arg; + Check* next; +}; +static Check *first_check, *next_check, *free_check; + +void Fl::add_check(Fl_Timeout_Handler cb, void *argp) { + Check* t = free_check; + if (t) free_check = t->next; + else t = new Check; + t->cb = cb; + t->arg = argp; + t->next = first_check; + if (next_check == first_check) next_check = t; + first_check = t; +} + +void Fl::remove_check(Fl_Timeout_Handler cb, void *argp) { + for (Check** p = &first_check; *p;) { + Check* t = *p; + if (t->cb == cb && t->arg == argp) { + if (next_check == t) next_check = t->next; + *p = t->next; + t->next = free_check; + free_check = t; + } else { + p = &(t->next); + } + } +} + +#if !defined(__APPLE__) +static void run_checks() +{ + // checks are a bit messy so that add/remove and wait may be called + // from inside them without causing an infinite loop: + if (next_check == first_check) { + while (next_check) { + Check* checkp = next_check; + next_check = checkp->next; + (checkp->cb)(checkp->arg); + } + next_check = first_check; + } +} +#endif // !__APPLE__ + +static char in_idle; + +//////////////////////////////////////////////////////////////// +// wait/run/check/ready: + +void (*Fl::idle)(); // see Fl_add_idle.cxx for the add/remove functions + +extern int fl_ready(); // in Fl_<platform>.cxx +extern int fl_wait(double time); // in Fl_<platform>.cxx + +double Fl::wait(double time_to_wait) { + // delete all widgets that were listed during callbacks + do_widget_deletion(); + +#ifdef WIN32 + + return fl_wait(time_to_wait); + +#elif defined(__APPLE__) + + flush(); + if (idle) { + if (!in_idle) { + in_idle = 1; + idle(); + in_idle = 0; + } + // the idle function may turn off idle, we can then wait: + if (idle) time_to_wait = 0.0; + } + return fl_wait(time_to_wait); + +#else + + if (first_timeout) { + elapse_timeouts(); + Timeout *t; + while ((t = first_timeout)) { + if (t->time > 0) break; + // The first timeout in the array has expired. + missed_timeout_by = t->time; + // We must remove timeout from array before doing the callback: + void (*cb)(void*) = t->cb; + void *argp = t->arg; + first_timeout = t->next; + t->next = free_timeout; + free_timeout = t; + ++free_timeout_count; + --first_timeout_count; + // Now it is safe for the callback to do add_timeout: + cb(argp); + } + } else { + reset_clock = 1; // we are not going to check the clock + } + run_checks(); +// if (idle && !fl_ready()) { + if (idle) { + if (!in_idle) { + in_idle = 1; + idle(); + in_idle = 0; + } + // the idle function may turn off idle, we can then wait: + if (idle) time_to_wait = 0.0; + } + if (first_timeout && first_timeout->time < time_to_wait) + time_to_wait = first_timeout->time; + if (time_to_wait <= 0.0) { + // do flush second so that the results of events are visible: + int ret = fl_wait(0.0); + flush(); + return ret; + } else { + // do flush first so that user sees the display: + flush(); + return fl_wait(time_to_wait); + } +#endif +} + +#define FOREVER 1e20 + +int Fl::run() { + while (Fl_X::first) wait(FOREVER); +#ifdef WIN32 + fl_free_fonts(); // do some WIN32 cleanup + fl_cleanup_pens(); + OleUninitialize(); + fl_brush_action(1); + fl_cleanup_dc_list(); +#endif + return 0; +} + +int Fl::wait() { + if (!Fl_X::first) return 0; + wait(FOREVER); + return Fl_X::first != 0; // return true if there is a window +} + +int Fl::check() { + wait(0.0); + return Fl_X::first != 0; // return true if there is a window +} + +int Fl::ready() { +#if ! defined( WIN32 ) && ! defined(__APPLE__) + if (first_timeout) { + elapse_timeouts(); + if (first_timeout->time <= 0) return 1; + } else { + reset_clock = 1; + } +#endif + return fl_ready(); +} + +//////////////////////////////////////////////////////////////// +// Window list management: + +Fl_X* Fl_X::first; + +Fl_Window* fl_find(Window xid) { + Fl_X *window; + for (Fl_X **pp = &Fl_X::first; (window = *pp); pp = &window->next) +#ifdef __APPLE_QD__ + if (window->xid == xid && !window->w->window()) { +#elif defined(__APPLE_QUARTZ__) + if (window->xid == xid && !window->w->window()) { +#else + if (window->xid == xid) { +#endif // __APPLE__ + if (window != Fl_X::first && !Fl::modal()) { + // make this window be first to speed up searches + // this is not done if modal is true to avoid messing up modal stack + *pp = window->next; + window->next = Fl_X::first; + Fl_X::first = window; + } + return window->w; + } + return 0; +} + +Fl_Window* Fl::first_window() { + Fl_X* i = Fl_X::first; + return i ? i->w : 0; +} + +Fl_Window* Fl::next_window(const Fl_Window* window) { + Fl_X* i = Fl_X::i(window)->next; + return i ? i->w : 0; +} + +void Fl::first_window(Fl_Window* window) { + if (!window || !window->shown()) return; + fl_find(fl_xid(window)); +} + +void Fl::redraw() { + for (Fl_X* i = Fl_X::first; i; i = i->next) i->w->redraw(); +} + +void Fl::flush() { + if (damage()) { + damage_ = 0; + for (Fl_X* i = Fl_X::first; i; i = i->next) { + if (i->wait_for_expose) {damage_ = 1; continue;} + Fl_Window* wi = i->w; + if (!wi->visible_r()) continue; + if (wi->damage()) {i->flush(); wi->clear_damage();} + // destroy damage regions for windows that don't use them: + if (i->region) {XDestroyRegion(i->region); i->region = 0;} + } + } + +#ifdef WIN32 + GdiFlush(); +#elif defined(__APPLE_QD__) + GrafPtr port; + GetPort( &port ); + if ( port ) + QDFlushPortBuffer( port, 0 ); +#elif defined (__APPLE_QUARTZ__) + if (fl_gc) + CGContextFlush(fl_gc); +#else + if (fl_display) XFlush(fl_display); +#endif +} + +//////////////////////////////////////////////////////////////// +// Event handlers: + +struct handler_link { + int (*handle)(int); + handler_link *next; +}; + +static handler_link *handlers = 0; + +void Fl::add_handler(int (*ha)(int)) { + handler_link *l = new handler_link; + l->handle = ha; + l->next = handlers; + handlers = l; +} + +void Fl::remove_handler(int (*ha)(int)) { + handler_link *l, *p; + + // Search for the handler in the list... + for (l = handlers, p = 0; l && l->handle != ha; p = l, l = l->next); + + if (l) { + // Found it, so remove it from the list... + if (p) p->next = l->next; + else handlers = l->next; + + // And free the record... + delete l; + } +} + +int (*fl_local_grab)(int); // used by fl_dnd.cxx + +static int send_handlers(int e) { + for (const handler_link *hl = handlers; hl; hl = hl->next) + if (hl->handle(e)) return 1; + return 0; +} + +//////////////////////////////////////////////////////////////// + +Fl_Widget* fl_oldfocus; // kludge for Fl_Group... + +void Fl::focus(Fl_Widget *o) { + if (o && !o->visible_focus()) return; + if (grab()) return; // don't do anything while grab is on + Fl_Widget *p = focus_; + if (o != p) { + Fl::compose_reset(); + focus_ = o; + fl_oldfocus = 0; + int old_event = e_number; + e_number = FL_UNFOCUS; + for (; p; p = p->parent()) { + p->handle(FL_UNFOCUS); + fl_oldfocus = p; + } + e_number = old_event; + } +} + +static char dnd_flag = 0; // make 'belowmouse' send DND_LEAVE instead of LEAVE + +void Fl::belowmouse(Fl_Widget *o) { + if (grab()) return; // don't do anything while grab is on + Fl_Widget *p = belowmouse_; + if (o != p) { + belowmouse_ = o; + int old_event = e_number; + e_number = dnd_flag ? FL_DND_LEAVE : FL_LEAVE; + for (; p && !p->contains(o); p = p->parent()) { + p->handle(e_number); + } + e_number = old_event; + } +} + +void Fl::pushed(Fl_Widget *o) { + pushed_ = o; +} + +Fl_Window *fl_xfocus; // which window X thinks has focus +Fl_Window *fl_xmousewin;// which window X thinks has FL_ENTER +Fl_Window *Fl::grab_; // most recent Fl::grab() +Fl_Window *Fl::modal_; // topmost modal() window + +static void nothing(Fl_Widget *) {} +void (*Fl_Tooltip::enter)(Fl_Widget *) = nothing; +void (*Fl_Tooltip::exit)(Fl_Widget *) = nothing; + +// Update modal(), focus() and other state according to system state, +// and send FL_ENTER, FL_LEAVE, FL_FOCUS, and/or FL_UNFOCUS events. +// This is the only function that produces these events in response +// to system activity. +// This is called whenever a window is added or hidden, and whenever +// X says the focus or mouse window have changed. + +void fl_fix_focus() { +#ifdef DEBUG + puts("fl_fix_focus();"); +#endif // DEBUG + + if (Fl::grab()) return; // don't do anything while grab is on. + + // set focus based on Fl::modal() and fl_xfocus + Fl_Widget* w = fl_xfocus; + if (w) { + int saved = Fl::e_keysym; + if (Fl::e_keysym < (FL_Button + FL_LEFT_MOUSE) || + Fl::e_keysym > (FL_Button + FL_RIGHT_MOUSE)) + Fl::e_keysym = 0; // make sure widgets don't think a keystroke moved focus + while (w->parent()) w = w->parent(); + if (Fl::modal()) w = Fl::modal(); + if (!w->contains(Fl::focus())) + if (!w->take_focus()) Fl::focus(w); + Fl::e_keysym = saved; + } else + Fl::focus(0); + +// MRS: Originally we checked the button state, but a user reported that it +// broke click-to-focus in FLWM?!? +// if (!(Fl::event_state() & 0x7f00000 /*FL_BUTTONS*/)) { + if (!Fl::pushed()) { + // set belowmouse based on Fl::modal() and fl_xmousewin: + w = fl_xmousewin; + if (w) { + if (Fl::modal()) w = Fl::modal(); + if (!w->contains(Fl::belowmouse())) { + int old_event = Fl::e_number; + w->handle(Fl::e_number = FL_ENTER); + Fl::e_number = old_event; + if (!w->contains(Fl::belowmouse())) Fl::belowmouse(w); + } else { + // send a FL_MOVE event so the enter/leave state is up to date + Fl::e_x = Fl::e_x_root-fl_xmousewin->x(); + Fl::e_y = Fl::e_y_root-fl_xmousewin->y(); + int old_event = Fl::e_number; + w->handle(Fl::e_number = FL_MOVE); + Fl::e_number = old_event; + } + } else { + Fl::belowmouse(0); + Fl_Tooltip::enter(0); + } + } +} + +#ifndef WIN32 +extern Fl_Widget *fl_selection_requestor; // from Fl_x.cxx +#endif + +// This function is called by ~Fl_Widget() and by Fl_Widget::deactivate +// and by Fl_Widget::hide(). It indicates that the widget does not want +// to receive any more events, and also removes all global variables that +// point at the widget. +// I changed this from the 1.0.1 behavior, the older version could send +// FL_LEAVE or FL_UNFOCUS events to the widget. This appears to not be +// desirable behavior and caused flwm to crash. + +void fl_throw_focus(Fl_Widget *o) { +#ifdef DEBUG + printf("fl_throw_focus(o=%p)\n", o); +#endif // DEBUG + + if (o->contains(Fl::pushed())) Fl::pushed_ = 0; +#ifndef WIN32 + if (o->contains(fl_selection_requestor)) fl_selection_requestor = 0; +#endif + if (o->contains(Fl::belowmouse())) Fl::belowmouse_ = 0; + if (o->contains(Fl::focus())) Fl::focus_ = 0; + if (o == fl_xfocus) fl_xfocus = 0; + if (o == Fl_Tooltip::current()) Fl_Tooltip::current(0); + if (o == fl_xmousewin) fl_xmousewin = 0; + Fl_Tooltip::exit(o); + fl_fix_focus(); +} + +//////////////////////////////////////////////////////////////// + +// Call to->handle but first replace the mouse x/y with the correct +// values to account for nested X windows. 'window' is the outermost +// window the event was posted to by X: +static int send(int event, Fl_Widget* to, Fl_Window* window) { + int dx, dy; + int old_event = Fl::e_number; + if (window) { + dx = window->x(); + dy = window->y(); + } else { + dx = dy = 0; + } + for (const Fl_Widget* w = to; w; w = w->parent()) + if (w->type()>=FL_WINDOW) {dx -= w->x(); dy -= w->y();} + int save_x = Fl::e_x; Fl::e_x += dx; + int save_y = Fl::e_y; Fl::e_y += dy; + int ret = to->handle(Fl::e_number = event); + Fl::e_number = old_event; + Fl::e_y = save_y; + Fl::e_x = save_x; + return ret; +} + +int Fl::handle(int e, Fl_Window* window) +{ + e_number = e; + if (fl_local_grab) return fl_local_grab(e); + + Fl_Widget* wi = window; + + switch (e) { + + case FL_CLOSE: + if (grab() || modal() && window != modal()) return 0; + wi->do_callback(); + return 1; + + case FL_SHOW: + wi->show(); // this calls Fl_Widget::show(), not Fl_Window::show() + return 1; + + case FL_HIDE: + wi->hide(); // this calls Fl_Widget::hide(), not Fl_Window::hide() + return 1; + + case FL_PUSH: +#ifdef DEBUG + printf("Fl::handle(e=%d, window=%p);\n", e, window); +#endif // DEBUG + + if (grab()) wi = grab(); + else if (modal() && wi != modal()) return 0; + pushed_ = wi; + Fl_Tooltip::current(wi); + if (send(e, wi, window)) return 1; + // raise windows that are clicked on: + window->show(); + return 1; + + case FL_DND_ENTER: + case FL_DND_DRAG: + dnd_flag = 1; + break; + + case FL_DND_LEAVE: + dnd_flag = 1; + belowmouse(0); + dnd_flag = 0; + return 1; + + case FL_DND_RELEASE: + wi = belowmouse(); + break; + + case FL_MOVE: + case FL_DRAG: + fl_xmousewin = window; // this should already be set, but just in case. + if (pushed()) { + wi = pushed(); + if (grab()) wi = grab(); + e_number = e = FL_DRAG; + break; + } + if (modal() && wi != modal()) wi = 0; + if (grab()) wi = grab(); + {Fl_Widget* pbm = belowmouse(); + int ret = (wi && send(e, wi, window)); + if (pbm != belowmouse()) { +#ifdef DEBUG + printf("Fl::handle(e=%d, window=%p);\n", e, window); +#endif // DEBUG + Fl_Tooltip::enter(belowmouse()); + } + return ret;} + + case FL_RELEASE: { +// printf("FL_RELEASE: window=%p, pushed() = %p, grab() = %p, modal() = %p\n", +// window, pushed(), grab(), modal()); + + if (grab()) { + wi = grab(); + pushed_ = 0; // must be zero before callback is done! + } else if (pushed()) { + wi = pushed(); + pushed_ = 0; // must be zero before callback is done! + } else if (modal() && wi != modal()) return 0; + int r = send(e, wi, window); + fl_fix_focus(); + return r;} + + case FL_UNFOCUS: + window = 0; + case FL_FOCUS: + fl_xfocus = window; + fl_fix_focus(); + return 1; + + case FL_KEYBOARD: +#ifdef DEBUG + printf("Fl::handle(e=%d, window=%p);\n", e, window); +#endif // DEBUG + + Fl_Tooltip::enter((Fl_Widget*)0); + + fl_xfocus = window; // this should not happen! But maybe it does: + + // Try it as keystroke, sending it to focus and all parents: + for (wi = grab() ? grab() : focus(); wi; wi = wi->parent()) + if (send(FL_KEYBOARD, wi, window)) return 1; + + // recursive call to try shortcut: + if (handle(FL_SHORTCUT, window)) return 1; + + // and then try a shortcut with the case of the text swapped, by + // changing the text and falling through to FL_SHORTCUT case: + {unsigned char* c = (unsigned char*)event_text(); // cast away const + if (!isalpha(*c)) return 0; + *c = isupper(*c) ? tolower(*c) : toupper(*c);} + e_number = e = FL_SHORTCUT; + + case FL_SHORTCUT: + if (grab()) {wi = grab(); break;} // send it to grab window + + // Try it as shortcut, sending to mouse widget and all parents: + wi = belowmouse(); if (!wi) {wi = modal(); if (!wi) wi = window;} + for (; wi; wi = wi->parent()) if (send(FL_SHORTCUT, wi, window)) return 1; + + // try using add_handle() functions: + if (send_handlers(FL_SHORTCUT)) return 1; + + // make Escape key close windows: + if (event_key()==FL_Escape) { + wi = modal(); if (!wi) wi = window; + wi->do_callback(); + return 1; + } + + return 0; + + case FL_ENTER: +#ifdef DEBUG + printf("Fl::handle(e=%d, window=%p);\n", e, window); +#endif // DEBUG + + fl_xmousewin = window; + fl_fix_focus(); + Fl_Tooltip::enter(belowmouse()); + return 1; + + case FL_LEAVE: +#ifdef DEBUG + printf("Fl::handle(e=%d, window=%p);\n", e, window); +#endif // DEBUG + + if (!pushed_) { + belowmouse(0); + Fl_Tooltip::enter(0); + } + if (window == fl_xmousewin) {fl_xmousewin = 0; fl_fix_focus();} + return 1; + + case FL_MOUSEWHEEL: + fl_xfocus = window; // this should not happen! But maybe it does: + + // Try sending it to the grab and then the window: + if (grab()) { + if (send(FL_MOUSEWHEEL, grab(), window)) return 1; + } + if (send(FL_MOUSEWHEEL, window, window)) return 1; + default: + break; + } + if (wi && send(e, wi, window)) { + dnd_flag = 0; + return 1; + } + dnd_flag = 0; + return send_handlers(e); +} + +//////////////////////////////////////////////////////////////// +// hide() destroys the X window, it does not do unmap! + +#if !defined(WIN32) && USE_XFT +extern void fl_destroy_xft_draw(Window); +#endif + +void Fl_Window::hide() { + clear_visible(); + + if (!shown()) return; + + // remove from the list of windows: + Fl_X* ip = i; + Fl_X** pp = &Fl_X::first; + for (; *pp != ip; pp = &(*pp)->next) if (!*pp) return; + *pp = ip->next; + +#ifdef __APPLE_QD__ + // remove all childwindow links + for ( Fl_X *pc = Fl_X::first; pc; pc = pc->next ) + { + if ( pc->xidNext == ip ) pc->xidNext = ip->xidNext; + if ( pc->xidChildren == ip ) pc->xidChildren = ip->xidNext; + } +#elif defined(__APPLE_QUARTZ__) + // remove all childwindow links + for ( Fl_X *pc = Fl_X::first; pc; pc = pc->next ) + { + if ( pc->xidNext == ip ) pc->xidNext = ip->xidNext; + if ( pc->xidChildren == ip ) pc->xidChildren = ip->xidNext; + } +#endif // __APPLE__ + + i = 0; + + // recursively remove any subwindows: + for (Fl_X *wi = Fl_X::first; wi;) { + Fl_Window* W = wi->w; + if (W->window() == this) { + W->hide(); + W->set_visible(); + wi = Fl_X::first; + } else wi = wi->next; + } + + if (this == Fl::modal_) { // we are closing the modal window, find next one: + Fl_Window* W; + for (W = Fl::first_window(); W; W = Fl::next_window(W)) + if (W->modal()) break; + Fl::modal_ = W; + } + + // Make sure no events are sent to this window: + fl_throw_focus(this); + handle(FL_HIDE); + +#ifdef WIN32 + // this little trick keeps the current clipboard alive, even if we are about + // to destroy the window that owns the selection. + if (GetClipboardOwner()==ip->xid) { + Fl_Window *w1 = Fl::first_window(); + if (w1 && OpenClipboard(fl_xid(w1))) { + EmptyClipboard(); + SetClipboardData(CF_TEXT, NULL); + CloseClipboard(); + } + } + // Send a message to myself so that I'll get out of the event loop... + PostMessage(ip->xid, WM_APP, 0, 0); + if (ip->private_dc) fl_release_dc(ip->xid, ip->private_dc); + if (ip->xid == fl_window && fl_gc) { + fl_release_dc(fl_window, fl_gc); + fl_window = (HWND)-1; + fl_gc = 0; + } +#elif defined(__APPLE_QD__) + if ( ip->xid == fl_window ) + fl_window = 0; +#elif defined(__APPLE_QUARTZ__) + Fl_X::q_release_context(ip); + if ( ip->xid == fl_window ) + fl_window = 0; +#endif + + if (ip->region) XDestroyRegion(ip->region); + +#ifdef WIN32 + XDestroyWindow(fl_display, ip->xid); +#elif defined(__APPLE_QD__) + if ( !parent() ) // don't destroy shared windows! + { + //+ RemoveTrackingHandler( dndTrackingHandler, ip->xid ); + //+ RemoveReceiveHandler( dndReceiveHandler, ip->xid ); + XDestroyWindow(fl_display, ip->xid); + } +#elif defined(__APPLE_QUARTZ__) + if ( !parent() ) // don't destroy shared windows! + { + //+ RemoveTrackingHandler( dndTrackingHandler, ip->xid ); + //+ RemoveReceiveHandler( dndReceiveHandler, ip->xid ); + XDestroyWindow(fl_display, ip->xid); + } +#else +# if USE_XFT + fl_destroy_xft_draw(ip->xid); +# endif + XDestroyWindow(fl_display, ip->xid); +#endif + +#ifdef WIN32 + // Try to stop the annoying "raise another program" behavior + if (non_modal() && Fl::first_window() && Fl::first_window()->shown()) + Fl::first_window()->show(); +#endif + delete ip; +} + +Fl_Window::~Fl_Window() { + hide(); +} + +// FL_SHOW and FL_HIDE are called whenever the visibility of this widget +// or any parent changes. We must correctly map/unmap the system's window. + +// For top-level windows it is assummed the window has already been +// mapped or unmapped!!! This is because this should only happen when +// Fl_Window::show() or Fl_Window::hide() is called, or in response to +// iconize/deiconize events from the system. + +int Fl_Window::handle(int ev) +{ + if (parent()) { + switch (ev) { + case FL_SHOW: + if (!shown()) show(); + else XMapWindow(fl_display, fl_xid(this)); // extra map calls are harmless + break; + case FL_HIDE: + if (shown()) { + // Find what really turned invisible, if is was a parent window + // we do nothing. We need to avoid unnecessary unmap calls + // because they cause the display to blink when the parent is + // remapped. However if this or any intermediate non-window + // widget has really had hide() called directly on it, we must + // unmap because when the parent window is remapped we don't + // want to reappear. + if (visible()) { + Fl_Widget* p = parent(); for (;p->visible();p = p->parent()) {} + if (p->type() >= FL_WINDOW) break; // don't do the unmap + } +#ifdef __APPLE_QD__ + hide(); + set_visible(); +#elif defined(__APPLE_QUARTZ__) + hide(); + set_visible(); +#else + XUnmapWindow(fl_display, fl_xid(this)); +#endif // __APPLE__ + } + break; + } +// } else if (ev == FL_FOCUS || ev == FL_UNFOCUS) { +// Fl_Tooltip::exit(Fl_Tooltip::current()); + } + + return Fl_Group::handle(ev); +} + +//////////////////////////////////////////////////////////////// +// Back compatability cut & paste functions for fltk 1.1 only: + +void Fl::selection_owner(Fl_Widget *owner) {selection_owner_ = owner;} + +void Fl::selection(Fl_Widget &owner, const char* text, int len) { + selection_owner_ = &owner; + Fl::copy(text, len, 0); +} + +void Fl::paste(Fl_Widget &receiver) { + Fl::paste(receiver, 0); +} + +//////////////////////////////////////////////////////////////// + +#include <FL/fl_draw.H> + +void Fl_Widget::redraw() { + damage(FL_DAMAGE_ALL); +} + +void Fl_Widget::redraw_label() { + if (window()) { + if (box() == FL_NO_BOX) { + // Widgets with the FL_NO_BOX boxtype need a parent to + // redraw, since it is responsible for redrawing the + // background... + int X = x() > 0 ? x() - 1 : 0; + int Y = y() > 0 ? y() - 1 : 0; + window()->damage(FL_DAMAGE_ALL, X, Y, w() + 2, h() + 2); + } + + if (align() && !(align() & FL_ALIGN_INSIDE) && window()->shown()) { + // If the label is not inside the widget, compute the location of + // the label and redraw the window within that bounding box... + int W = 0, H = 0; + label_.measure(W, H); + W += 5; // Add a little to the size of the label to cover overflow + H += 5; + + if (align() & FL_ALIGN_BOTTOM) { + window()->damage(FL_DAMAGE_EXPOSE, x(), y() + h(), w(), H); + } else if (align() & FL_ALIGN_TOP) { + window()->damage(FL_DAMAGE_EXPOSE, x(), y() - H, w(), H); + } else if (align() & FL_ALIGN_LEFT) { + window()->damage(FL_DAMAGE_EXPOSE, x() - W, y(), W, h()); + } else if (align() & FL_ALIGN_RIGHT) { + window()->damage(FL_DAMAGE_EXPOSE, x() + w(), y(), W, h()); + } else { + window()->damage(FL_DAMAGE_ALL); + } + } else { + // The label is inside the widget, so just redraw the widget itself... + damage(FL_DAMAGE_ALL); + } + } +} + +void Fl_Widget::damage(uchar fl) { + if (type() < FL_WINDOW) { + // damage only the rectangle covered by a child widget: + damage(fl, x(), y(), w(), h()); + } else { + // damage entire window by deleting the region: + Fl_X* i = Fl_X::i((Fl_Window*)this); + if (!i) return; // window not mapped, so ignore it + if (i->region) {XDestroyRegion(i->region); i->region = 0;} + damage_ |= fl; + Fl::damage(FL_DAMAGE_CHILD); + } +} + +void Fl_Widget::damage(uchar fl, int X, int Y, int W, int H) { + Fl_Widget* wi = this; + // mark all parent widgets between this and window with FL_DAMAGE_CHILD: + while (wi->type() < FL_WINDOW) { + wi->damage_ |= fl; + wi = wi->parent(); + if (!wi) return; + fl = FL_DAMAGE_CHILD; + } + Fl_X* i = Fl_X::i((Fl_Window*)wi); + if (!i) return; // window not mapped, so ignore it + + // clip the damage to the window and quit if none: + if (X < 0) {W += X; X = 0;} + if (Y < 0) {H += Y; Y = 0;} + if (W > wi->w()-X) W = wi->w()-X; + if (H > wi->h()-Y) H = wi->h()-Y; + if (W <= 0 || H <= 0) return; + + if (!X && !Y && W==wi->w() && H==wi->h()) { + // if damage covers entire window delete region: + wi->damage(fl); + return; + } + + if (wi->damage()) { + // if we already have damage we must merge with existing region: + if (i->region) { +#ifdef WIN32 + Fl_Region R = XRectangleRegion(X, Y, W, H); + CombineRgn(i->region, i->region, R, RGN_OR); + XDestroyRegion(R); +#elif defined(__APPLE_QD__) + Fl_Region R = NewRgn(); + SetRectRgn(R, X, Y, X+W, Y+H); + UnionRgn(R, i->region, i->region); + DisposeRgn(R); +#elif defined(__APPLE_QUARTZ__) + Fl_Region R = NewRgn(); + SetRectRgn(R, X, Y, X+W, Y+H); + UnionRgn(R, i->region, i->region); + DisposeRgn(R); +#else + XRectangle R; + R.x = X; R.y = Y; R.width = W; R.height = H; + XUnionRectWithRegion(&R, i->region, i->region); +#endif + } + wi->damage_ |= fl; + } else { + // create a new region: + if (i->region) XDestroyRegion(i->region); + i->region = XRectangleRegion(X,Y,W,H); + wi->damage_ = fl; + } + Fl::damage(FL_DAMAGE_CHILD); +} + +void Fl_Window::flush() { + make_current(); +//if (damage() == FL_DAMAGE_EXPOSE && can_boxcheat(box())) fl_boxcheat = this; + fl_clip_region(i->region); i->region = 0; + draw(); +} + +#ifdef WIN32 +# include "Fl_win32.cxx" +#elif defined(__APPLE__) +# include "Fl_mac.cxx" +#endif + +// +// The following methods allow callbacks to schedule the deletion of +// widgets at "safe" times. +// + +static int num_dwidgets = 0, alloc_dwidgets = 0; +static Fl_Widget **dwidgets = 0; + +void +Fl::delete_widget(Fl_Widget *wi) { + if (!wi) return; + + if (num_dwidgets >= alloc_dwidgets) { + Fl_Widget **temp; + + temp = new Fl_Widget *[alloc_dwidgets + 10]; + if (alloc_dwidgets) { + memcpy(temp, dwidgets, alloc_dwidgets * sizeof(Fl_Widget *)); + delete[] dwidgets; + } + + dwidgets = temp; + alloc_dwidgets += 10; + } + + dwidgets[num_dwidgets] = wi; + num_dwidgets ++; +} + + +void +Fl::do_widget_deletion() { + if (!num_dwidgets) return; + + for (int i = 0; i < num_dwidgets; i ++) + delete dwidgets[i]; + + num_dwidgets = 0; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Adjuster.cxx b/Utilities/FLTK/src/Fl_Adjuster.cxx new file mode 100644 index 0000000000..5c5e46f3a2 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Adjuster.cxx @@ -0,0 +1,171 @@ +// +// "$Id$" +// +// Adjuster widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + + +#include <FL/Fl.H> +#include <FL/Fl_Adjuster.H> +#include <FL/Fl_Bitmap.H> +#include <FL/fl_draw.H> + +#include "fastarrow.h" +static Fl_Bitmap fastarrow(fastarrow_bits, fastarrow_width, fastarrow_height); +#include "mediumarrow.h" +static Fl_Bitmap mediumarrow(mediumarrow_bits, mediumarrow_width, mediumarrow_height); +#include "slowarrow.h" +static Fl_Bitmap slowarrow(slowarrow_bits, slowarrow_width, slowarrow_height); + +// changing the value does not change the appearance: +void Fl_Adjuster::value_damage() {} + +void Fl_Adjuster::draw() { + int dx, dy, W, H; + if (w()>=h()) { + dx = W = w()/3; + dy = 0; H = h(); + } else { + dx = 0; W = w(); + dy = H = h()/3; + } + draw_box(drag==1?FL_DOWN_BOX:box(), x(), y()+2*dy, W, H, color()); + draw_box(drag==2?FL_DOWN_BOX:box(), x()+dx, y()+dy, W, H, color()); + draw_box(drag==3?FL_DOWN_BOX:box(), x()+2*dx, y(), W, H, color()); + if (active_r()) + fl_color(selection_color()); + else + fl_color(fl_inactive(selection_color())); + fastarrow.draw(x()+(W-fastarrow_width)/2, + y()+2*dy+(H-fastarrow_height)/2, W, H); + mediumarrow.draw(x()+dx+(W-mediumarrow_width)/2, + y()+dy+(H-mediumarrow_height)/2, W, H); + slowarrow.draw(x()+2*dx+(W-slowarrow_width)/2, + y()+(H-slowarrow_width)/2, W, H); + if (Fl::focus() == this) draw_focus(); +} + +int Fl_Adjuster::handle(int event) { + double v; + int delta; + int mx = Fl::event_x(); + switch (event) { + case FL_PUSH: + if (Fl::visible_focus()) Fl::focus(this); + ix = mx; + if (w()>=h()) + drag = 3*(mx-x())/w() + 1; + else + drag = 3-3*(Fl::event_y()-y()-1)/h(); + handle_push(); + redraw(); + return 1; + case FL_DRAG: + if (w() >= h()) { + delta = x()+(drag-1)*w()/3; // left edge of button + if (mx < delta) + delta = mx-delta; + else if (mx > (delta+w()/3)) // right edge of button + delta = mx-delta-w()/3; + else + delta = 0; + } else { + if (mx < x()) + delta = mx-x(); + else if (mx > (x()+w())) + delta = mx-x()-w(); + else + delta = 0; + } + switch (drag) { + case 3: v = increment(previous_value(), delta); break; + case 2: v = increment(previous_value(), delta*10); break; + default:v = increment(previous_value(), delta*100); break; + } + handle_drag(soft() ? softclamp(v) : clamp(v)); + return 1; + case FL_RELEASE: + if (Fl::event_is_click()) { // detect click but no drag + if (Fl::event_state()&0xF0000) delta = -10; + else delta = 10; + switch (drag) { + case 3: v = increment(previous_value(), delta); break; + case 2: v = increment(previous_value(), delta*10); break; + default:v = increment(previous_value(), delta*100); break; + } + handle_drag(soft() ? softclamp(v) : clamp(v)); + } + drag = 0; + redraw(); + handle_release(); + return 1; + case FL_KEYBOARD : + switch (Fl::event_key()) { + case FL_Up: + if (w() > h()) return 0; + handle_drag(clamp(increment(value(),-1))); + return 1; + case FL_Down: + if (w() > h()) return 0; + handle_drag(clamp(increment(value(),1))); + return 1; + case FL_Left: + if (w() < h()) return 0; + handle_drag(clamp(increment(value(),-1))); + return 1; + case FL_Right: + if (w() < h()) return 0; + handle_drag(clamp(increment(value(),1))); + return 1; + default: + return 0; + } + // break not required because of switch... + + case FL_FOCUS: + case FL_UNFOCUS: + if (Fl::visible_focus()) { + redraw(); + return 1; + } else return 0; + + case FL_ENTER : + case FL_LEAVE : + return 1; + } + return 0; +} + +Fl_Adjuster::Fl_Adjuster(int X, int Y, int W, int H, const char* l) + : Fl_Valuator(X, Y, W, H, l) { + box(FL_UP_BOX); + step(1, 10000); + selection_color(FL_SELECTION_COLOR); + drag = 0; + soft_ = 1; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_BMP_Image.cxx b/Utilities/FLTK/src/Fl_BMP_Image.cxx new file mode 100644 index 0000000000..2af7f0c95e --- /dev/null +++ b/Utilities/FLTK/src/Fl_BMP_Image.cxx @@ -0,0 +1,496 @@ +// +// "$Id$" +// +// Fl_BMP_Image routines. +// +// Copyright 1997-2005 by Easy Software Products. +// Image support donated by Matthias Melcher, Copyright 2000. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +// Contents: +// +// Fl_BMP_Image::Fl_BMP_Image() - Load a BMP image file. +// + +// +// Include necessary header files... +// + +#include <FL/Fl_BMP_Image.H> +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" + +#include <stdio.h> +#include <stdlib.h> + + +// +// BMP definitions... +// + +#ifndef BI_RGB +# define BI_RGB 0 // No compression - straight BGR data +# define BI_RLE8 1 // 8-bit run-length compression +# define BI_RLE4 2 // 4-bit run-length compression +# define BI_BITFIELDS 3 // RGB bitmap with RGB masks +#endif // !BI_RGB + + +// +// Local functions... +// + +static int read_long(FILE *fp); +static unsigned short read_word(FILE *fp); +static unsigned int read_dword(FILE *fp); + + +// +// 'Fl_BMP_Image::Fl_BMP_Image()' - Load a BMP image file. +// + +Fl_BMP_Image::Fl_BMP_Image(const char *bmp) // I - File to read + : Fl_RGB_Image(0,0,0) { + FILE *fp; // File pointer + int info_size, // Size of info header + depth, // Depth of image (bits) + bDepth = 3, // Depth of image (bytes) + compression, // Type of compression + colors_used, // Number of colors used + x, y, // Looping vars + color, // Color of RLE pixel + repcount, // Number of times to repeat + temp, // Temporary color + align, // Alignment bytes + dataSize, // number of bytes in image data set + row_order, // 1 = normal; -1 = flipped row order + start_y, // Beginning Y + end_y; // Ending Y + long offbits; // Offset to image data + uchar bit, // Bit in image + byte; // Byte in image + uchar *ptr; // Pointer into pixels + uchar colormap[256][3];// Colormap + uchar havemask; // Single bit mask follows image data + int use_5_6_5; // Use 5:6:5 for R:G:B channels in 16 bit images + + + // Open the file... + if ((fp = fopen(bmp, "rb")) == NULL) return; + + // Get the header... + byte = (uchar)getc(fp); // Check "BM" sync chars + bit = (uchar)getc(fp); + if (byte != 'B' || bit != 'M') { + fclose(fp); + return; + } + + read_dword(fp); // Skip size + read_word(fp); // Skip reserved stuff + read_word(fp); + offbits = (long)read_dword(fp);// Read offset to image data + + // Then the bitmap information... + info_size = read_dword(fp); + +// printf("offbits = %ld, info_size = %d\n", offbits, info_size); + + havemask = 0; + row_order = -1; + use_5_6_5 = 0; + + if (info_size < 40) { + // Old Windows/OS2 BMP header... + w(read_word(fp)); + h(read_word(fp)); + read_word(fp); + depth = read_word(fp); + compression = BI_RGB; + colors_used = 0; + + repcount = info_size - 12; + } else { + // New BMP header... + w(read_long(fp)); + // If the height is negative, the row order is flipped + temp = read_long(fp); + if (temp < 0) row_order = 1; + h(abs(temp)); + read_word(fp); + depth = read_word(fp); + compression = read_dword(fp); + dataSize = read_dword(fp); + read_long(fp); + read_long(fp); + colors_used = read_dword(fp); + read_dword(fp); + + repcount = info_size - 40; + + if (!compression && depth>=8 && w()>32/depth) { + int Bpp = depth/8; + int maskSize = (((w()*Bpp+3)&~3)*h()) + (((((w()+7)/8)+3)&~3)*h()); + if (maskSize==2*dataSize) { + havemask = 1; + h(h()/2); + bDepth = 4; + } + } + } + +// printf("w() = %d, h() = %d, depth = %d, compression = %d, colors_used = %d, repcount = %d\n", +// w(), h(), depth, compression, colors_used, repcount); + + // Skip remaining header bytes... + while (repcount > 0) { + getc(fp); + repcount --; + } + + // Check header data... + if (!w() || !h() || !depth) { + fclose(fp); + return; + } + + // Get colormap... + if (colors_used == 0 && depth <= 8) + colors_used = 1 << depth; + + for (repcount = 0; repcount < colors_used; repcount ++) { + // Read BGR color... + fread(colormap[repcount], 1, 3, fp); + + // Skip pad byte for new BMP files... + if (info_size > 12) getc(fp); + } + + // Read first dword of colormap. It tells us if 5:5:5 or 5:6:5 for 16 bit + if (depth == 16) + use_5_6_5 = (read_dword(fp) == 0xf800); + + // Set byte depth for RGBA images + if (depth == 32) + bDepth=4; + + // Setup image and buffers... + d(bDepth); + if (offbits) fseek(fp, offbits, SEEK_SET); + + array = new uchar[w() * h() * d()]; + alloc_array = 1; + + // Read the image data... + color = 0; + repcount = 0; + align = 0; + byte = 0; + temp = 0; + + if (row_order < 0) { + start_y = h() - 1; + end_y = -1; + } else { + start_y = 0; + end_y = h(); + } + + for (y = start_y; y != end_y; y += row_order) { + ptr = (uchar *)array + y * w() * d(); + + switch (depth) + { + case 1 : // Bitmap + for (x = w(), bit = 128; x > 0; x --) { + if (bit == 128) byte = (uchar)getc(fp); + + if (byte & bit) { + *ptr++ = colormap[1][2]; + *ptr++ = colormap[1][1]; + *ptr++ = colormap[1][0]; + } else { + *ptr++ = colormap[0][2]; + *ptr++ = colormap[0][1]; + *ptr++ = colormap[0][0]; + } + + if (bit > 1) + bit >>= 1; + else + bit = 128; + } + + // Read remaining bytes to align to 32 bits... + for (temp = (w() + 7) / 8; temp & 3; temp ++) { + getc(fp); + } + break; + + case 4 : // 16-color + for (x = w(), bit = 0xf0; x > 0; x --) { + // Get a new repcount as needed... + if (repcount == 0) { + if (compression != BI_RLE4) { + repcount = 2; + color = -1; + } else { + while (align > 0) { + align --; + getc(fp); + } + + if ((repcount = getc(fp)) == 0) { + if ((repcount = getc(fp)) == 0) { + // End of line... + x ++; + continue; + } else if (repcount == 1) { + // End of image... + break; + } else if (repcount == 2) { + // Delta... + repcount = getc(fp) * getc(fp) * w(); + color = 0; + } else { + // Absolute... + color = -1; + align = ((4 - (repcount & 3)) / 2) & 1; + } + } else { + color = getc(fp); + } + } + } + + // Get a new color as needed... + repcount --; + + // Extract the next pixel... + if (bit == 0xf0) { + // Get the next color byte as needed... + if (color < 0) temp = getc(fp); + else temp = color; + + // Copy the color value... + *ptr++ = colormap[(temp >> 4) & 15][2]; + *ptr++ = colormap[(temp >> 4) & 15][1]; + *ptr++ = colormap[(temp >> 4) & 15][0]; + + bit = 0x0f; + } else { + bit = 0xf0; + + // Copy the color value... + *ptr++ = colormap[temp & 15][2]; + *ptr++ = colormap[temp & 15][1]; + *ptr++ = colormap[temp & 15][0]; + } + + } + + if (!compression) { + // Read remaining bytes to align to 32 bits... + for (temp = (w() + 1) / 2; temp & 3; temp ++) { + getc(fp); + } + } + break; + + case 8 : // 256-color + for (x = w(); x > 0; x --) { + // Get a new repcount as needed... + if (compression != BI_RLE8) { + repcount = 1; + color = -1; + } + + if (repcount == 0) { + while (align > 0) { + align --; + getc(fp); + } + + if ((repcount = getc(fp)) == 0) { + if ((repcount = getc(fp)) == 0) { + // End of line... + x ++; + continue; + } else if (repcount == 1) { + // End of image... + break; + } else if (repcount == 2) { + // Delta... + repcount = getc(fp) * getc(fp) * w(); + color = 0; + } else { + // Absolute... + color = -1; + align = (2 - (repcount & 1)) & 1; + } + } else { + color = getc(fp); + } + } + + // Get a new color as needed... + if (color < 0) temp = getc(fp); + else temp = color; + + repcount --; + + // Copy the color value... + *ptr++ = colormap[temp][2]; + *ptr++ = colormap[temp][1]; + *ptr++ = colormap[temp][0]; + if (havemask) ptr++; + } + + if (!compression) { + // Read remaining bytes to align to 32 bits... + for (temp = w(); temp & 3; temp ++) { + getc(fp); + } + } + break; + + case 16 : // 16-bit 5:5:5 or 5:6:5 RGB + for (x = w(); x > 0; x --, ptr += bDepth) { + uchar b = getc(fp), a = getc(fp) ; + if (use_5_6_5) { + ptr[2] = (uchar)(( b << 3 ) & 0xf8); + ptr[1] = (uchar)(((a << 5) & 0xe0) | ((b >> 3) & 0x1c)); + ptr[0] = (uchar)(a & 0xf8); + } else { + ptr[2] = (uchar)((b << 3) & 0xf8); + ptr[1] = (uchar)(((a << 6) & 0xc0) | ((b >> 2) & 0x38)); + ptr[0] = (uchar)((a<<1) & 0xf8); + } + } + + // Read remaining bytes to align to 32 bits... + for (temp = w() * 2; temp & 3; temp ++) { + getc(fp); + } + break; + + case 24 : // 24-bit RGB + for (x = w(); x > 0; x --, ptr += bDepth) { + ptr[2] = (uchar)getc(fp); + ptr[1] = (uchar)getc(fp); + ptr[0] = (uchar)getc(fp); + } + + // Read remaining bytes to align to 32 bits... + for (temp = w() * 3; temp & 3; temp ++) { + getc(fp); + } + break; + + case 32 : // 32-bit RGBA + for (x = w(); x > 0; x --, ptr += bDepth) { + ptr[2] = (uchar)getc(fp); + ptr[1] = (uchar)getc(fp); + ptr[0] = (uchar)getc(fp); + ptr[3] = (uchar)getc(fp); + } + break; + } + } + + if (havemask) { + for (y = h() - 1; y >= 0; y --) { + ptr = (uchar *)array + y * w() * d() + 3; + for (x = w(), bit = 128; x > 0; x --, ptr+=bDepth) { + if (bit == 128) byte = (uchar)getc(fp); + if (byte & bit) + *ptr = 0; + else + *ptr = 255; + if (bit > 1) + bit >>= 1; + else + bit = 128; + } + // Read remaining bytes to align to 32 bits... + for (temp = (w() + 7) / 8; temp & 3; temp ++) + getc(fp); + } + } + + // Close the file and return... + fclose(fp); +} + + +// +// 'read_word()' - Read a 16-bit unsigned integer. +// + +static unsigned short // O - 16-bit unsigned integer +read_word(FILE *fp) { // I - File to read from + unsigned char b0, b1; // Bytes from file + + b0 = (uchar)getc(fp); + b1 = (uchar)getc(fp); + + return ((b1 << 8) | b0); +} + + +// +// 'read_dword()' - Read a 32-bit unsigned integer. +// + +static unsigned int // O - 32-bit unsigned integer +read_dword(FILE *fp) { // I - File to read from + unsigned char b0, b1, b2, b3; // Bytes from file + + b0 = (uchar)getc(fp); + b1 = (uchar)getc(fp); + b2 = (uchar)getc(fp); + b3 = (uchar)getc(fp); + + return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0); +} + + +// +// 'read_long()' - Read a 32-bit signed integer. +// + +static int // O - 32-bit signed integer +read_long(FILE *fp) { // I - File to read from + unsigned char b0, b1, b2, b3; // Bytes from file + + b0 = (uchar)getc(fp); + b1 = (uchar)getc(fp); + b2 = (uchar)getc(fp); + b3 = (uchar)getc(fp); + + return ((int)(((((b3 << 8) | b2) << 8) | b1) << 8) | b0); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Bitmap.cxx b/Utilities/FLTK/src/Fl_Bitmap.cxx new file mode 100644 index 0000000000..46425e98d6 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Bitmap.cxx @@ -0,0 +1,518 @@ +// +// "$Id$" +// +// Bitmap drawing routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/x.H> +#include <FL/fl_draw.H> +#include <FL/Fl_Widget.H> +#include <FL/Fl_Menu_Item.H> +#include <FL/Fl_Bitmap.H> +#include "flstring.h" + +#ifdef __APPLE_QD__ // MacOS bitmask functions +Fl_Bitmask fl_create_bitmask(int w, int h, const uchar *array) { + Rect srcRect; + srcRect.left = 0; srcRect.right = w; + srcRect.top = 0; srcRect.bottom = h; + GrafPtr savePort; + + GetPort(&savePort); // remember the current port + + Fl_Bitmask gw; + NewGWorld( &gw, 1, &srcRect, 0L, 0L, 0 ); + PixMapHandle pm = GetGWorldPixMap( gw ); + if ( pm ) + { + LockPixels( pm ); + if ( *pm ) + { + uchar *base = (uchar*)GetPixBaseAddr( pm ); + if ( base ) + { + PixMapPtr pmp = *pm; + // verify the parameters for direct memory write + if ( pmp->pixelType == 0 || pmp->pixelSize == 1 || pmp->cmpCount == 1 || pmp->cmpSize == 1 ) + { + static uchar reverse[16] = /* Bit reversal lookup table */ + { 0x00, 0x88, 0x44, 0xcc, 0x22, 0xaa, 0x66, 0xee, 0x11, 0x99, 0x55, 0xdd, 0x33, 0xbb, 0x77, 0xff }; + uchar *dst = base; + const uchar *src = array; + int rowBytesSrc = (w+7)>>3 ; + int rowPatch = (pmp->rowBytes&0x3fff) - rowBytesSrc; + for ( int j=0; j<h; j++,dst+=rowPatch ) + for ( int i=0; i<rowBytesSrc; i++,src++ ) + *dst++ = (reverse[*src & 0x0f] & 0xf0) | (reverse[(*src >> 4) & 0x0f] & 0x0f); + } + } + UnlockPixels( pm ); + } + } + + SetPort(savePort); + return gw; /* tell caller we succeeded! */ +} + +void fl_delete_bitmask(Fl_Bitmask id) { + if (id) DisposeGWorld(id); +} +#elif defined(__APPLE_QUARTZ__) +Fl_Bitmask fl_create_bitmask(int w, int h, const uchar *array) { + static uchar reverse[16] = /* Bit reversal lookup table */ + { 0x00, 0x88, 0x44, 0xcc, 0x22, 0xaa, 0x66, 0xee, + 0x11, 0x99, 0x55, 0xdd, 0x33, 0xbb, 0x77, 0xff }; + int rowBytes = (w+7)>>3 ; + uchar *bmask = (uchar*)malloc(rowBytes*h), *dst = bmask; + const uchar *src = array; + for ( int i=rowBytes*h; i>0; i--,src++ ) { + *dst++ = ((reverse[*src & 0x0f] & 0xf0) | (reverse[(*src >> 4) & 0x0f] & 0x0f))^0xff; + } + CGDataProviderRef srcp = CGDataProviderCreateWithData( 0L, bmask, rowBytes*h, 0L); + CGImageRef id = CGImageMaskCreate( w, h, 1, 1, rowBytes, srcp, 0L, false); + CGDataProviderRelease(srcp); + return (Fl_Bitmask)id; +} +void fl_delete_bitmask(Fl_Bitmask id) { + if (id) CGImageRelease((CGImageRef)id); +} +#elif defined(WIN32) // Windows bitmask functions... +// 'fl_create_bitmap()' - Create a 1-bit bitmap for drawing... +static Fl_Bitmask fl_create_bitmap(int w, int h, const uchar *data) { + // we need to pad the lines out to words & swap the bits + // in each byte. + int w1 = (w+7)/8; + int w2 = ((w+15)/16)*2; + uchar* newarray = new uchar[w2*h]; + const uchar* src = data; + uchar* dest = newarray; + Fl_Bitmask id; + static uchar reverse[16] = /* Bit reversal lookup table */ + { 0x00, 0x88, 0x44, 0xcc, 0x22, 0xaa, 0x66, 0xee, + 0x11, 0x99, 0x55, 0xdd, 0x33, 0xbb, 0x77, 0xff }; + + for (int y=0; y < h; y++) { + for (int n = 0; n < w1; n++, src++) + *dest++ = (uchar)((reverse[*src & 0x0f] & 0xf0) | + (reverse[(*src >> 4) & 0x0f] & 0x0f)); + dest += w2-w1; + } + + id = CreateBitmap(w, h, 1, 1, newarray); + + delete[] newarray; + + return id; +} + +// 'fl_create_bitmask()' - Create an N-bit bitmap for masking... +Fl_Bitmask fl_create_bitmask(int w, int h, const uchar *data) { + // this won't work when the user changes display mode during run or + // has two screens with differnet depths + Fl_Bitmask id; + static uchar hiNibble[16] = + { 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0 }; + static uchar loNibble[16] = + { 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e, + 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f }; + int np = GetDeviceCaps(fl_gc, PLANES); //: was always one on sample machines + int bpp = GetDeviceCaps(fl_gc, BITSPIXEL);//: 1,4,8,16,24,32 and more odd stuff? + int Bpr = (bpp*w+7)/8; //: bytes per row + int pad = Bpr&1, w1 = (w+7)/8, shr = ((w-1)&7)+1; + if (bpp==4) shr = (shr+1)/2; + uchar *newarray = new uchar[(Bpr+pad)*h]; + uchar *dst = newarray; + const uchar *src = data; + + for (int i=0; i<h; i++) { + // This is slooow, but we do it only once per pixmap + for (int j=w1; j>0; j--) { + uchar b = *src++; + if (bpp==1) { + *dst++ = (uchar)( hiNibble[b&15] ) | ( loNibble[(b>>4)&15] ); + } else if (bpp==4) { + for (int k=(j==1)?shr:4; k>0; k--) { + *dst++ = (uchar)("\377\360\017\000"[b&3]); + b = b >> 2; + } + } else { + for (int k=(j==1)?shr:8; k>0; k--) { + if (b&1) { + *dst++=0; + if (bpp>8) *dst++=0; + if (bpp>16) *dst++=0; + if (bpp>24) *dst++=0; + } else { + *dst++=0xff; + if (bpp>8) *dst++=0xff; + if (bpp>16) *dst++=0xff; + if (bpp>24) *dst++=0xff; + } + + b = b >> 1; + } + } + } + + dst += pad; + } + + id = CreateBitmap(w, h, np, bpp, newarray); + delete[] newarray; + + return id; +} + +#if 0 // This doesn't appear to be used anywhere... +Fl_Bitmask fl_create_bitmask(int w, int h, const uchar *data, int for_mask) { + // we need to pad the lines out to words & swap the bits + // in each byte. + int w1 = (w+7)/8; + int w2 = ((w+15)/16)*2; + uchar* newarray = new uchar[w2*h]; + const uchar* src = data; + uchar* dest = newarray; + Fl_Bitmask id; + static uchar reverse[16] = /* Bit reversal lookup table */ + { 0x00, 0x88, 0x44, 0xcc, 0x22, 0xaa, 0x66, 0xee, + 0x11, 0x99, 0x55, 0xdd, 0x33, 0xbb, 0x77, 0xff }; + + for (int y=0; y < h; y++) { + for (int n = 0; n < w1; n++, src++) + *dest++ = (reverse[*src & 0x0f] & 0xf0) | + (reverse[(*src >> 4) & 0x0f] & 0x0f); + dest += w2-w1; + } + + id = CreateBitmap(w, h, 1, 1, newarray); + + delete[] newarray; + + return (id); +} +# endif // 0 + +void fl_delete_bitmask(Fl_Bitmask bm) { + DeleteObject((HGDIOBJ)bm); +} +#else // X11 bitmask functions +Fl_Bitmask fl_create_bitmask(int w, int h, const uchar *data) { + return XCreateBitmapFromData(fl_display, fl_window, (const char *)data, + (w+7)&-8, h); +} + +void fl_delete_bitmask(Fl_Bitmask bm) { + fl_delete_offscreen((Fl_Offscreen)bm); +} +#endif // __APPLE__ + + +// MRS: Currently it appears that CopyDeepMask() does not work with an 8-bit alpha mask. +// If you want to test/fix this, uncomment the "#ifdef __APPLE__" and comment out +// the "#if 0" here. Also see Fl_Image.cxx for a similar check... + +//#ifdef __APPLE_QD__ +#if 0 +// Create an 8-bit mask used for alpha blending +Fl_Bitmask fl_create_alphamask(int w, int h, int d, int ld, const uchar *array) { + Rect srcRect; + srcRect.left = 0; srcRect.right = w; + srcRect.top = 0; srcRect.bottom = h; + GrafPtr savePort; + + GetPort(&savePort); // remember the current port + + Fl_Bitmask gw; + NewGWorld( &gw, 8, &srcRect, 0L, 0L, 0 ); + PixMapHandle pm = GetGWorldPixMap( gw ); + if ( pm ) + { + LockPixels( pm ); + if ( *pm ) + { + uchar *base = (uchar*)GetPixBaseAddr( pm ); + if ( base ) + { + PixMapPtr pmp = *pm; + // verify the parameters for direct memory write + if ( pmp->pixelType == 0 || pmp->pixelSize == 8 || pmp->cmpCount == 1 || pmp->cmpSize == 8 ) + { + // Copy alpha values from the source array to the pixmap... + array += d - 1; + int rowoffset = (pmp->rowBytes & 0x3fff) - w; + for (int y = h; y > 0; y --, array += ld, base += rowoffset) { + for (int x = w; x > 0; x --, array += d) { + *base++ = 255 /*255 - *array*/; + } + } + } + } + UnlockPixels( pm ); + } + } + + SetPort(savePort); + return gw; /* tell caller we succeeded! */ +} +#else +// Create a 1-bit mask used for alpha blending +Fl_Bitmask fl_create_alphamask(int w, int h, int d, int ld, const uchar *array) { + Fl_Bitmask mask; + int bmw = (w + 7) / 8; + uchar *bitmap = new uchar[bmw * h]; + uchar *bitptr, bit; + const uchar *dataptr; + int x, y; + static uchar dither[16][16] = { // Simple 16x16 Floyd dither + { 0, 128, 32, 160, 8, 136, 40, 168, + 2, 130, 34, 162, 10, 138, 42, 170 }, + { 192, 64, 224, 96, 200, 72, 232, 104, + 194, 66, 226, 98, 202, 74, 234, 106 }, + { 48, 176, 16, 144, 56, 184, 24, 152, + 50, 178, 18, 146, 58, 186, 26, 154 }, + { 240, 112, 208, 80, 248, 120, 216, 88, + 242, 114, 210, 82, 250, 122, 218, 90 }, + { 12, 140, 44, 172, 4, 132, 36, 164, + 14, 142, 46, 174, 6, 134, 38, 166 }, + { 204, 76, 236, 108, 196, 68, 228, 100, + 206, 78, 238, 110, 198, 70, 230, 102 }, + { 60, 188, 28, 156, 52, 180, 20, 148, + 62, 190, 30, 158, 54, 182, 22, 150 }, + { 252, 124, 220, 92, 244, 116, 212, 84, + 254, 126, 222, 94, 246, 118, 214, 86 }, + { 3, 131, 35, 163, 11, 139, 43, 171, + 1, 129, 33, 161, 9, 137, 41, 169 }, + { 195, 67, 227, 99, 203, 75, 235, 107, + 193, 65, 225, 97, 201, 73, 233, 105 }, + { 51, 179, 19, 147, 59, 187, 27, 155, + 49, 177, 17, 145, 57, 185, 25, 153 }, + { 243, 115, 211, 83, 251, 123, 219, 91, + 241, 113, 209, 81, 249, 121, 217, 89 }, + { 15, 143, 47, 175, 7, 135, 39, 167, + 13, 141, 45, 173, 5, 133, 37, 165 }, + { 207, 79, 239, 111, 199, 71, 231, 103, + 205, 77, 237, 109, 197, 69, 229, 101 }, + { 63, 191, 31, 159, 55, 183, 23, 151, + 61, 189, 29, 157, 53, 181, 21, 149 }, + { 254, 127, 223, 95, 247, 119, 215, 87, + 253, 125, 221, 93, 245, 117, 213, 85 } + }; + + // Generate a 1-bit "screen door" alpha mask; not always pretty, but + // definitely fast... In the future we may be able to support things + // like the RENDER extension in XFree86, when available, to provide + // true RGBA-blended rendering. See: + // + // http://www.xfree86.org/~keithp/render/protocol.html + // + // for more info on XRender... + // + // MacOS already provides alpha blending support and has its own + // fl_create_alphamask() function... + memset(bitmap, 0, bmw * h); + + for (dataptr = array + d - 1, y = 0; y < h; y ++, dataptr += ld) + for (bitptr = bitmap + y * bmw, bit = 1, x = 0; x < w; x ++, dataptr += d) { + if (*dataptr > dither[x & 15][y & 15]) + *bitptr |= bit; + if (bit < 128) bit <<= 1; + else { + bit = 1; + bitptr ++; + } + } + + mask = fl_create_bitmask(w, h, bitmap); + delete[] bitmap; + + return (mask); +} +#endif // __APPLE__ + +void Fl_Bitmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) { + if (!array) { + draw_empty(XP, YP); + return; + } + + // account for current clip region (faster on Irix): + int X,Y,W,H; fl_clip_box(XP,YP,WP,HP,X,Y,W,H); + cx += X-XP; cy += Y-YP; + // clip the box down to the size of image, quit if empty: + if (cx < 0) {W += cx; X -= cx; cx = 0;} + if ((cx+W) > w()) W = w()-cx; + if (W <= 0) return; + if (cy < 0) {H += cy; Y -= cy; cy = 0;} + if ((cy+H) > h()) H = h()-cy; + if (H <= 0) return; +#ifdef WIN32 + if (!id) id = fl_create_bitmap(w(), h(), array); + + HDC tempdc = CreateCompatibleDC(fl_gc); + int save = SaveDC(tempdc); + SelectObject(tempdc, (HGDIOBJ)id); + SelectObject(fl_gc, fl_brush()); + // secret bitblt code found in old MSWindows reference manual: + BitBlt(fl_gc, X, Y, W, H, tempdc, cx, cy, 0xE20746L); + RestoreDC(tempdc, save); + DeleteDC(tempdc); +#elif defined(__APPLE_QD__) + if (!id) id = fl_create_bitmask(w(), h(), array); + GrafPtr dstPort; + GetPort( &dstPort ); + Rect src, dst; + GetPortBounds( (Fl_Offscreen)id, &src ); + SetRect( &src, cx, cy, cx+W, cy+H ); + SetRect( &dst, X, Y, X+W, Y+H ); + CopyBits(GetPortBitMapForCopyBits((Fl_Offscreen)id), // srcBits + GetPortBitMapForCopyBits(dstPort), // dstBits + &src, // src bounds + &dst, // dst bounds + srcOr, // mode + 0L); // mask region +#elif defined(__APPLE_QUARTZ__) + if (!id) id = fl_create_bitmask(w(), h(), array); + if (id && fl_gc) { + CGRect rect = { X, Y, W, H }; + Fl_X::q_begin_image(rect, cx, cy, w(), h()); + CGContextDrawImage(fl_gc, rect, (CGImageRef)id); + Fl_X::q_end_image(); + } +#else + if (!id) id = fl_create_bitmask(w(), h(), array); + + XSetStipple(fl_display, fl_gc, id); + int ox = X-cx; if (ox < 0) ox += w(); + int oy = Y-cy; if (oy < 0) oy += h(); + XSetTSOrigin(fl_display, fl_gc, ox, oy); + XSetFillStyle(fl_display, fl_gc, FillStippled); + XFillRectangle(fl_display, fl_window, fl_gc, X, Y, W, H); + XSetFillStyle(fl_display, fl_gc, FillSolid); +#endif +} + +Fl_Bitmap::~Fl_Bitmap() { + uncache(); + if (alloc_array) delete[] (uchar *)array; +} + +void Fl_Bitmap::uncache() { + if (id) { + fl_delete_bitmask((Fl_Offscreen)id); + id = 0; + } +} + +void Fl_Bitmap::label(Fl_Widget* widget) { + widget->image(this); +} + +void Fl_Bitmap::label(Fl_Menu_Item* m) { + Fl::set_labeltype(_FL_IMAGE_LABEL, labeltype, measure); + m->label(_FL_IMAGE_LABEL, (const char*)this); +} + +Fl_Image *Fl_Bitmap::copy(int W, int H) { + Fl_Bitmap *new_image; // New RGB image + uchar *new_array; // New array for image data + + // Optimize the simple copy where the width and height are the same... + if (W == w() && H == h()) { + new_array = new uchar [H * ((W + 7) / 8)]; + memcpy(new_array, array, H * ((W + 7) / 8)); + + new_image = new Fl_Bitmap(new_array, W, H); + new_image->alloc_array = 1; + + return new_image; + } + if (W <= 0 || H <= 0) return 0; + + // OK, need to resize the image data; allocate memory and + uchar *new_ptr, // Pointer into new array + new_bit, // Bit for new array + old_bit; // Bit for old array + const uchar *old_ptr; // Pointer into old array + int sx, sy, // Source coordinates + dx, dy, // Destination coordinates + xerr, yerr, // X & Y errors + xmod, ymod, // X & Y moduli + xstep, ystep; // X & Y step increments + + + // Figure out Bresenheim step/modulus values... + xmod = w() % W; + xstep = w() / W; + ymod = h() % H; + ystep = h() / H; + + // Allocate memory for the new image... + new_array = new uchar [H * ((W + 7) / 8)]; + new_image = new Fl_Bitmap(new_array, W, H); + new_image->alloc_array = 1; + + memset(new_array, 0, H * ((W + 7) / 8)); + + // Scale the image using a nearest-neighbor algorithm... + for (dy = H, sy = 0, yerr = H, new_ptr = new_array; dy > 0; dy --) { + for (dx = W, xerr = W, old_ptr = array + sy * ((w() + 7) / 8), sx = 0, new_bit = 1; + dx > 0; + dx --) { + old_bit = (uchar)(1 << (sx & 7)); + if (old_ptr[sx / 8] & old_bit) *new_ptr |= new_bit; + + if (new_bit < 128) new_bit <<= 1; + else { + new_bit = 1; + new_ptr ++; + } + + sx += xstep; + xerr -= xmod; + + if (xerr <= 0) { + xerr += W; + sx ++; + } + } + + if (new_bit > 1) new_ptr ++; + + sy += ystep; + yerr -= ymod; + if (yerr <= 0) { + yerr += H; + sy ++; + } + } + + return new_image; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Box.cxx b/Utilities/FLTK/src/Fl_Box.cxx new file mode 100644 index 0000000000..b8107e9f83 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Box.cxx @@ -0,0 +1,44 @@ +// +// "$Id$" +// +// Box widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl_Widget.H> +#include <FL/Fl_Box.H> + +void Fl_Box::draw() { + draw_box(); + draw_label(); +} + +int Fl_Box::handle(int event) { + if (event == FL_ENTER || event == FL_LEAVE) return 1; + else return 0; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Browser.cxx b/Utilities/FLTK/src/Fl_Browser.cxx new file mode 100644 index 0000000000..96f2dfe05d --- /dev/null +++ b/Utilities/FLTK/src/Fl_Browser.cxx @@ -0,0 +1,551 @@ +// +// "$Id$" +// +// Browser widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Browser.H> +#include <FL/fl_draw.H> +#include "flstring.h" +#include <stdlib.h> +#include <math.h> + +// I modified this from the original Forms data to use a linked list +// so that the number of items in the browser and size of those items +// is unlimited. The only problem is that the old browser used an +// index number to identify a line, and it is slow to convert from/to +// a pointer. I use a cache of the last match to try to speed this +// up. + +// Also added the ability to "hide" a line. This set's it's height to +// zero, so the Fl_Browser_ cannot pick it. + +#define SELECTED 1 +#define NOTDISPLAYED 2 + +struct FL_BLINE { // data is in a linked list of these + FL_BLINE* prev; + FL_BLINE* next; + void* data; + short length; // sizeof(txt)-1, may be longer than string + char flags; // selected, displayed + char txt[1]; // start of allocated array +}; + +void* Fl_Browser::item_first() const {return first;} + +void* Fl_Browser::item_next(void* l) const {return ((FL_BLINE*)l)->next;} + +void* Fl_Browser::item_prev(void* l) const {return ((FL_BLINE*)l)->prev;} + +int Fl_Browser::item_selected(void* l) const { + return ((FL_BLINE*)l)->flags&SELECTED;} + +void Fl_Browser::item_select(void* l, int v) { + if (v) ((FL_BLINE*)l)->flags |= SELECTED; + else ((FL_BLINE*)l)->flags &= ~SELECTED; +} + +FL_BLINE* Fl_Browser::find_line(int line) const { + int n; FL_BLINE* l; + if (line == cacheline) return cache; + if (cacheline && line > (cacheline/2) && line < ((cacheline+lines)/2)) { + n = cacheline; l = cache; + } else if (line <= (lines/2)) { + n = 1; l = first; + } else { + n = lines; l = last; + } + for (; n < line && l; n++) l = l->next; + for (; n > line && l; n--) l = l->prev; + ((Fl_Browser*)this)->cacheline = line; + ((Fl_Browser*)this)->cache = l; + return l; +} + +int Fl_Browser::lineno(void* v) const { + FL_BLINE* l = (FL_BLINE*)v; + if (!l) return 0; + if (l == cache) return cacheline; + if (l == first) return 1; + if (l == last) return lines; + if (!cache) { + ((Fl_Browser*)this)->cache = first; + ((Fl_Browser*)this)->cacheline = 1; + } + // assumme it is near cache, search both directions: + FL_BLINE* b = cache->prev; + int bnum = cacheline-1; + FL_BLINE* f = cache->next; + int fnum = cacheline+1; + int n = 0; + for (;;) { + if (b == l) {n = bnum; break;} + if (f == l) {n = fnum; break;} + if (b) {b = b->prev; bnum--;} + if (f) {f = f->next; fnum++;} + } + ((Fl_Browser*)this)->cache = l; + ((Fl_Browser*)this)->cacheline = n; + return n; +} + +FL_BLINE* Fl_Browser::_remove(int line) { + FL_BLINE* ttt = find_line(line); + deleting(ttt); + + cacheline = line-1; + cache = ttt->prev; + lines--; + full_height_ -= item_height(ttt); + if (ttt->prev) ttt->prev->next = ttt->next; + else first = ttt->next; + if (ttt->next) ttt->next->prev = ttt->prev; + else last = ttt->prev; + + return(ttt); +} + +void Fl_Browser::remove(int line) { + if (line < 1 || line > lines) return; + free(_remove(line)); +} + +void Fl_Browser::insert(int line, FL_BLINE* t) { + if (!first) { + t->prev = t->next = 0; + first = last = t; + } else if (line <= 1) { + inserting(first, t); + t->prev = 0; + t->next = first; + t->next->prev = t; + first = t; + } else if (line > lines) { + t->prev = last; + t->prev->next = t; + t->next = 0; + last = t; + } else { + FL_BLINE* n = find_line(line); + inserting(n, t); + t->next = n; + t->prev = n->prev; + t->prev->next = t; + n->prev = t; + } + cacheline = line; + cache = t; + lines++; + full_height_ += item_height(t); + redraw_line(t); +} + +void Fl_Browser::insert(int line, const char* newtext, void* d) { + int l = strlen(newtext); + FL_BLINE* t = (FL_BLINE*)malloc(sizeof(FL_BLINE)+l); + t->length = (short)l; + t->flags = 0; + strcpy(t->txt, newtext); + t->data = d; + insert(line, t); +} + +void Fl_Browser::move(int to, int from) { + if (from < 1 || from > lines) return; + insert(to, _remove(from)); +} + +void Fl_Browser::text(int line, const char* newtext) { + if (line < 1 || line > lines) return; + FL_BLINE* t = find_line(line); + int l = strlen(newtext); + if (l > t->length) { + FL_BLINE* n = (FL_BLINE*)malloc(sizeof(FL_BLINE)+l); + replacing(t, n); + cache = n; + n->data = t->data; + n->length = (short)l; + n->flags = t->flags; + n->prev = t->prev; + if (n->prev) n->prev->next = n; else first = n; + n->next = t->next; + if (n->next) n->next->prev = n; else last = n; + free(t); + t = n; + } + strcpy(t->txt, newtext); + redraw_line(t); +} + +void Fl_Browser::data(int line, void* d) { + if (line < 1 || line > lines) return; + find_line(line)->data = d; +} + +int Fl_Browser::item_height(void* lv) const { + FL_BLINE* l = (FL_BLINE*)lv; + if (l->flags & NOTDISPLAYED) return 0; + + int hmax = 2; // use 2 to insure we don't return a zero! + + if (!l->txt[0]) { + // For blank lines set the height to exactly 1 line! + fl_font(textfont(), textsize()); + int hh = fl_height(); + if (hh > hmax) hmax = hh; + } + else { + const int* i = column_widths(); + // do each column separately as they may all set different fonts: + for (char* str = l->txt; str && *str; str++) { + Fl_Font font = textfont(); // default font + int tsize = textsize(); // default size + while (*str==format_char()) { + str++; + switch (*str++) { + case 'l': case 'L': tsize = 24; break; + case 'm': case 'M': tsize = 18; break; + case 's': tsize = 11; break; + case 'b': font = (Fl_Font)(font|FL_BOLD); break; + case 'i': font = (Fl_Font)(font|FL_ITALIC); break; + case 'f': case 't': font = FL_COURIER; break; + case 'B': + case 'C': strtol(str, &str, 10); break;// skip a color number + case 'F': font = (Fl_Font)strtol(str,&str,10); break; + case 'S': tsize = strtol(str,&str,10); break; + case 0: case '@': str--; + case '.': goto END_FORMAT; + } + } + END_FORMAT: + char* ptr = str; + if (ptr && *i++) str = strchr(str, column_char()); + else str = NULL; + if((!str && *ptr) || (str && ptr < str)) { + fl_font(font, tsize); int hh = fl_height(); + if (hh > hmax) hmax = hh; + } + if (!str || !*str) break; + } + } + + return hmax; // previous version returned hmax+2! +} + +int Fl_Browser::item_width(void* v) const { + char* str = ((FL_BLINE*)v)->txt; + const int* i = column_widths(); + int ww = 0; + + while (*i) { // add up all tab-seperated fields + char* e; + e = strchr(str, column_char()); + if (!e) break; // last one occupied by text + str = e+1; + ww += *i++; + } + + // OK, we gotta parse the string and find the string width... + int tsize = textsize(); + Fl_Font font = textfont(); + int done = 0; + + while (*str == format_char_ && str[1] && str[1] != format_char_) { + str ++; + switch (*str++) { + case 'l': case 'L': tsize = 24; break; + case 'm': case 'M': tsize = 18; break; + case 's': tsize = 11; break; + case 'b': font = (Fl_Font)(font|FL_BOLD); break; + case 'i': font = (Fl_Font)(font|FL_ITALIC); break; + case 'f': case 't': font = FL_COURIER; break; + case 'B': + case 'C': strtol(str, &str, 10); break;// skip a color number + case 'F': font = (Fl_Font)strtol(str, &str, 10); break; + case 'S': tsize = strtol(str, &str, 10); break; + case '.': + done = 1; + break; + case '@': + str--; + done = 1; + } + + if (done) + break; + } + + if (*str == format_char_ && str[1]) + str ++; + + fl_font(font, tsize); + return ww + int(fl_width(str)) + 6; +} + +int Fl_Browser::full_height() const { + return full_height_; +} + +int Fl_Browser::incr_height() const { + return textsize()+2; +} + +void Fl_Browser::item_draw(void* v, int X, int Y, int W, int H) const { + char* str = ((FL_BLINE*)v)->txt; + const int* i = column_widths(); + + while (W > 6) { // do each tab-seperated field + int w1 = W; // width for this field + char* e = 0; // pointer to end of field or null if none + if (*i) { // find end of field and temporarily replace with 0 + e = strchr(str, column_char()); + if (e) {*e = 0; w1 = *i++;} + } + int tsize = textsize(); + Fl_Font font = textfont(); + Fl_Color lcol = textcolor(); + Fl_Align talign = FL_ALIGN_LEFT; + // check for all the @-lines recognized by XForms: + while (*str == format_char() && *++str && *str != format_char()) { + switch (*str++) { + case 'l': case 'L': tsize = 24; break; + case 'm': case 'M': tsize = 18; break; + case 's': tsize = 11; break; + case 'b': font = (Fl_Font)(font|FL_BOLD); break; + case 'i': font = (Fl_Font)(font|FL_ITALIC); break; + case 'f': case 't': font = FL_COURIER; break; + case 'c': talign = FL_ALIGN_CENTER; break; + case 'r': talign = FL_ALIGN_RIGHT; break; + case 'B': + if (!(((FL_BLINE*)v)->flags & SELECTED)) { + fl_color((Fl_Color)strtol(str, &str, 10)); + fl_rectf(X, Y, w1, H); + } else strtol(str, &str, 10); + break; + case 'C': + lcol = (Fl_Color)strtol(str, &str, 10); + break; + case 'F': + font = (Fl_Font)strtol(str, &str, 10); + break; + case 'N': + lcol = FL_INACTIVE_COLOR; + break; + case 'S': + tsize = strtol(str, &str, 10); + break; + case '-': + fl_color(FL_DARK3); + fl_line(X+3, Y+H/2, X+w1-3, Y+H/2); + fl_color(FL_LIGHT3); + fl_line(X+3, Y+H/2+1, X+w1-3, Y+H/2+1); + break; + case 'u': + case '_': + fl_color(lcol); + fl_line(X+3, Y+H-1, X+w1-3, Y+H-1); + break; + case '.': + goto BREAK; + case '@': + str--; goto BREAK; + } + } + BREAK: + fl_font(font, tsize); + if (((FL_BLINE*)v)->flags & SELECTED) + lcol = fl_contrast(lcol, selection_color()); + if (!active_r()) lcol = fl_inactive(lcol); + fl_color(lcol); + fl_draw(str, X+3, Y, w1-6, H, e ? Fl_Align(talign|FL_ALIGN_CLIP) : talign, 0, 0); + if (!e) break; // no more fields... + *e = column_char(); // put the seperator back + X += w1; + W -= w1; + str = e+1; + } +} + +static const int no_columns[1] = {0}; + +Fl_Browser::Fl_Browser(int X, int Y, int W, int H, const char*l) + : Fl_Browser_(X, Y, W, H, l) { + column_widths_ = no_columns; + lines = 0; + full_height_ = 0; + cacheline = 0; + format_char_ = '@'; + column_char_ = '\t'; + first = last = cache = 0; +} + +void Fl_Browser::lineposition(int line, Fl_Line_Position pos) { + if (line<1) line = 1; + if (line>lines) line = lines; + int p = 0; + + FL_BLINE* l; + for (l=first; l && line>1; l = l->next) { + line--; p += item_height(l); + } + if (l && (pos == BOTTOM)) p += item_height (l); + + int final = p, X, Y, W, H; + bbox(X, Y, W, H); + + switch(pos) { + case TOP: break; + case BOTTOM: final -= H; break; + case MIDDLE: final -= H/2; break; + } + + if (final > (full_height() - H)) final = full_height() -H; + position(final); +} + +int Fl_Browser::topline() const { + return lineno(top()); +} + +void Fl_Browser::clear() { + for (FL_BLINE* l = first; l;) { + FL_BLINE* n = l->next; + free(l); + l = n; + } + full_height_ = 0; + first = 0; + lines = 0; + new_list(); +} + +void Fl_Browser::add(const char* newtext, void* d) { + insert(lines+1, newtext, d); + //Fl_Browser_::display(last); +} + +const char* Fl_Browser::text(int line) const { + if (line < 1 || line > lines) return 0; + return find_line(line)->txt; +} + +void* Fl_Browser::data(int line) const { + if (line < 1 || line > lines) return 0; + return find_line(line)->data; +} + +int Fl_Browser::select(int line, int v) { + if (line < 1 || line > lines) return 0; + return Fl_Browser_::select(find_line(line), v); +} + +int Fl_Browser::selected(int line) const { + if (line < 1 || line > lines) return 0; + return find_line(line)->flags & SELECTED; +} + +void Fl_Browser::show(int line) { + FL_BLINE* t = find_line(line); + if (t->flags & NOTDISPLAYED) { + t->flags &= ~NOTDISPLAYED; + full_height_ += item_height(t); + if (Fl_Browser_::displayed(t)) redraw_lines(); + } +} + +void Fl_Browser::hide(int line) { + FL_BLINE* t = find_line(line); + if (!(t->flags & NOTDISPLAYED)) { + full_height_ -= item_height(t); + t->flags |= NOTDISPLAYED; + if (Fl_Browser_::displayed(t)) redraw_lines(); + } +} + +void Fl_Browser::display(int line, int v) { + if (line < 1 || line > lines) return; + if (v) show(line); else hide(line); +} + +int Fl_Browser::visible(int line) const { + if (line < 1 || line > lines) return 0; + return !(find_line(line)->flags&NOTDISPLAYED); +} + +int Fl_Browser::value() const { + return lineno(selection()); +} + +// SWAP TWO LINES +void Fl_Browser::swap(FL_BLINE *a, FL_BLINE *b) { + + if ( a == b || !a || !b) return; // nothing to do + FL_BLINE *aprev = a->prev; + FL_BLINE *anext = a->next; + FL_BLINE *bprev = b->prev; + FL_BLINE *bnext = b->next; + if ( b->prev == a ) { // A ADJACENT TO B + if ( aprev ) aprev->next = b; else first = b; + b->next = a; + a->next = bnext; + b->prev = aprev; + a->prev = b; + if ( bnext ) bnext->prev = a; else last = a; + } else if ( a->prev == b ) { // B ADJACENT TO A + if ( bprev ) bprev->next = a; else first = a; + a->next = b; + b->next = anext; + a->prev = bprev; + b->prev = a; + if ( anext ) anext->prev = b; else last = b; + } else { // A AND B NOT ADJACENT + // handle prev's + b->prev = aprev; + if ( anext ) anext->prev = b; else last = b; + a->prev = bprev; + if ( bnext ) bnext->prev = a; else last = a; + // handle next's + if ( aprev ) aprev->next = b; else first = b; + b->next = anext; + if ( bprev ) bprev->next = a; else first = a; + a->next = bnext; + } + // Disable cache -- we played around with positions + cacheline = 0; + // Redraw modified lines + redraw_lines(); +} + +void Fl_Browser::swap(int ai, int bi) { + if (ai < 1 || ai > lines || bi < 1 || bi > lines) return; + FL_BLINE* a = find_line(ai); + FL_BLINE* b = find_line(bi); + swap(a,b); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Browser_.cxx b/Utilities/FLTK/src/Fl_Browser_.cxx new file mode 100644 index 0000000000..8f51318fe3 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Browser_.cxx @@ -0,0 +1,807 @@ +// +// "$Id$" +// +// Base Browser widget class for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#define DISPLAY_SEARCH_BOTH_WAYS_AT_ONCE + +#include <stdio.h> +#include <FL/Fl.H> +#include <FL/Fl_Widget.H> +#include <FL/Fl_Browser_.H> +#include <FL/fl_draw.H> + + +// This is the base class for browsers. To be useful it must be +// subclassed and several virtual functions defined. The +// Forms-compatable browser and the file chooser's browser are +// subclassed off of this. + +// Yes, I know this should be a template... + +// This has been designed so that the subclass has complete control +// over the storage of the data, although because next() and prev() +// functions are used to index, it works best as a linked list or as a +// large block of characters in which the line breaks must be searched +// for. + +// A great deal of work has been done so that the "height" of a data +// object does not need to be determined until it is drawn. This was +// done for the file chooser, because the height requires doing stat() +// to see if the file is a directory, which can be annoyingly slow +// over the network. + +/* redraw bits: + 1 = redraw children (the scrollbar) + 2 = redraw one or two items + 4 = redraw all items +*/ + +static void scrollbar_callback(Fl_Widget* s, void*) { + ((Fl_Browser_*)(s->parent()))->position(int(((Fl_Scrollbar*)s)->value())); +} + +static void hscrollbar_callback(Fl_Widget* s, void*) { + ((Fl_Browser_*)(s->parent()))->hposition(int(((Fl_Scrollbar*)s)->value())); +} + +int Fl_Browser_::scrollbar_width_ = 16; + +// return where to draw the actual box: +void Fl_Browser_::bbox(int& X, int& Y, int& W, int& H) const { + Fl_Boxtype b = box() ? box() : FL_DOWN_BOX; + X = x()+Fl::box_dx(b); + Y = y()+Fl::box_dy(b); + W = w()-Fl::box_dw(b); + H = h()-Fl::box_dh(b); + if (scrollbar.visible()) { + W -= scrollbar_width_; + if (scrollbar.align() & FL_ALIGN_LEFT) X += scrollbar_width_; + } + if (W < 0) W = 0; + if (hscrollbar.visible()) { + H -= scrollbar_width_; + if (scrollbar.align() & FL_ALIGN_TOP) Y += scrollbar_width_; + } + if (H < 0) H = 0; +} + +int Fl_Browser_::leftedge() const { + int X, Y, W, H; bbox(X, Y, W, H); + return X; +} + +// The scrollbars may be moved again by draw(), since each one's size +// depends on whether the other is visible or not. This skips over +// Fl_Group::resize since it moves the scrollbars uselessly. +void Fl_Browser_::resize(int X, int Y, int W, int H) { + Fl_Widget::resize(X, Y, W, H); + // move the scrollbars so they can respond to events: + bbox(X,Y,W,H); + scrollbar.resize( + scrollbar.align()&FL_ALIGN_LEFT ? X-scrollbar_width_ : X+W, + Y, scrollbar_width_, H); + hscrollbar.resize( + X, scrollbar.align()&FL_ALIGN_TOP ? Y-scrollbar_width_ : Y+H, + W, scrollbar_width_); +} + +// Cause minimal update to redraw the given item: +void Fl_Browser_::redraw_line(void* l) { + if (!redraw1 || redraw1 == l) {redraw1 = l; damage(FL_DAMAGE_EXPOSE);} + else if (!redraw2 || redraw2 == l) {redraw2 = l; damage(FL_DAMAGE_EXPOSE);} + else damage(FL_DAMAGE_SCROLL); +} + +// Figure out top() based on position(): +void Fl_Browser_::update_top() { + if (!top_) top_ = item_first(); + if (position_ != real_position_) { + void* l; + int ly; + int yy = position_; + // start from either head or current position, whichever is closer: + if (!top_ || yy <= (real_position_/2)) { + l = item_first(); + ly = 0; + } else { + l = top_; + ly = real_position_-offset_; + } + if (!l) { + top_ = 0; + offset_ = 0; + real_position_ = 0; + } else { + int hh = item_quick_height(l); + // step through list until we find line containing this point: + while (ly > yy) { + void* l1 = item_prev(l); + if (!l1) {ly = 0; break;} // hit the top + l = l1; + hh = item_quick_height(l); + ly -= hh; + } + while ((ly+hh) <= yy) { + void* l1 = item_next(l); + if (!l1) {yy = ly+hh-1; break;} + l = l1; + ly += hh; + hh = item_quick_height(l); + } + // top item must *really* be visible, use slow height: + for (;;) { + hh = item_height(l); + if ((ly+hh) > yy) break; // it is big enough to see + // go up to top of previous item: + void* l1 = item_prev(l); + if (!l1) {ly = yy = 0; break;} // hit the top + l = l1; yy = position_ = ly = ly-item_quick_height(l); + } + // use it: + top_ = l; + offset_ = yy-ly; + real_position_ = yy; + } + damage(FL_DAMAGE_SCROLL); + } +} + +// Change position(), top() will update when update_top() is called +// (probably by draw() or handle()): +void Fl_Browser_::position(int yy) { + if (yy < 0) yy = 0; + if (yy == position_) return; + position_ = yy; + if (yy != real_position_) redraw_lines(); +} + +void Fl_Browser_::hposition(int xx) { + if (xx < 0) xx = 0; + if (xx == hposition_) return; + hposition_ = xx; + if (xx != real_hposition_) redraw_lines(); +} + +// Tell whether item is currently displayed: +int Fl_Browser_::displayed(void* p) const { + int X, Y, W, H; bbox(X, Y, W, H); + int yy = H+offset_; + for (void* l = top_; l && yy > 0; l = item_next(l)) { + if (l == p) return 1; + yy -= item_height(l); + } + return 0; +} + +// Ensure this item is displayed: +// Messy because we have no idea if it is before top or after bottom: +void Fl_Browser_::display(void* p) { + + // First special case - want to display first item in the list? + update_top(); + if (p == item_first()) {position(0); return;} + + int X, Y, W, H, Yp; bbox(X, Y, W, H); + void* l = top_; + Y = Yp = -offset_; + int h1; + + // 2nd special case - want to display item already displayed at top of browser? + if (l == p) {position(real_position_+Y); return;} // scroll up a bit + + // 3rd special case - want to display item just above top of browser? + void* lp = item_prev(l); + if (lp == p) {position(real_position_+Y-item_quick_height(lp)); return;} + +#ifdef DISPLAY_SEARCH_BOTH_WAYS_AT_ONCE + // search for item. We search both up and down the list at the same time, + // this evens up the execution time for the two cases - the old way was + // much slower for going up than for going down. + while (l || lp) { + if (l) { + h1 = item_quick_height(l); + if (l == p) { + if (Y <= H) { // it is visible or right at bottom + Y = Y+h1-H; // find where bottom edge is + if (Y > 0) position(real_position_+Y); // scroll down a bit + } else { + position(real_position_+Y-(H-h1)/2); // center it + } + return; + } + Y += h1; + l = item_next(l); + } + if (lp) { + h1 = item_quick_height(lp); + Yp -= h1; + if (lp == p) { + if ((Yp + h1) >= 0) position(real_position_+Yp); + else position(real_position_+Yp-(H-h1)/2); + return; + } + lp = item_prev(lp); + } + } +#else + // Old version went forwards and then backwards: + // search forward for it: + l = top_; + for (; l; l = item_next(l)) { + h1 = item_quick_height(l); + if (l == p) { + if (Y <= H) { // it is visible or right at bottom + Y = Y+h1-H; // find where bottom edge is + if (Y > 0) position(real_position_+Y); // scroll down a bit + } else { + position(real_position_+Y-(H-h1)/2); // center it + } + return; + } + Y += h1; + } + // search backward for it, if found center it: + l = lp; + Y = -offset_; + for (; l; l = item_prev(l)) { + h1 = item_quick_height(l); + Y -= h1; + if (l == p) { + if ((Y + h1) >= 0) position(real_position_+Y); + else position(real_position_+Y-(H-h1)/2); + return; + } + } +#endif +} + +// redraw, has side effect of updating top and setting scrollbar: + +void Fl_Browser_::draw() { + int drawsquare = 0; + update_top(); + int full_width_ = full_width(); + int full_height_ = full_height(); + int X, Y, W, H; bbox(X, Y, W, H); + int dont_repeat = 0; +J1: + if (damage() & FL_DAMAGE_ALL) { // redraw the box if full redraw + Fl_Boxtype b = box() ? box() : FL_DOWN_BOX; + draw_box(b, x(), y(), w(), h(), color()); + drawsquare = 1; + } + // see if scrollbar needs to be switched on/off: + if ((has_scrollbar_ & VERTICAL) && ( + (has_scrollbar_ & ALWAYS_ON) || position_ || full_height_ > H)) { + if (!scrollbar.visible()) { + scrollbar.set_visible(); + drawsquare = 1; + bbox(X, Y, W, H); + } + } else { + top_ = item_first(); real_position_ = offset_ = 0; + if (scrollbar.visible()) { + scrollbar.clear_visible(); + clear_damage((uchar)(damage()|FL_DAMAGE_SCROLL)); + } + } + + if ((has_scrollbar_ & HORIZONTAL) && ( + (has_scrollbar_ & ALWAYS_ON) || hposition_ || full_width_ > W)) { + if (!hscrollbar.visible()) { + hscrollbar.set_visible(); + drawsquare = 1; + bbox(X, Y, W, H); + } + } else { + real_hposition_ = 0; + if (hscrollbar.visible()) { + hscrollbar.clear_visible(); + clear_damage((uchar)(damage()|FL_DAMAGE_SCROLL)); + } + } + + // Check the vertical scrollbar again, just in case it needs to be drawn + // because the horizontal one is drawn. There should be a cleaner way + // to do this besides copying the same code... + if ((has_scrollbar_ & VERTICAL) && ( + (has_scrollbar_ & ALWAYS_ON) || position_ || full_height_ > H)) { + if (!scrollbar.visible()) { + scrollbar.set_visible(); + drawsquare = 1; + bbox(X, Y, W, H); + } + } else { + top_ = item_first(); real_position_ = offset_ = 0; + if (scrollbar.visible()) { + scrollbar.clear_visible(); + clear_damage((uchar)(damage()|FL_DAMAGE_SCROLL)); + } + } + + bbox(X, Y, W, H); + + fl_clip(X, Y, W, H); + // for each line, draw it if full redraw or scrolled. Erase background + // if not a full redraw or if it is selected: + void* l = top(); + int yy = -offset_; + for (; l && yy < H; l = item_next(l)) { + int hh = item_height(l); + if (hh <= 0) continue; + if ((damage()&(FL_DAMAGE_SCROLL|FL_DAMAGE_ALL)) || l == redraw1 || l == redraw2) { + if (item_selected(l)) { + fl_color(active_r() ? selection_color() : fl_inactive(selection_color())); + fl_rectf(X, yy+Y, W, hh); + } else if (!(damage()&FL_DAMAGE_ALL)) { + fl_push_clip(X, yy+Y, W, hh); + draw_box(box() ? box() : FL_DOWN_BOX, x(), y(), w(), h(), color()); + fl_pop_clip(); + } + item_draw(l, X-hposition_, yy+Y, W+hposition_, hh); + if (l == selection_ && Fl::focus() == this) { + draw_box(FL_BORDER_FRAME, X, yy+Y, W, hh, color()); + draw_focus(FL_NO_BOX, X, yy+Y, W+1, hh+1); + } + int ww = item_width(l); + if (ww > max_width) {max_width = ww; max_width_item = l;} + } + yy += hh; + } + // erase the area below last line: + if (!(damage()&FL_DAMAGE_ALL) && yy < H) { + fl_push_clip(X, yy+Y, W, H-yy); + draw_box(box() ? box() : FL_DOWN_BOX, x(), y(), w(), h(), color()); + fl_pop_clip(); + } + fl_pop_clip(); + redraw1 = redraw2 = 0; + + if (!dont_repeat) { + dont_repeat = 1; + // see if changes to full_height caused by calls to slow_height + // caused scrollbar state to change, in which case we have to redraw: + full_height_ = full_height(); + full_width_ = full_width(); + if ((has_scrollbar_ & VERTICAL) && + ((has_scrollbar_ & ALWAYS_ON) || position_ || full_height_>H)) { + if (!scrollbar.visible()) { damage(FL_DAMAGE_ALL); goto J1; } + } else { + if (scrollbar.visible()) { damage(FL_DAMAGE_ALL); goto J1; } + } + if ((has_scrollbar_ & HORIZONTAL) && + ((has_scrollbar_ & ALWAYS_ON) || hposition_ || full_width_>W)) { + if (!hscrollbar.visible()) { damage(FL_DAMAGE_ALL); goto J1; } + } else { + if (hscrollbar.visible()) { damage(FL_DAMAGE_ALL); goto J1; } + } + } + + // update the scrollbars and redraw them: + int dy = top_ ? item_quick_height(top_) : 0; if (dy < 10) dy = 10; + if (scrollbar.visible()) { + scrollbar.damage_resize( + scrollbar.align()&FL_ALIGN_LEFT ? X-scrollbar_width_ : X+W, + Y, scrollbar_width_, H); + scrollbar.value(position_, H, 0, full_height_); + scrollbar.linesize(dy); + if (drawsquare) draw_child(scrollbar); + else update_child(scrollbar); + } + if (hscrollbar.visible()) { + hscrollbar.damage_resize( + X, scrollbar.align()&FL_ALIGN_TOP ? Y-scrollbar_width_ : Y+H, + W, scrollbar_width_); + hscrollbar.value(hposition_, W, 0, full_width_); + hscrollbar.linesize(dy); + if (drawsquare) draw_child(hscrollbar); + else update_child(hscrollbar); + } + + // draw that little square between the scrollbars: + if (drawsquare && scrollbar.visible() && hscrollbar.visible()) { + fl_color(parent()->color()); + fl_rectf(scrollbar.x(), hscrollbar.y(), scrollbar_width_,scrollbar_width_); + } + + real_hposition_ = hposition_; +} + +// Quick way to delete and reset everything: +void Fl_Browser_::new_list() { + top_ = 0; + position_ = real_position_ = 0; + hposition_ = real_hposition_ = 0; + selection_ = 0; + offset_ = 0; + max_width = 0; + max_width_item = 0; + redraw_lines(); +} + +// Tell it that this item is going away, and that this must remove +// all pointers to it: +void Fl_Browser_::deleting(void* l) { + if (displayed(l)) { + redraw_lines(); + if (l == top_) { + real_position_ -= offset_; + offset_ = 0; + top_ = item_next(l); + if (!top_) top_ = item_prev(l); + } + } else { + // we don't know where this item is, recalculate top... + real_position_ = 0; + offset_ = 0; + top_ = 0; + } + if (l == selection_) selection_ = 0; + if (l == max_width_item) {max_width_item = 0; max_width = 0;} +} + +void Fl_Browser_::replacing(void* a, void* b) { + redraw_line(a); + if (a == selection_) selection_ = b; + if (a == top_) top_ = b; + if (a == max_width_item) {max_width_item = 0; max_width = 0;} +} + +void Fl_Browser_::inserting(void* a, void* b) { + if (displayed(a)) redraw_lines(); + if (a == top_) top_ = b; +} + +void* Fl_Browser_::find_item(int my) { + update_top(); + int X, Y, W, H; bbox(X, Y, W, H); + void* l; + int yy = Y-offset_; + for (l = top_; l; l = item_next(l)) { + int hh = item_height(l); if (hh <= 0) continue; + yy += hh; + if (my <= yy || yy>=(Y+H)) return l; + } + return 0; +} + +int Fl_Browser_::select(void* l, int i, int docallbacks) { + if (type() == FL_MULTI_BROWSER) { + if (selection_ != l) { + if (selection_) redraw_line(selection_); + selection_ = l; + redraw_line(l); + } + if ((!i)==(!item_selected(l))) return 0; + item_select(l, i); + redraw_line(l); + } else { + if (i && selection_ == l) return 0; + if (!i && selection_ != l) return 0; + if (selection_) { + item_select(selection_, 0); + redraw_line(selection_); + selection_ = 0; + } + if (i) { + item_select(l, 1); + selection_ = l; + redraw_line(l); + display(l); + } + } + if (docallbacks) { + set_changed(); + do_callback(); + } + return 1; +} + +int Fl_Browser_::deselect(int docallbacks) { + if (type() == FL_MULTI_BROWSER) { + int change = 0; + for (void* p = item_first(); p; p = item_next(p)) + change |= select(p, 0, docallbacks); + return change; + } else { + if (!selection_) return 0; + item_select(selection_, 0); + redraw_line(selection_); + selection_ = 0; + return 1; + } +} + +int Fl_Browser_::select_only(void* l, int docallbacks) { + if (!l) return deselect(docallbacks); + int change = 0; + if (type() == FL_MULTI_BROWSER) { + for (void* p = item_first(); p; p = item_next(p)) + if (p != l) change |= select(p, 0, docallbacks); + } + change |= select(l, 1, docallbacks); + display(l); + return change; +} + +int Fl_Browser_::handle(int event) { + // must do shortcuts first or the scrollbar will get them... + if (event == FL_ENTER || event == FL_LEAVE) return 1; + if (event == FL_KEYBOARD && type() >= FL_HOLD_BROWSER) { + void* l1 = selection_; + void* l = l1; if (!l) l = top_; if (!l) l = item_first(); + if (l) { + if (type()==FL_HOLD_BROWSER) switch (Fl::event_key()) { + case FL_Down: + while ((l = item_next(l))) + if (item_height(l)>0) {select_only(l, 1); break;} + return 1; + case FL_Up: + while ((l = item_prev(l))) if (item_height(l)>0) { + select_only(l, 1); break;} + return 1; + } else switch (Fl::event_key()) { + case FL_Enter: + case FL_KP_Enter: + select_only(l, 1); + return 1; + case ' ': + selection_ = l; + select(l, !item_selected(l), 1); + return 1; + case FL_Down: + while ((l = item_next(l))) { + if (Fl::event_state(FL_SHIFT|FL_CTRL)) + select(l, l1 ? item_selected(l1) : 1, 1); + if (item_height(l)>0) goto J1; + } + return 1; + case FL_Up: + while ((l = item_prev(l))) { + if (Fl::event_state(FL_SHIFT|FL_CTRL)) + select(l, l1 ? item_selected(l1) : 1, 1); + if (item_height(l)>0) goto J1; + } + return 1; + J1: + if (selection_) redraw_line(selection_); + selection_ = l; redraw_line(l); + display(l); + return 1; + } + } + } + + if (Fl_Group::handle(event)) return 1; + int X, Y, W, H; bbox(X, Y, W, H); + int my; +// NOTE: +// instead of: +// change = select_only(find_item(my), when() & FL_WHEN_CHANGED) +// we use the construct: +// change = select_only(find_item(my), 0); +// if (change && (when() & FL_WHEN_CHANGED)) { +// set_changed(); +// do_callback(); +// } +// See str #834 +// The first form calls the callback *before* setting change. +// The callback may execute an Fl::wait(), resulting in another +// call of Fl_Browser_::handle() for the same widget. The sequence +// of events can be an FL_PUSH followed by an FL_RELEASE. +// This second call of Fl_Browser_::handle() may result in a - +// somewhat unexpected - second concurrent invocation of the callback. + + static char change; + static char whichway; + static int py; + switch (event) { + case FL_PUSH: + if (!Fl::event_inside(X, Y, W, H)) return 0; + if (Fl::visible_focus()) { + Fl::focus(this); + redraw(); + } + my = py = Fl::event_y(); + change = 0; + if (type() == FL_NORMAL_BROWSER || !top_) + ; + else if (type() != FL_MULTI_BROWSER) { + change = select_only(find_item(my), 0); + if (change && (when() & FL_WHEN_CHANGED)) { + set_changed(); + do_callback(); + } + } else { + void* l = find_item(my); + whichway = 1; + if (Fl::event_state(FL_CTRL)) { // toggle selection: + TOGGLE: + if (l) { + whichway = !item_selected(l); + change = select(l, whichway, 0); + if (change && (when() & FL_WHEN_CHANGED)) { + set_changed(); + do_callback(); + } + } + } else if (Fl::event_state(FL_SHIFT)) { // extend selection: + if (l == selection_) goto TOGGLE; + // state of previous selection determines new value: + whichway = l ? !item_selected(l) : 1; + // see which of the new item or previous selection is earlier, + // by searching from the previous forward for this one: + int down; + if (!l) down = 1; + else {for (void* m = selection_; ; m = item_next(m)) { + if (m == l) {down = 1; break;} + if (!m) {down = 0; break;} + }} + if (down) { + for (void* m = selection_; m != l; m = item_next(m)) + select(m, whichway, when() & FL_WHEN_CHANGED); + } else { + void* e = selection_; + for (void* m = item_next(l); m; m = item_next(m)) { + select(m, whichway, when() & FL_WHEN_CHANGED); + if (m == e) break; + } + } + // do the clicked item last so the select box is around it: + change = 1; + if (l) select(l, whichway, when() & FL_WHEN_CHANGED); + } else { // select only this item + change = select_only(l, 0); + if (change && (when() & FL_WHEN_CHANGED)) { + set_changed(); + do_callback(); + } + } + } + return 1; + case FL_DRAG: + // do the scrolling first: + my = Fl::event_y(); + if (my < Y && my < py) { + int p = real_position_+my-Y; + if (p<0) p = 0; + position(p); + } else if (my > (Y+H) && my > py) { + int p = real_position_+my-(Y+H); + int hh = full_height()-H; if (p > hh) p = hh; + if (p<0) p = 0; + position(p); + } + if (type() == FL_NORMAL_BROWSER || !top_) + ; + else if (type() == FL_MULTI_BROWSER) { + void* l = find_item(my); + void* t; void* b; // this will be the range to change + if (my > py) { // go down + t = selection_ ? item_next(selection_) : 0; + b = l ? item_next(l) : 0; + } else { // go up + t = l; + b = selection_; + } + for (; t && t != b; t = item_next(t)) { + char change_t; + change_t = select(t, whichway, 0); + change |= change_t; + if (change_t && (when() & FL_WHEN_CHANGED)) { + set_changed(); + do_callback(); + } + } + if (l) selection_ = l; + } else { + void* l1 = selection_; + void* l = + (Fl::event_x()<x() || Fl::event_x()>x()+w()) ? selection_ : + find_item(my); + change = (l != l1); + select_only(l, when() & FL_WHEN_CHANGED); + } + py = my; + return 1; + case FL_RELEASE: + if (type() == FL_SELECT_BROWSER) { + void* t = selection_; deselect(); selection_ = t; + } + if (change) { + set_changed(); + if (when() & FL_WHEN_RELEASE) do_callback(); + } else { + if (when() & FL_WHEN_NOT_CHANGED) do_callback(); + } + return 1; + case FL_FOCUS: + case FL_UNFOCUS: + if (type() >= FL_HOLD_BROWSER && Fl::visible_focus()) { + redraw(); + return 1; + } else return 0; + } + + return 0; +} + +Fl_Browser_::Fl_Browser_(int X, int Y, int W, int H, const char* l) + : Fl_Group(X, Y, W, H, l), + scrollbar(0, 0, 0, 0, 0), // they will be resized by draw() + hscrollbar(0, 0, 0, 0, 0) +{ + box(FL_NO_BOX); + align(FL_ALIGN_BOTTOM); + position_ = real_position_ = 0; + hposition_ = real_hposition_ = 0; + offset_ = 0; + top_ = 0; + when(FL_WHEN_RELEASE_ALWAYS); + selection_ = 0; + color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR); + scrollbar.callback(scrollbar_callback); +//scrollbar.align(FL_ALIGN_LEFT|FL_ALIGN_BOTTOM); // back compatability? + hscrollbar.callback(hscrollbar_callback); + hscrollbar.type(FL_HORIZONTAL); + textfont_ = FL_HELVETICA; + textsize_ = (uchar)FL_NORMAL_SIZE; + textcolor_ = FL_FOREGROUND_COLOR; + has_scrollbar_ = BOTH; + max_width = 0; + max_width_item = 0; + redraw1 = redraw2 = 0; + end(); +} + +// Default versions of some of the virtual functions: + +int Fl_Browser_::item_quick_height(void* l) const { + return item_height(l); +} + +int Fl_Browser_::incr_height() const { + return item_quick_height(item_first()); +} + +int Fl_Browser_::full_height() const { + int t = 0; + for (void* p = item_first(); p; p = item_next(p)) + t += item_quick_height(p); + return t; +} + +int Fl_Browser_::full_width() const { + return max_width; +} + +void Fl_Browser_::item_select(void*, int) {} + +int Fl_Browser_::item_selected(void* l) const {return l==selection_;} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Browser_load.cxx b/Utilities/FLTK/src/Fl_Browser_load.cxx new file mode 100644 index 0000000000..1e12a78728 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Browser_load.cxx @@ -0,0 +1,57 @@ +// +// "$Id$" +// +// File loading routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Browser.H> +#include <stdio.h> + +int Fl_Browser::load(const char *filename) { +#define MAXFL_BLINE 1024 + char newtext[MAXFL_BLINE]; + int c; + int i; + clear(); + if (!filename || !(filename[0])) return 1; + FILE *fl = fopen(filename,"r"); + if (!fl) return 0; + i = 0; + do { + c = getc(fl); + if (c == '\n' || c <= 0 || i>=(MAXFL_BLINE-1)) { + newtext[i] = 0; + add(newtext); + i = 0; + } else + newtext[i++] = c; + } while (c >= 0); + fclose(fl); + return 1; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Button.cxx b/Utilities/FLTK/src/Fl_Button.cxx new file mode 100644 index 0000000000..8a4536de0a --- /dev/null +++ b/Utilities/FLTK/src/Fl_Button.cxx @@ -0,0 +1,164 @@ +// +// "$Id$" +// +// Button widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Group.H> +#include <FL/Fl_Window.H> + +// There are a lot of subclasses, named Fl_*_Button. Some of +// them are implemented by setting the type() value and testing it +// here. This includes Fl_Radio_Button and Fl_Toggle_Button + +int Fl_Button::value(int v) { + v = v ? 1 : 0; + oldval = v; + clear_changed(); + if (value_ != v) { + value_ = v; + redraw(); + return 1; + } else { + return 0; + } +} + +void Fl_Button::setonly() { // set this radio button on, turn others off + value(1); + Fl_Group* g = (Fl_Group*)parent(); + Fl_Widget*const* a = g->array(); + for (int i = g->children(); i--;) { + Fl_Widget* o = *a++; + if (o != this && o->type()==FL_RADIO_BUTTON) ((Fl_Button*)o)->value(0); + } +} + +void Fl_Button::draw() { + if (type() == FL_HIDDEN_BUTTON) return; + Fl_Color col = value() ? selection_color() : color(); +//if (col == FL_GRAY && Fl::belowmouse()==this) col = FL_LIGHT1; + draw_box(value() ? (down_box()?down_box():fl_down(box())) : box(), col); + draw_label(); + if (Fl::focus() == this) draw_focus(); +} + +int Fl_Button::handle(int event) { + int newval; + switch (event) { + case FL_ENTER: + case FL_LEAVE: +// if ((value_?selection_color():color())==FL_GRAY) redraw(); + return 1; + case FL_PUSH: + if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this); + case FL_DRAG: + if (Fl::event_inside(this)) { + if (type() == FL_RADIO_BUTTON) newval = 1; + else newval = !oldval; + } else + newval = oldval; + if (newval != value_) { + value_ = newval; + set_changed(); + redraw(); + if (when() & FL_WHEN_CHANGED) do_callback(); + } + return 1; + case FL_RELEASE: + if (value_ == oldval) { + if (when() & FL_WHEN_NOT_CHANGED) do_callback(); + return 1; + } + set_changed(); + if (type() == FL_RADIO_BUTTON) setonly(); + else if (type() == FL_TOGGLE_BUTTON) oldval = value_; + else { + value(oldval); + if (when() & FL_WHEN_CHANGED) do_callback(); + } + if (when() & FL_WHEN_RELEASE) do_callback(); + return 1; + case FL_SHORTCUT: + if (!(shortcut() ? + Fl::test_shortcut(shortcut()) : test_shortcut())) return 0; + + if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this); + + if (type() == FL_RADIO_BUTTON && !value_) { + setonly(); + set_changed(); + if (when() & FL_WHEN_CHANGED) do_callback(); + } else if (type() == FL_TOGGLE_BUTTON) { + value(!value()); + set_changed(); + if (when() & FL_WHEN_CHANGED) do_callback(); + } else if (when() & FL_WHEN_RELEASE) do_callback(); + return 1; + case FL_FOCUS : + case FL_UNFOCUS : + if (Fl::visible_focus()) { + if (box() == FL_NO_BOX) { + // Widgets with the FL_NO_BOX boxtype need a parent to + // redraw, since it is responsible for redrawing the + // background... + int X = x() > 0 ? x() - 1 : 0; + int Y = y() > 0 ? y() - 1 : 0; + if (window()) window()->damage(FL_DAMAGE_ALL, X, Y, w() + 2, h() + 2); + } else redraw(); + return 1; + } else return 0; + case FL_KEYBOARD : + if (Fl::focus() == this && Fl::event_key() == ' ' && + !(Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) { + set_changed(); + if (type() == FL_RADIO_BUTTON && !value_) { + setonly(); + if (when() & FL_WHEN_CHANGED) do_callback(); + } else if (type() == FL_TOGGLE_BUTTON) { + value(!value()); + if (when() & FL_WHEN_CHANGED) do_callback(); + } + if (when() & FL_WHEN_RELEASE) do_callback(); + return 1; + } + default: + return 0; + } +} + +Fl_Button::Fl_Button(int X, int Y, int W, int H, const char *l) +: Fl_Widget(X,Y,W,H,l) { + box(FL_UP_BOX); + down_box(FL_NO_BOX); + value_ = oldval = 0; + shortcut_ = 0; + set_flag(SHORTCUT_LABEL); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Chart.cxx b/Utilities/FLTK/src/Fl_Chart.cxx new file mode 100644 index 0000000000..fce4bf045f --- /dev/null +++ b/Utilities/FLTK/src/Fl_Chart.cxx @@ -0,0 +1,390 @@ +// +// "$Id$" +// +// Forms-compatible chart widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/math.h> +#include <FL/Fl.H> +#include <FL/Fl_Chart.H> +#include <FL/fl_draw.H> +#include "flstring.h" +#include <stdlib.h> + +#define ARCINC (2.0*M_PI/360.0) + +// this function is in fl_boxtype.cxx: +void fl_rectbound(int x,int y,int w,int h, Fl_Color color); + +/* Widget specific information */ + +static void draw_barchart(int x,int y,int w,int h, + int numb, FL_CHART_ENTRY entries[], + double min, double max, int autosize, int maxnumb, + Fl_Color textcolor) +/* Draws a bar chart. x,y,w,h is the bounding box, entries the array of + numb entries and min and max the boundaries. */ +{ + double incr; + int zeroh; + double lh = fl_height(); + if (max == min) incr = h; + else incr = h/(max-min); + if ( (-min*incr) < lh) { + incr = (h - lh + min*incr)/(max-min); + zeroh = int(y+h-lh); + } else { + zeroh = (int)rint(y+h+min * incr); + } + int bwidth = (int)rint(w/double(autosize?numb:maxnumb)); + /* Draw base line */ + fl_color(textcolor); + fl_line(x, zeroh, x+w, zeroh); + if (min == 0.0 && max == 0.0) return; /* Nothing else to draw */ + int i; + /* Draw the bars */ + for (i=0; i<numb; i++) { + int hh = (int)rint(entries[i].val*incr); + if (hh < 0) + fl_rectbound(x+i*bwidth,zeroh,bwidth+1,-hh+1, (Fl_Color)entries[i].col); + else if (hh > 0) + fl_rectbound(x+i*bwidth,zeroh-hh,bwidth+1,hh+1,(Fl_Color)entries[i].col); + } + /* Draw the labels */ + fl_color(textcolor); + for (i=0; i<numb; i++) + fl_draw(entries[i].str, + x+i*bwidth+bwidth/2,zeroh,0,0, + FL_ALIGN_TOP); +} + +static void draw_horbarchart(int x,int y,int w,int h, + int numb, FL_CHART_ENTRY entries[], + double min, double max, int autosize, int maxnumb, + Fl_Color textcolor) +/* Draws a horizontal bar chart. x,y,w,h is the bounding box, entries the + array of numb entries and min and max the boundaries. */ +{ + int i; + double lw = 0.0; /* Maximal label width */ + /* Compute maximal label width */ + for (i=0; i<numb; i++) { + double w1 = fl_width(entries[i].str); + if (w1 > lw) lw = w1; + } + if (lw > 0.0) lw += 4.0; + double incr; + int zeroh; + if (max == min) incr = w; + else incr = w/(max-min); + if ( (-min*incr) < lw) { + incr = (w - lw + min*incr)/(max-min); + zeroh = x+(int)rint(lw); + } else { + zeroh = (int)rint(x-min * incr); + } + int bwidth = (int)rint(h/double(autosize?numb:maxnumb)); + /* Draw base line */ + fl_color(textcolor); + fl_line(zeroh, y, zeroh, y+h); + if (min == 0.0 && max == 0.0) return; /* Nothing else to draw */ + /* Draw the bars */ + for (i=0; i<numb; i++) { + int ww = (int)rint(entries[i].val*incr); + if (ww > 0) + fl_rectbound(zeroh,y+i*bwidth,ww+1,bwidth+1, (Fl_Color)entries[i].col); + else if (ww < 0) + fl_rectbound(zeroh+w,y+i*bwidth,-ww+1,bwidth+1,(Fl_Color)entries[i].col); + } + /* Draw the labels */ + fl_color(textcolor); + for (i=0; i<numb; i++) + fl_draw(entries[i].str, + zeroh-2,y+i*bwidth+bwidth/2,0,0, + FL_ALIGN_RIGHT); +} + +static void draw_linechart(int type, int x,int y,int w,int h, + int numb, FL_CHART_ENTRY entries[], + double min, double max, int autosize, int maxnumb, + Fl_Color textcolor) +/* Draws a line chart. x,y,w,h is the bounding box, entries the array of + numb entries and min and max the boundaries. */ +{ + int i; + double lh = fl_height(); + double incr; + if (max == min) incr = h-2.0*lh; + else incr = (h-2.0*lh)/ (max-min); + int zeroh = (int)rint(y+h-lh+min * incr); + double bwidth = w/double(autosize?numb:maxnumb); + /* Draw the values */ + for (i=0; i<numb; i++) { + int x0 = x + (int)rint((i-.5)*bwidth); + int x1 = x + (int)rint((i+.5)*bwidth); + int yy0 = i ? zeroh - (int)rint(entries[i-1].val*incr) : 0; + int yy1 = zeroh - (int)rint(entries[i].val*incr); + if (type == FL_SPIKE_CHART) { + fl_color((Fl_Color)entries[i].col); + fl_line(x1, zeroh, x1, yy1); + } else if (type == FL_LINE_CHART && i != 0) { + fl_color((Fl_Color)entries[i-1].col); + fl_line(x0,yy0,x1,yy1); + } else if (type == FL_FILLED_CHART && i != 0) { + fl_color((Fl_Color)entries[i-1].col); + if ((entries[i-1].val>0.0)!=(entries[i].val>0.0)) { + double ttt = entries[i-1].val/(entries[i-1].val-entries[i].val); + int xt = x + (int)rint((i-.5+ttt)*bwidth); + fl_polygon(x0,zeroh, x0,yy0, xt,zeroh); + fl_polygon(xt,zeroh, x1,yy1, x1,zeroh); + } else { + fl_polygon(x0,zeroh, x0,yy0, x1,yy1, x1,zeroh); + } + fl_color(textcolor); + fl_line(x0,yy0,x1,yy1); + } + } + /* Draw base line */ + fl_color(textcolor); + fl_line(x,zeroh,x+w,zeroh); + /* Draw the labels */ + for (i=0; i<numb; i++) + fl_draw(entries[i].str, + x+(int)rint((i+.5)*bwidth), zeroh - (int)rint(entries[i].val*incr),0,0, + entries[i].val>=0 ? FL_ALIGN_BOTTOM : FL_ALIGN_TOP); +} + +static void draw_piechart(int x,int y,int w,int h, + int numb, FL_CHART_ENTRY entries[], int special, + Fl_Color textcolor) +/* Draws a pie chart. x,y,w,h is the bounding box, entries the array of + numb entries */ +{ + int i; + double xc,yc,rad; /* center and radius */ + double tot; /* sum of values */ + double incr; /* increment in angle */ + double curang; /* current angle we are drawing */ + double txc,tyc; /* temporary center */ + double lh = fl_height(); + /* compute center and radius */ + double h_denom = (special ? 2.3 : 2.0); + rad = (h - 2*lh)/h_denom/1.1; + xc = x+w/2.0; yc = y+h-1.1*rad-lh; + /* compute sum of values */ + tot = 0.0; + for (i=0; i<numb; i++) + if (entries[i].val > 0.0) tot += entries[i].val; + if (tot == 0.0) return; + incr = 360.0/tot; + /* Draw the pie */ + curang = 0.0; + for (i=0; i<numb; i++) + if (entries[i].val > 0.0) + { + txc = xc; tyc = yc; + /* Correct for special pies */ + if (special && i==0) + { + txc += 0.3*rad*cos(ARCINC*(curang+0.5*incr*entries[i].val)); + tyc -= 0.3*rad*sin(ARCINC*(curang+0.5*incr*entries[i].val)); + } + fl_color((Fl_Color)entries[i].col); + fl_begin_polygon(); fl_vertex(txc,tyc); + fl_arc(txc,tyc,rad,curang, curang+incr*entries[i].val); + fl_end_polygon(); + fl_color(textcolor); + fl_begin_loop(); fl_vertex(txc,tyc); + fl_arc(txc,tyc,rad,curang, curang+incr*entries[i].val); + fl_end_loop(); + curang += 0.5 * incr * entries[i].val; + /* draw the label */ + double xl = txc + 1.1*rad*cos(ARCINC*curang); + fl_draw(entries[i].str, + (int)rint(xl), + (int)rint(tyc - 1.1*rad*sin(ARCINC*curang)), + 0, 0, + xl<txc ? FL_ALIGN_RIGHT : FL_ALIGN_LEFT); + curang += 0.5 * incr * entries[i].val; + } +} + +void Fl_Chart::draw() { + + draw_box(); + Fl_Boxtype b = box(); + int xx = x()+Fl::box_dx(b); // was 9 instead of dx... + int yy = y()+Fl::box_dy(b); + int ww = w()-Fl::box_dw(b); + int hh = h()-Fl::box_dh(b); + fl_push_clip(xx, yy, ww, hh); + + ww--; hh--; // adjust for line thickness + + if (min >= max) { + min = max = 0.0; + for (int i=0; i<numb; i++) { + if (entries[i].val < min) min = entries[i].val; + if (entries[i].val > max) max = entries[i].val; + } + } + + fl_font(textfont(),textsize()); + + switch (type()) { + case FL_BAR_CHART: + ww++; // makes the bars fill box correctly + draw_barchart(xx,yy,ww,hh, numb, entries, min, max, + autosize(), maxnumb, textcolor()); + break; + case FL_HORBAR_CHART: + hh++; // makes the bars fill box correctly + draw_horbarchart(xx,yy,ww,hh, numb, entries, min, max, + autosize(), maxnumb, textcolor()); + break; + case FL_PIE_CHART: + draw_piechart(xx,yy,ww,hh,numb,entries,0, textcolor()); + break; + case FL_SPECIALPIE_CHART: + draw_piechart(xx,yy,ww,hh,numb,entries,1,textcolor()); + break; + default: + draw_linechart(type(),xx,yy,ww,hh, numb, entries, min, max, + autosize(), maxnumb, textcolor()); + break; + } + draw_label(); + fl_pop_clip(); +} + +/*------------------------------*/ + +#define FL_CHART_BOXTYPE FL_BORDER_BOX +#define FL_CHART_COL1 FL_COL1 +#define FL_CHART_LCOL FL_LCOL +#define FL_CHART_ALIGN FL_ALIGN_BOTTOM + +Fl_Chart::Fl_Chart(int X, int Y, int W, int H,const char *l) : +Fl_Widget(X,Y,W,H,l) { + box(FL_BORDER_BOX); + align(FL_ALIGN_BOTTOM); + numb = 0; + maxnumb = 0; + sizenumb = FL_CHART_MAX; + autosize_ = 1; + min = max = 0; + textfont_ = FL_HELVETICA; + textsize_ = 10; + textcolor_ = FL_FOREGROUND_COLOR; + entries = (FL_CHART_ENTRY *)calloc(sizeof(FL_CHART_ENTRY), FL_CHART_MAX + 1); +} + +Fl_Chart::~Fl_Chart() { + free(entries); +} + +void Fl_Chart::clear() { + numb = 0; + redraw(); +} + +void Fl_Chart::add(double val, const char *str, unsigned col) { + /* Allocate more entries if required */ + if (numb >= sizenumb) { + sizenumb += FL_CHART_MAX; + entries = (FL_CHART_ENTRY *)realloc(entries, sizeof(FL_CHART_ENTRY) * (sizenumb + 1)); + } + // Shift entries as needed + if (numb >= maxnumb && maxnumb > 0) { + memmove(entries, entries + 1, sizeof(FL_CHART_ENTRY) * (numb - 1)); + numb --; + } + entries[numb].val = float(val); + entries[numb].col = col; + if (str) { + strlcpy(entries[numb].str,str,FL_CHART_LABEL_MAX + 1); + } else { + entries[numb].str[0] = 0; + } + numb++; + redraw(); +} + +void Fl_Chart::insert(int ind, double val, const char *str, unsigned col) { + int i; + if (ind < 1 || ind > numb+1) return; + /* Allocate more entries if required */ + if (numb >= sizenumb) { + sizenumb += FL_CHART_MAX; + entries = (FL_CHART_ENTRY *)realloc(entries, sizeof(FL_CHART_ENTRY) * (sizenumb + 1)); + } + // Shift entries as needed + for (i=numb; i >= ind; i--) entries[i] = entries[i-1]; + if (numb < maxnumb || maxnumb == 0) numb++; + /* Fill in the new entry */ + entries[ind-1].val = float(val); + entries[ind-1].col = col; + if (str) { + strlcpy(entries[ind-1].str,str,FL_CHART_LABEL_MAX+1); + } else { + entries[ind-1].str[0] = 0; + } + redraw(); +} + +void Fl_Chart::replace(int ind,double val, const char *str, unsigned col) { + if (ind < 1 || ind > numb) return; + entries[ind-1].val = float(val); + entries[ind-1].col = col; + if (str) { + strlcpy(entries[ind-1].str,str,FL_CHART_LABEL_MAX+1); + } else { + entries[ind-1].str[0] = 0; + } + redraw(); +} + +void Fl_Chart::bounds(double mymin, double mymax) { + this->min = mymin; + this->max = mymax; + redraw(); +} + +void Fl_Chart::maxsize(int m) { + int i; + /* Fill in the new number */ + if (m < 0) return; + maxnumb = m; + /* Shift entries if required */ + if (numb > maxnumb) { + for (i = 0; i<maxnumb; i++) + entries[i] = entries[i+numb-maxnumb]; + numb = maxnumb; + redraw(); + } +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Check_Browser.cxx b/Utilities/FLTK/src/Fl_Check_Browser.cxx new file mode 100644 index 0000000000..05c7b1c329 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Check_Browser.cxx @@ -0,0 +1,272 @@ +// +// "$Id$" +// +// Fl_Check_Browser header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <stdio.h> +#include <stdlib.h> +#include "flstring.h" +#include <FL/fl_draw.H> +#include <FL/Fl_Check_Browser.H> + +/* This uses a cache for faster access when you're scanning the list +either forwards or backwards. */ + +Fl_Check_Browser::cb_item *Fl_Check_Browser::find_item(int n) const { + int i = n; + cb_item *p = first; + + if (n <= 0 || n > nitems_ || p == 0) { + return 0; + } + + if (n == cached_item) { + p = cache; + n = 1; + } else if (n == cached_item + 1) { + p = cache->next; + n = 1; + } else if (n == cached_item - 1) { + p = cache->prev; + n = 1; + } + + while (--n) { + p = p->next; + } + + /* Cast to not const and cache it. */ + + ((Fl_Check_Browser *)this)->cache = p; + ((Fl_Check_Browser *)this)->cached_item = i; + + return p; +} + +int Fl_Check_Browser::lineno(cb_item *p0) const { + cb_item *p = first; + + if (p == 0) { + return 0; + } + + int i = 1; + while (p) { + if (p == p0) { + return i; + } + i++; + p = p->next; + } + + return 0; +} + +Fl_Check_Browser::Fl_Check_Browser(int X, int Y, int W, int H, const char *l) + : Fl_Browser_(X, Y, W, H, l) { + type(FL_SELECT_BROWSER); + when(FL_WHEN_NEVER); + first = last = 0; + nitems_ = nchecked_ = 0; + cached_item = -1; +} + +void *Fl_Check_Browser::item_first() const { + return first; +} + +void *Fl_Check_Browser::item_next(void *l) const { + return ((cb_item *)l)->next; +} + +void *Fl_Check_Browser::item_prev(void *l) const { + return ((cb_item *)l)->prev; +} + +int Fl_Check_Browser::item_height(void *) const { + return textsize() + 2; +} + +#define CHECK_SIZE (textsize()-2) + +int Fl_Check_Browser::item_width(void *v) const { + fl_font(textfont(), textsize()); + return int(fl_width(((cb_item *)v)->text)) + CHECK_SIZE + 8; +} + +void Fl_Check_Browser::item_draw(void *v, int X, int Y, int, int) const { + cb_item *i = (cb_item *)v; + char *s = i->text; + int tsize = textsize(); + Fl_Color col = active_r() ? textcolor() : fl_inactive(textcolor()); + int cy = Y + (tsize + 1 - CHECK_SIZE) / 2; + X += 2; + + fl_color(active_r() ? FL_FOREGROUND_COLOR : fl_inactive(FL_FOREGROUND_COLOR)); + fl_loop(X, cy, X, cy + CHECK_SIZE, + X + CHECK_SIZE, cy + CHECK_SIZE, X + CHECK_SIZE, cy); + if (i->checked) { + int tx = X + 3; + int tw = CHECK_SIZE - 4; + int d1 = tw/3; + int d2 = tw-d1; + int ty = cy + (CHECK_SIZE+d2)/2-d1-2; + for (int n = 0; n < 3; n++, ty++) { + fl_line(tx, ty, tx+d1, ty+d1); + fl_line(tx+d1, ty+d1, tx+tw-1, ty+d1-d2+1); + } + } + fl_font(textfont(), tsize); + if (i->selected) { + col = fl_contrast(col, selection_color()); + } + fl_color(col); + fl_draw(s, X + CHECK_SIZE + 8, Y + tsize - 1); +} + +void Fl_Check_Browser::item_select(void *v, int state) { + cb_item *i = (cb_item *)v; + + if (state) { + if (i->checked) { + i->checked = 0; + nchecked_--; + } else { + i->checked = 1; + nchecked_++; + } + } +} + +int Fl_Check_Browser::item_selected(void *v) const { + cb_item *i = (cb_item *)v; + return i->selected; +} + +int Fl_Check_Browser::add(char *s) { + return (add(s, 0)); +} + +int Fl_Check_Browser::add(char *s, int b) { + cb_item *p = (cb_item *)malloc(sizeof(cb_item)); + p->next = 0; + p->prev = 0; + p->checked = b; + p->selected = 0; + p->text = strdup(s); + + if (b) { + nchecked_++; + } + + if (last == 0) { + first = last = p; + } else { + last->next = p; + p->prev = last; + last = p; + } + nitems_++; + + return (nitems_); +} + +void Fl_Check_Browser::clear() { + cb_item *p = first; + cb_item *next; + + if (p == 0) { + return; + } + + new_list(); + do { + next = p->next; + free(p->text); + free(p); + p = next; + } while (p); + + first = last = 0; + nitems_ = nchecked_ = 0; + cached_item = -1; +} + +int Fl_Check_Browser::checked(int i) const { + cb_item *p = find_item(i); + + if (p) return p->checked; + return 0; +} + +void Fl_Check_Browser::checked(int i, int b) { + cb_item *p = find_item(i); + + if (p && (p->checked ^ b)) { + p->checked = b; + if (b) { + nchecked_++; + } else { + nchecked_--; + } + redraw(); + } +} + +int Fl_Check_Browser::value() const { + return lineno((cb_item *)selection()); +} + +char *Fl_Check_Browser::text(int i) const { + cb_item *p = find_item(i); + + if (p) return p->text; + return 0; +} + +void Fl_Check_Browser::check_all() { + cb_item *p; + + nchecked_ = nitems_; + for (p = first; p; p = p->next) { + p->checked = 1; + } + redraw(); +} + +void Fl_Check_Browser::check_none() { + cb_item *p; + + nchecked_ = 0; + for (p = first; p; p = p->next) { + p->checked = 0; + } + redraw(); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Check_Button.cxx b/Utilities/FLTK/src/Fl_Check_Button.cxx new file mode 100644 index 0000000000..54fb028501 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Check_Button.cxx @@ -0,0 +1,40 @@ +// +// "$Id$" +// +// Check button widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Check_Button.H> + +// A subclass of Fl_Button that always draws as a diamond box. This +// diamond is smaller than the widget size and can be surchecked by +// another box type, for compatability with Forms. + +Fl_Check_Button::Fl_Check_Button(int X, int Y, int W, int H, const char *l) +: Fl_Light_Button(X, Y, W, H, l) { + box(FL_NO_BOX); + down_box(FL_DOWN_BOX); + selection_color(FL_FOREGROUND_COLOR); +} diff --git a/Utilities/FLTK/src/Fl_Choice.cxx b/Utilities/FLTK/src/Fl_Choice.cxx new file mode 100644 index 0000000000..6361e03a45 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Choice.cxx @@ -0,0 +1,162 @@ +// +// "$Id$" +// +// Choice widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Choice.H> +#include <FL/fl_draw.H> + +// Emulates the Forms choice widget. This is almost exactly the same +// as an Fl_Menu_Button. The only difference is the appearance of the +// button: it draws the text of the current pick and a down-arrow. + +void Fl_Choice::draw() { + int dx = Fl::box_dx(FL_DOWN_BOX); + int dy = Fl::box_dy(FL_DOWN_BOX); + int H = h() - 2 * dy; + int W = (H > 20) ? 20 : H; + int X = x() + w() - W - dx; + int Y = y() + dy; + int w1 = (W - 4) / 3; if (w1 < 1) w1 = 1; + int x1 = X + (W - 2 * w1 - 1) / 2; + int y1 = Y + (H - w1 - 1) / 2; + + if (Fl::scheme()) { + draw_box(FL_UP_BOX, color()); + + fl_color(active_r() ? labelcolor() : fl_inactive(labelcolor())); + fl_polygon(x1, y1 + 3, x1 + w1, y1 + w1 + 3, x1 + 2 * w1, y1 + 3); + fl_polygon(x1, y1 + 1, x1 + w1, y1 - w1 + 1, x1 + 2 * w1, y1 + 1); + } else { + draw_box(FL_DOWN_BOX, color()); + draw_box(FL_UP_BOX,X,Y,W,H,FL_GRAY); + + fl_color(active_r() ? labelcolor() : fl_inactive(labelcolor())); + fl_polygon(x1, y1, x1 + w1, y1 + w1, x1 + 2 * w1, y1); + } + + W += 2 * dx; + + if (mvalue()) { + Fl_Menu_Item m = *mvalue(); + if (active_r()) m.activate(); else m.deactivate(); + + // ERCO + int xx = x() + dx, yy = y() + dy + 1, ww = w() - W, hh = H - 2; + + fl_clip(xx, yy, ww, hh); + + if ( Fl::scheme()) { + Fl_Label l; + l.value = m.text; + l.image = 0; + l.deimage = 0; + l.type = m.labeltype_; + l.font = m.labelsize_ || m.labelfont_ ? m.labelfont_ : uchar(textfont()); + l.size = m.labelsize_ ? m.labelsize_ : textsize(); + l.color= m.labelcolor_ ? m.labelcolor_ : textcolor(); + if (!m.active()) l.color = fl_inactive((Fl_Color)l.color); + fl_draw_shortcut = 2; // hack value to make '&' disappear + l.draw(xx+3, yy, ww>6 ? ww-6 : 0, hh, FL_ALIGN_LEFT); + fl_draw_shortcut = 0; + if ( Fl::focus() == this ) draw_focus(box(), xx, yy, ww, hh); + } + else { + fl_draw_shortcut = 2; // hack value to make '&' disappear + m.draw(xx, yy, ww, hh, this, Fl::focus() == this); + fl_draw_shortcut = 0; + } + + fl_pop_clip(); + } + + draw_label(); +} + +Fl_Choice::Fl_Choice(int X, int Y, int W, int H, const char *l) +: Fl_Menu_(X,Y,W,H,l) { + align(FL_ALIGN_LEFT); + when(FL_WHEN_RELEASE); + textfont(FL_HELVETICA); + box(FL_FLAT_BOX); + down_box(FL_BORDER_BOX); + color(FL_BACKGROUND2_COLOR); +} + +int Fl_Choice::value(const Fl_Menu_Item *v) { + if (!Fl_Menu_::value(v)) return 0; + redraw(); + return 1; +} + +int Fl_Choice::value(int v) { + if (v == -1) return value((const Fl_Menu_Item *)0); + if (v < 0 || v >= (size() - 1)) return 0; + if (!Fl_Menu_::value(v)) return 0; + redraw(); + return 1; +} + +int Fl_Choice::handle(int e) { + if (!menu() || !menu()->text) return 0; + const Fl_Menu_Item* v; + switch (e) { + case FL_ENTER: + case FL_LEAVE: + return 1; + + case FL_KEYBOARD: + if (Fl::event_key() != ' ' || + (Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) return 0; + case FL_PUSH: + if (Fl::visible_focus()) Fl::focus(this); + J1: + v = menu()->pulldown(x(), y(), w(), h(), mvalue(), this); + if (!v || v->submenu()) return 1; + if (v != mvalue()) redraw(); + picked(v); + return 1; + case FL_SHORTCUT: + if (Fl_Widget::test_shortcut()) goto J1; + v = menu()->test_shortcut(); + if (!v) return 0; + if (v != mvalue()) redraw(); + picked(v); + return 1; + case FL_FOCUS: + case FL_UNFOCUS: + if (Fl::visible_focus()) { + redraw(); + return 1; + } else return 0; + default: + return 0; + } +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Clock.cxx b/Utilities/FLTK/src/Fl_Clock.cxx new file mode 100644 index 0000000000..edb6749c4c --- /dev/null +++ b/Utilities/FLTK/src/Fl_Clock.cxx @@ -0,0 +1,173 @@ +// +// "$Id$" +// +// Clock widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Clock.H> +#include <FL/fl_draw.H> +#include <math.h> +#include <time.h> +#ifndef WIN32 +# include <sys/time.h> +#endif /* !WIN32 */ + +// Original clock display written by Paul Haeberli at SGI. +// Modifications by Mark Overmars for Forms +// Further changes by Bill Spitzak for fltk + +const float hourhand[4][2] = {{-0.5f, 0}, {0, 1.5f}, {0.5f, 0}, {0, -7.0f}}; +const float minhand[4][2] = {{-0.5f, 0}, {0, 1.5f}, {0.5f, 0}, {0, -11.5f}}; +const float sechand[4][2] = {{-0.1f, 0}, {0, 2.0f}, {0.1f, 0}, {0, -11.5f}}; + +static void drawhand(double ang,const float v[][2],Fl_Color fill,Fl_Color line) +{ + fl_push_matrix(); + fl_rotate(ang); + fl_color(fill); fl_begin_polygon(); + int i; for (i=0; i<4; i++) fl_vertex(v[i][0],v[i][1]); fl_end_polygon(); + fl_color(line); fl_begin_loop(); + for (i=0; i<4; i++) fl_vertex(v[i][0],v[i][1]); fl_end_loop(); + fl_pop_matrix(); +} + +void Fl_Clock_Output::drawhands(Fl_Color fill, Fl_Color line) { + drawhand(-360*(hour()+minute()/60.0)/12, hourhand, fill, line); + drawhand(-360*(minute()+second()/60.0)/60, minhand, fill, line); + drawhand(-360*(second()/60.0), sechand, fill, line); +} + +static void rect(double x, double y, double w, double h) { + double r = x+w; + double t = y+h; + fl_begin_polygon(); + fl_vertex(x, y); + fl_vertex(r, y); + fl_vertex(r, t); + fl_vertex(x, t); + fl_end_polygon(); +} + +void Fl_Clock_Output::draw(int X, int Y, int W, int H) { + Fl_Color box_color = type()==FL_ROUND_CLOCK ? FL_GRAY : color(); + Fl_Color shadow_color = fl_color_average(box_color, FL_BLACK, 0.5); + draw_box(box(), X, Y, W, H, box_color); + fl_push_matrix(); + fl_translate(X+W/2.0-.5, Y+H/2.0-.5); + fl_scale((W-1)/28.0, (H-1)/28.0); + if (type() == FL_ROUND_CLOCK) { + fl_color(color()); + fl_begin_polygon(); fl_circle(0,0,14); fl_end_polygon(); + fl_color(FL_FOREGROUND_COLOR); + fl_begin_loop(); fl_circle(0,0,14); fl_end_loop(); + } + // draw the shadows: + fl_push_matrix(); + fl_translate(0.60, 0.60); + drawhands(shadow_color, shadow_color); + fl_pop_matrix(); + // draw the tick marks: + fl_push_matrix(); + fl_color(FL_FOREGROUND_COLOR); // color was 52 + for (int i=0; i<12; i++) { + if (i==6) rect(-0.5, 9, 1, 2); + else if (i==3 || i==0 || i== 9) rect(-0.5, 9.5, 1, 1); + else rect(-0.25, 9.5, .5, 1); + fl_rotate(-30); + } + fl_pop_matrix(); + // draw the hands: + drawhands(selection_color(), FL_FOREGROUND_COLOR); // color was 54 + fl_pop_matrix(); +} + +void Fl_Clock_Output::draw() { + draw(x(), y(), w(), h()); + draw_label(); +} + +void Fl_Clock_Output::value(int H, int m, int s) { + if (H!=hour_ || m!=minute_ || s!=second_) { + hour_ = H; minute_ = m; second_ = s; + value_ = (H * 60 + m) * 60 + s; + damage(FL_DAMAGE_CHILD); + } +} + +void Fl_Clock_Output::value(ulong v) { + value_ = v; + struct tm *timeofday; + // Some platforms, notably Windows, now use a 64-bit time_t value... + time_t vv = (time_t)v; + timeofday = localtime(&vv); + value(timeofday->tm_hour, timeofday->tm_min, timeofday->tm_sec); +} + +Fl_Clock_Output::Fl_Clock_Output(int X, int Y, int W, int H, const char *l) +: Fl_Widget(X, Y, W, H, l) { + box(FL_UP_BOX); + selection_color(fl_gray_ramp(5)); + align(FL_ALIGN_BOTTOM); + hour_ = 0; + minute_ = 0; + second_ = 0; + value_ = 0; +} + +//////////////////////////////////////////////////////////////// + +Fl_Clock::Fl_Clock(int X, int Y, int W, int H, const char *l) + : Fl_Clock_Output(X, Y, W, H, l) {} + +Fl_Clock::Fl_Clock(uchar t, int X, int Y, int W, int H, const char *l) + : Fl_Clock_Output(X, Y, W, H, l) { + type(t); + box(t==FL_ROUND_CLOCK ? FL_NO_BOX : FL_UP_BOX); +} + +static void tick(void *v) { + ((Fl_Clock*)v)->value(time(0)); + Fl::add_timeout(1.0, tick, v); +} + +int Fl_Clock::handle(int event) { + switch (event) { + case FL_SHOW: + tick(this); + break; + case FL_HIDE: + Fl::remove_timeout(tick, this); + break; + } + return Fl_Clock_Output::handle(event); +} + +Fl_Clock::~Fl_Clock() { + Fl::remove_timeout(tick, this); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Color_Chooser.cxx b/Utilities/FLTK/src/Fl_Color_Chooser.cxx new file mode 100644 index 0000000000..d97b2b577f --- /dev/null +++ b/Utilities/FLTK/src/Fl_Color_Chooser.cxx @@ -0,0 +1,529 @@ +// +// "$Id$" +// +// Color chooser for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Color_Chooser.H> +#include <FL/fl_draw.H> +#include <FL/math.h> +#include <stdio.h> + +// Besides being a useful object on it's own, the Fl_Color_Chooser was +// an attempt to make a complex composite object that could be easily +// imbedded into a user interface. If you wish to make complex objects +// of your own, be sure to read this code. + +// The function fl_color_chooser() creates a window containing a color +// chooser and a few buttons and current-color indicators. It is an +// easier interface for simple programs that just need a color. + +// The "hue box" can be a circle or rectilinear. +// You get a circle by defining this: +#define CIRCLE 1 +// And the "hue box" can auto-update when the value changes +// you get this by defining this: +#define UPDATE_HUE_BOX 1 + +void Fl_Color_Chooser::hsv2rgb( + double H, double S, double V, double& R, double& G, double& B) { + if (S < 5.0e-6) { + R = G = B = V; + } else { + int i = (int)H; + double f = H - (float)i; + double p1 = V*(1.0-S); + double p2 = V*(1.0-S*f); + double p3 = V*(1.0-S*(1.0-f)); + switch (i) { + case 0: R = V; G = p3; B = p1; break; + case 1: R = p2; G = V; B = p1; break; + case 2: R = p1; G = V; B = p3; break; + case 3: R = p1; G = p2; B = V; break; + case 4: R = p3; G = p1; B = V; break; + case 5: R = V; G = p1; B = p2; break; + } + } +} + +void Fl_Color_Chooser::rgb2hsv( + double R, double G, double B, double& H, double& S, double& V) { + double maxv = R > G ? R : G; if (B > maxv) maxv = B; + V = maxv; + if (maxv>0) { + double minv = R < G ? R : G; if (B < minv) minv = B; + S = 1.0 - double(minv)/maxv; + if (maxv > minv) { + if (maxv == R) {H = (G-B)/double(maxv-minv); if (H<0) H += 6.0;} + else if (maxv == G) H = 2.0+(B-R)/double(maxv-minv); + else H = 4.0+(R-G)/double(maxv-minv); + } + } +} + +enum {M_RGB, M_BYTE, M_HEX, M_HSV}; // modes +static Fl_Menu_Item mode_menu[] = { + {"rgb"}, + {"byte"}, + {"hex"}, + {"hsv"}, + {0} +}; + +int Flcc_Value_Input::format(char* buf) { + Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent(); + if (c->mode() == M_HEX) return sprintf(buf,"0x%02X", int(value())); + else return Fl_Valuator::format(buf); +} + +void Fl_Color_Chooser::set_valuators() { + switch (mode()) { + case M_RGB: + rvalue.range(0,1); rvalue.step(1,1000); rvalue.value(r_); + gvalue.range(0,1); gvalue.step(1,1000); gvalue.value(g_); + bvalue.range(0,1); bvalue.step(1,1000); bvalue.value(b_); + break; + case M_BYTE: + case M_HEX: + rvalue.range(0,255); rvalue.step(1); rvalue.value(int(255*r_+.5)); + gvalue.range(0,255); gvalue.step(1); gvalue.value(int(255*g_+.5)); + bvalue.range(0,255); bvalue.step(1); bvalue.value(int(255*b_+.5)); + break; + case M_HSV: + rvalue.range(0,6); rvalue.step(1,1000); rvalue.value(hue_); + gvalue.range(0,1); gvalue.step(1,1000); gvalue.value(saturation_); + bvalue.range(0,1); bvalue.step(1,1000); bvalue.value(value_); + break; + } +} + +int Fl_Color_Chooser::rgb(double R, double G, double B) { + if (R == r_ && G == g_ && B == b_) return 0; + r_ = R; g_ = G; b_ = B; + double ph = hue_; + double ps = saturation_; + double pv = value_; + rgb2hsv(R,G,B,hue_,saturation_,value_); + set_valuators(); + set_changed(); + if (value_ != pv) { +#ifdef UPDATE_HUE_BOX + huebox.damage(FL_DAMAGE_SCROLL); +#endif + valuebox.damage(FL_DAMAGE_EXPOSE);} + if (hue_ != ph || saturation_ != ps) { + huebox.damage(FL_DAMAGE_EXPOSE); + valuebox.damage(FL_DAMAGE_SCROLL); + } + return 1; +} + +int Fl_Color_Chooser::hsv(double H, double S, double V) { + H = fmod(H,6.0); if (H < 0.0) H += 6.0; + if (S < 0.0) S = 0.0; else if (S > 1.0) S = 1.0; + if (V < 0.0) V = 0.0; else if (V > 1.0) V = 1.0; + if (H == hue_ && S == saturation_ && V == value_) return 0; + double ph = hue_; + double ps = saturation_; + double pv = value_; + hue_ = H; saturation_ = S; value_ = V; + if (value_ != pv) { +#ifdef UPDATE_HUE_BOX + huebox.damage(FL_DAMAGE_SCROLL); +#endif + valuebox.damage(FL_DAMAGE_EXPOSE);} + if (hue_ != ph || saturation_ != ps) { + huebox.damage(FL_DAMAGE_EXPOSE); + valuebox.damage(FL_DAMAGE_SCROLL); + } + hsv2rgb(H,S,V,r_,g_,b_); + set_valuators(); + set_changed(); + return 1; +} + +//////////////////////////////////////////////////////////////// + +static void tohs(double x, double y, double& h, double& s) { +#ifdef CIRCLE + x = 2*x-1; + y = 1-2*y; + s = sqrt(x*x+y*y); if (s > 1.0) s = 1.0; + h = (3.0/M_PI)*atan2(y,x); + if (h<0) h += 6.0; +#else + h = fmod(6.0*x,6.0); if (h < 0.0) h += 6.0; + s = 1.0-y; if (s < 0.0) s = 0.0; else if (s > 1.0) s = 1.0; +#endif +} + +int Flcc_HueBox::handle(int e) { + static double ih, is; + Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent(); + switch (e) { + case FL_PUSH: + if (Fl::visible_focus()) { + Fl::focus(this); + redraw(); + } + ih = c->hue(); + is = c->saturation(); + case FL_DRAG: { + double Xf, Yf, H, S; + Xf = (Fl::event_x()-x()-Fl::box_dx(box()))/double(w()-Fl::box_dw(box())); + Yf = (Fl::event_y()-y()-Fl::box_dy(box()))/double(h()-Fl::box_dh(box())); + tohs(Xf, Yf, H, S); + if (fabs(H-ih) < 3*6.0/w()) H = ih; + if (fabs(S-is) < 3*1.0/h()) S = is; + if (Fl::event_state(FL_CTRL)) H = ih; + if (c->hsv(H, S, c->value())) c->do_callback(); + } return 1; + case FL_FOCUS : + case FL_UNFOCUS : + if (Fl::visible_focus()) { + redraw(); + return 1; + } + else return 1; + case FL_KEYBOARD : + return handle_key(Fl::event_key()); + default: + return 0; + } +} + +static void generate_image(void* vv, int X, int Y, int W, uchar* buf) { + Flcc_HueBox* v = (Flcc_HueBox*)vv; + int iw = v->w()-Fl::box_dw(v->box()); + double Yf = double(Y)/(v->h()-Fl::box_dh(v->box())); +#ifdef UPDATE_HUE_BOX + const double V = ((Fl_Color_Chooser*)(v->parent()))->value(); +#else + const double V = 1.0; +#endif + for (int x = X; x < X+W; x++) { + double Xf = double(x)/iw; + double H,S; tohs(Xf,Yf,H,S); + double r,g,b; + Fl_Color_Chooser::hsv2rgb(H,S,V,r,g,b); + *buf++ = uchar(255*r+.5); + *buf++ = uchar(255*g+.5); + *buf++ = uchar(255*b+.5); + } +} + +int Flcc_HueBox::handle_key(int key) { + int w1 = w()-Fl::box_dw(box())-6; + int h1 = h()-Fl::box_dh(box())-6; + Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent(); + +#ifdef CIRCLE + int X = int(.5*(cos(c->hue()*(M_PI/3.0))*c->saturation()+1) * w1); + int Y = int(.5*(1-sin(c->hue()*(M_PI/3.0))*c->saturation()) * h1); +#else + int X = int(c->hue()/6.0*w1); + int Y = int((1-c->saturation())*h1); +#endif + + switch (key) { + case FL_Up : + Y -= 3; + break; + case FL_Down : + Y += 3; + break; + case FL_Left : + X -= 3; + break; + case FL_Right : + X += 3; + break; + default : + return 0; + } + + double Xf, Yf, H, S; + Xf = (double)X/(double)w1; + Yf = (double)Y/(double)h1; + tohs(Xf, Yf, H, S); + if (c->hsv(H, S, c->value())) c->do_callback(); + + return 1; +} + +void Flcc_HueBox::draw() { + if (damage()&FL_DAMAGE_ALL) draw_box(); + int x1 = x()+Fl::box_dx(box()); + int yy1 = y()+Fl::box_dy(box()); + int w1 = w()-Fl::box_dw(box()); + int h1 = h()-Fl::box_dh(box()); + if (damage() == FL_DAMAGE_EXPOSE) fl_clip(x1+px,yy1+py,6,6); + fl_draw_image(generate_image, this, x1, yy1, w1, h1); + if (damage() == FL_DAMAGE_EXPOSE) fl_pop_clip(); + Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent(); +#ifdef CIRCLE + int X = int(.5*(cos(c->hue()*(M_PI/3.0))*c->saturation()+1) * (w1-6)); + int Y = int(.5*(1-sin(c->hue()*(M_PI/3.0))*c->saturation()) * (h1-6)); +#else + int X = int(c->hue()/6.0*(w1-6)); + int Y = int((1-c->saturation())*(h1-6)); +#endif + if (X < 0) X = 0; else if (X > w1-6) X = w1-6; + if (Y < 0) Y = 0; else if (Y > h1-6) Y = h1-6; + // fl_color(c->value()>.75 ? FL_BLACK : FL_WHITE); + draw_box(FL_UP_BOX,x1+X,yy1+Y,6,6,Fl::focus() == this ? FL_FOREGROUND_COLOR : FL_GRAY); + px = X; py = Y; +} + +//////////////////////////////////////////////////////////////// + +int Flcc_ValueBox::handle(int e) { + static double iv; + Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent(); + switch (e) { + case FL_PUSH: + if (Fl::visible_focus()) { + Fl::focus(this); + redraw(); + } + iv = c->value(); + case FL_DRAG: { + double Yf; + Yf = 1-(Fl::event_y()-y()-Fl::box_dy(box()))/double(h()-Fl::box_dh(box())); + if (fabs(Yf-iv)<(3*1.0/h())) Yf = iv; + if (c->hsv(c->hue(),c->saturation(),Yf)) c->do_callback(); + } return 1; + case FL_FOCUS : + case FL_UNFOCUS : + if (Fl::visible_focus()) { + redraw(); + return 1; + } + else return 1; + case FL_KEYBOARD : + return handle_key(Fl::event_key()); + default: + return 0; + } +} + +static double tr, tg, tb; +static void generate_vimage(void* vv, int X, int Y, int W, uchar* buf) { + Flcc_ValueBox* v = (Flcc_ValueBox*)vv; + double Yf = 255*(1.0-double(Y)/(v->h()-Fl::box_dh(v->box()))); + uchar r = uchar(tr*Yf+.5); + uchar g = uchar(tg*Yf+.5); + uchar b = uchar(tb*Yf+.5); + for (int x = X; x < X+W; x++) { + *buf++ = r; *buf++ = g; *buf++ = b; + } +} + +void Flcc_ValueBox::draw() { + if (damage()&FL_DAMAGE_ALL) draw_box(); + Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent(); + c->hsv2rgb(c->hue(),c->saturation(),1.0,tr,tg,tb); + int x1 = x()+Fl::box_dx(box()); + int yy1 = y()+Fl::box_dy(box()); + int w1 = w()-Fl::box_dw(box()); + int h1 = h()-Fl::box_dh(box()); + if (damage() == FL_DAMAGE_EXPOSE) fl_clip(x1,yy1+py,w1,6); + fl_draw_image(generate_vimage, this, x1, yy1, w1, h1); + if (damage() == FL_DAMAGE_EXPOSE) fl_pop_clip(); + int Y = int((1-c->value()) * (h1-6)); + if (Y < 0) Y = 0; else if (Y > h1-6) Y = h1-6; + draw_box(FL_UP_BOX,x1,yy1+Y,w1,6,Fl::focus() == this ? FL_FOREGROUND_COLOR : FL_GRAY); + py = Y; +} + +int Flcc_ValueBox::handle_key(int key) { + int h1 = h()-Fl::box_dh(box())-6; + Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent(); + + int Y = int((1-c->value()) * h1); + if (Y < 0) Y = 0; else if (Y > h1) Y = h1; + + switch (key) { + case FL_Up : + Y -= 3; + break; + case FL_Down : + Y += 3; + break; + default : + return 0; + } + + double Yf; + Yf = 1-((double)Y/(double)h1); + if (c->hsv(c->hue(),c->saturation(),Yf)) c->do_callback(); + + return 1; +} + +//////////////////////////////////////////////////////////////// + +void Fl_Color_Chooser::rgb_cb(Fl_Widget* o, void*) { + Fl_Color_Chooser* c = (Fl_Color_Chooser*)(o->parent()); + double R = c->rvalue.value(); + double G = c->gvalue.value(); + double B = c->bvalue.value(); + if (c->mode() == M_HSV) { + if (c->hsv(R,G,B)) c->do_callback(); + return; + } + if (c->mode() != M_RGB) { + R = R/255; + G = G/255; + B = B/255; + } + if (c->rgb(R,G,B)) c->do_callback(); +} + +void Fl_Color_Chooser::mode_cb(Fl_Widget* o, void*) { + Fl_Color_Chooser* c = (Fl_Color_Chooser*)(o->parent()); + // force them to redraw even if value is the same: + c->rvalue.value(-1); + c->gvalue.value(-1); + c->bvalue.value(-1); + c->set_valuators(); +} + +//////////////////////////////////////////////////////////////// + +Fl_Color_Chooser::Fl_Color_Chooser(int X, int Y, int W, int H, const char* L) + : Fl_Group(0,0,195,115,L), + huebox(0,0,115,115), + valuebox(115,0,20,115), + choice(140,0,55,25), + rvalue(140,30,55,25), + gvalue(140,60,55,25), + bvalue(140,90,55,25), + resize_box(0,0,115,115) +{ + end(); + resizable(resize_box); + resize(X,Y,W,H); + r_ = g_ = b_ = 0; + hue_ = 0.0; + saturation_ = 0.0; + value_ = 0.0; + huebox.box(FL_DOWN_FRAME); + valuebox.box(FL_DOWN_FRAME); + choice.menu(mode_menu); + set_valuators(); + rvalue.callback(rgb_cb); + gvalue.callback(rgb_cb); + bvalue.callback(rgb_cb); + choice.callback(mode_cb); + choice.box(FL_THIN_UP_BOX); + choice.textfont(FL_HELVETICA_BOLD_ITALIC); +} + +//////////////////////////////////////////////////////////////// +// fl_color_chooser(): + +#include <FL/Fl_Window.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Return_Button.H> + +class ColorChip : public Fl_Widget { + void draw(); +public: + uchar r,g,b; + ColorChip(int X, int Y, int W, int H) : Fl_Widget(X,Y,W,H) { + box(FL_ENGRAVED_FRAME);} +}; + +void ColorChip::draw() { + if (damage()&FL_DAMAGE_ALL) draw_box(); + fl_rectf(x()+Fl::box_dx(box()), + y()+Fl::box_dy(box()), + w()-Fl::box_dw(box()), + h()-Fl::box_dh(box()),r,g,b); +} + +static void chooser_cb(Fl_Object* o, void* vv) { + Fl_Color_Chooser* c = (Fl_Color_Chooser*)o; + ColorChip* v = (ColorChip*)vv; + v->r = uchar(255*c->r()+.5); + v->g = uchar(255*c->g()+.5); + v->b = uchar(255*c->b()+.5); + v->damage(FL_DAMAGE_EXPOSE); +} + +extern const char* fl_ok; +extern const char* fl_cancel; + +int fl_color_chooser(const char* name, double& r, double& g, double& b) { + Fl_Window window(215,200,name); + Fl_Color_Chooser chooser(10, 10, 195, 115); + ColorChip ok_color(10, 130, 95, 25); + Fl_Return_Button ok_button(10, 165, 95, 25, fl_ok); + ColorChip cancel_color(110, 130, 95, 25); + cancel_color.r = uchar(255*r+.5); ok_color.r = cancel_color.r; + ok_color.g = cancel_color.g = uchar(255*g+.5); + ok_color.b = cancel_color.b = uchar(255*b+.5); + Fl_Button cancel_button(110, 165, 95, 25, fl_cancel); + window.resizable(chooser); + chooser.rgb(r,g,b); + chooser.callback(chooser_cb, &ok_color); + window.end(); + window.set_modal(); + window.hotspot(window); + window.show(); + while (window.shown()) { + Fl::wait(); + for (;;) { + Fl_Widget* o = Fl::readqueue(); + if (!o) break; + if (o == &ok_button) { + r = chooser.r(); + g = chooser.g(); + b = chooser.b(); + return 1; + } + if (o == &window || o == &cancel_button) return 0; + } + } + return 0; +} + +int fl_color_chooser(const char* name, uchar& r, uchar& g, uchar& b) { + double dr = r/255.0; + double dg = g/255.0; + double db = b/255.0; + if (fl_color_chooser(name,dr,dg,db)) { + r = uchar(255*dr+.5); + g = uchar(255*dg+.5); + b = uchar(255*db+.5); + return 1; + } + return 0; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Counter.cxx b/Utilities/FLTK/src/Fl_Counter.cxx new file mode 100644 index 0000000000..875171541a --- /dev/null +++ b/Utilities/FLTK/src/Fl_Counter.cxx @@ -0,0 +1,197 @@ +// +// "$Id$" +// +// Counter widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Counter.H> +#include <FL/fl_draw.H> + +void Fl_Counter::draw() { + int i; Fl_Boxtype boxtype[5]; + Fl_Color selcolor; + + boxtype[0] = box(); + if (boxtype[0] == FL_UP_BOX) boxtype[0] = FL_DOWN_BOX; + if (boxtype[0] == FL_THIN_UP_BOX) boxtype[0] = FL_THIN_DOWN_BOX; + for (i=1; i<5; i++) + if (mouseobj == i) + boxtype[i] = fl_down(box()); + else + boxtype[i] = box(); + + int xx[5], ww[5]; + if (type() == FL_NORMAL_COUNTER) { + int W = w()*15/100; + xx[1] = x(); ww[1] = W; + xx[2] = x()+1*W; ww[2] = W; + xx[0] = x()+2*W; ww[0] = w()-4*W; + xx[3] = x()+w()-2*W; ww[3] = W; + xx[4] = x()+w()-1*W; ww[4] = W; + } else { + int W = w()*20/100; + xx[1] = 0; ww[1] = 0; + xx[2] = x(); ww[2] = W; + xx[0] = x()+W; ww[0] = w()-2*W; + xx[3] = x()+w()-1*W; ww[3] = W; + xx[4] = 0; ww[4] = 0; + } + + draw_box(boxtype[0], xx[0], y(), ww[0], h(), FL_BACKGROUND2_COLOR); + fl_font(textfont(), textsize()); + fl_color(active_r() ? textcolor() : fl_inactive(textcolor())); + char str[128]; format(str); + fl_draw(str, xx[0], y(), ww[0], h(), FL_ALIGN_CENTER); + if (Fl::focus() == this) draw_focus(boxtype[0], xx[0], y(), ww[0], h()); + if (!(damage()&FL_DAMAGE_ALL)) return; // only need to redraw text + + if (active_r()) + selcolor = labelcolor(); + else + selcolor = fl_inactive(labelcolor()); + + if (type() == FL_NORMAL_COUNTER) { + draw_box(boxtype[1], xx[1], y(), ww[1], h(), color()); + fl_draw_symbol("@-4<<", xx[1], y(), ww[1], h(), selcolor); + } + draw_box(boxtype[2], xx[2], y(), ww[2], h(), color()); + fl_draw_symbol("@-4<", xx[2], y(), ww[2], h(), selcolor); + draw_box(boxtype[3], xx[3], y(), ww[3], h(), color()); + fl_draw_symbol("@-4>", xx[3], y(), ww[3], h(), selcolor); + if (type() == FL_NORMAL_COUNTER) { + draw_box(boxtype[4], xx[4], y(), ww[4], h(), color()); + fl_draw_symbol("@-4>>", xx[4], y(), ww[4], h(), selcolor); + } +} + +void Fl_Counter::increment_cb() { + if (!mouseobj) return; + double v = value(); + switch (mouseobj) { + case 1: v -= lstep_; break; + case 2: v = increment(v, -1); break; + case 3: v = increment(v, 1); break; + case 4: v += lstep_; break; + } + handle_drag(clamp(round(v))); +} + +#define INITIALREPEAT .5 +#define REPEAT .1 + +void Fl_Counter::repeat_callback(void* v) { + Fl_Counter* b = (Fl_Counter*)v; + if (b->mouseobj) { + Fl::add_timeout(REPEAT, repeat_callback, b); + b->increment_cb(); + } +} + +int Fl_Counter::calc_mouseobj() { + if (type() == FL_NORMAL_COUNTER) { + int W = w()*15/100; + if (Fl::event_inside(x(), y(), W, h())) return 1; + if (Fl::event_inside(x()+W, y(), W, h())) return 2; + if (Fl::event_inside(x()+w()-2*W, y(), W, h())) return 3; + if (Fl::event_inside(x()+w()-W, y(), W, h())) return 4; + } else { + int W = w()*20/100; + if (Fl::event_inside(x(), y(), W, h())) return 2; + if (Fl::event_inside(x()+w()-W, y(), W, h())) return 3; + } + return -1; +} + +int Fl_Counter::handle(int event) { + int i; + switch (event) { + case FL_RELEASE: + if (mouseobj) { + Fl::remove_timeout(repeat_callback, this); + mouseobj = 0; + redraw(); + } + handle_release(); + return 1; + case FL_PUSH: + if (Fl::visible_focus()) Fl::focus(this); + handle_push(); + case FL_DRAG: + i = calc_mouseobj(); + if (i != mouseobj) { + Fl::remove_timeout(repeat_callback, this); + mouseobj = (uchar)i; + if (i) Fl::add_timeout(INITIALREPEAT, repeat_callback, this); + increment_cb(); + redraw(); + } + return 1; + case FL_KEYBOARD : + switch (Fl::event_key()) { + case FL_Left: + handle_drag(clamp(increment(value(),-1))); + return 1; + case FL_Right: + handle_drag(clamp(increment(value(),1))); + return 1; + default: + return 0; + } + // break not required because of switch... + case FL_FOCUS : + case FL_UNFOCUS : + if (Fl::visible_focus()) { + redraw(); + return 1; + } else return 0; + case FL_ENTER : + case FL_LEAVE : + return 1; + default: + return 0; + } +} + +Fl_Counter::~Fl_Counter() { + Fl::remove_timeout(repeat_callback, this); +} + +Fl_Counter::Fl_Counter(int X, int Y, int W, int H, const char* l) + : Fl_Valuator(X, Y, W, H, l) { + box(FL_UP_BOX); + selection_color(FL_INACTIVE_COLOR); // was FL_BLUE + align(FL_ALIGN_BOTTOM); + bounds(-1000000.0, 1000000.0); + Fl_Valuator::step(1, 10); + lstep_ = 1.0; + mouseobj = 0; + textfont_ = FL_HELVETICA; + textsize_ = (uchar)FL_NORMAL_SIZE; + textcolor_ = FL_FOREGROUND_COLOR; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Dial.cxx b/Utilities/FLTK/src/Fl_Dial.cxx new file mode 100644 index 0000000000..de77cb2682 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Dial.cxx @@ -0,0 +1,140 @@ +// +// "$Id$" +// +// Circular dial widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Dial.H> +#include <FL/fl_draw.H> +#include <stdlib.h> +#include <FL/math.h> + +// All angles are measured with 0 to the right and counter-clockwise + +void Fl_Dial::draw(int X, int Y, int W, int H) { + if (damage()&FL_DAMAGE_ALL) draw_box(box(), X, Y, W, H, color()); + X += Fl::box_dx(box()); + Y += Fl::box_dy(box()); + W -= Fl::box_dw(box()); + H -= Fl::box_dh(box()); + double angle = (a2-a1)*(value()-minimum())/(maximum()-minimum()) + a1; + if (type() == FL_FILL_DIAL) { + // foo: draw this nicely in certain round box types + int foo = (box() > _FL_ROUND_UP_BOX && Fl::box_dx(box())); + if (foo) {X--; Y--; W+=2; H+=2;} + fl_color(color()); + fl_pie(X, Y, W, H, 270-a1, angle > a1 ? 360+270-angle : 270-360-angle); + fl_color(selection_color()); + fl_pie(X, Y, W, H, 270-angle, 270-a1); + if (foo) { + fl_color(FL_FOREGROUND_COLOR); + fl_arc(X, Y, W, H, 0, 360); + } + return; + } + if (!(damage()&FL_DAMAGE_ALL)) { + fl_color(color()); + fl_pie(X+1, Y+1, W-2, H-2, 0, 360); + } + fl_push_matrix(); + fl_translate(X+W/2-.5, Y+H/2-.5); + fl_scale(W-1, H-1); + fl_rotate(45-angle); + fl_color(selection_color()); + if (type()) { // FL_LINE_DIAL + fl_begin_polygon(); + fl_vertex(0.0, 0.0); + fl_vertex(-0.04, 0.0); + fl_vertex(-0.25, 0.25); + fl_vertex(0.0, 0.04); + fl_end_polygon(); + fl_color(FL_FOREGROUND_COLOR); + fl_begin_loop(); + fl_vertex(0.0, 0.0); + fl_vertex(-0.04, 0.0); + fl_vertex(-0.25, 0.25); + fl_vertex(0.0, 0.04); + fl_end_loop(); + } else { + fl_begin_polygon(); fl_circle(-0.20, 0.20, 0.07); fl_end_polygon(); + fl_color(FL_FOREGROUND_COLOR); + fl_begin_loop(); fl_circle(-0.20, 0.20, 0.07); fl_end_loop(); + } + fl_pop_matrix(); +} + +void Fl_Dial::draw() { + draw(x(), y(), w(), h()); + draw_label(); +} + +int Fl_Dial::handle(int event, int X, int Y, int W, int H) { + switch (event) { + case FL_PUSH: + handle_push(); + case FL_DRAG: { + int mx = (Fl::event_x()-X-W/2)*H; + int my = (Fl::event_y()-Y-H/2)*W; + if (!mx && !my) return 1; + double angle = 270-atan2((float)-my, (float)mx)*180/M_PI; + double oldangle = (a2-a1)*(value()-minimum())/(maximum()-minimum()) + a1; + while (angle < oldangle-180) angle += 360; + while (angle > oldangle+180) angle -= 360; + double val; + if ((a1<a2) ? (angle <= a1) : (angle >= a1)) { + val = minimum(); + } else if ((a1<a2) ? (angle >= a2) : (angle <= a2)) { + val = maximum(); + } else { + val = minimum() + (maximum()-minimum())*(angle-a1)/(a2-a1); + } + handle_drag(clamp(round(val))); + } return 1; + case FL_RELEASE: + handle_release(); + return 1; + case FL_ENTER : + case FL_LEAVE : + return 1; + default: + return 0; + } +} + +int Fl_Dial::handle(int e) { + return handle(e, x(), y(), w(), h()); +} + +Fl_Dial::Fl_Dial(int X, int Y, int W, int H, const char* l) + : Fl_Valuator(X, Y, W, H, l) { + box(FL_OVAL_BOX); + selection_color(FL_INACTIVE_COLOR); // was 37 + a1 = 45; + a2 = 315; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Double_Window.cxx b/Utilities/FLTK/src/Fl_Double_Window.cxx new file mode 100644 index 0000000000..fdeffe99de --- /dev/null +++ b/Utilities/FLTK/src/Fl_Double_Window.cxx @@ -0,0 +1,368 @@ +// +// "$Id$" +// +// Double-buffered window code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#include <FL/Fl_Double_Window.H> +#include <FL/x.H> +#include <FL/fl_draw.H> + +// On systems that support double buffering "naturally" the base +// Fl_Window class will probably do double-buffer and this subclass +// does nothing. + +#if USE_XDBE + +#include <X11/extensions/Xdbe.h> + +static int use_xdbe; + +static int can_xdbe() { + static int tried; + if (!tried) { + tried = 1; + int event_base, error_base; + if (!XdbeQueryExtension(fl_display, &event_base, &error_base)) return 0; + Drawable root = RootWindow(fl_display,fl_screen); + int numscreens = 1; + XdbeScreenVisualInfo *a = XdbeGetVisualInfo(fl_display,&root,&numscreens); + if (!a) return 0; + for (int j = 0; j < a->count; j++) + if (a->visinfo[j].visual == fl_visual->visualid + /*&& a->visinfo[j].perflevel > 0*/) {use_xdbe = 1; break;} + XdbeFreeVisualInfo(a); + } + return use_xdbe; +} +#endif + +void Fl_Double_Window::show() { +#if !defined(WIN32) && !defined(__APPLE__) + if (!shown()) { // don't set the background pixel + fl_open_display(); + Fl_X::make_xid(this); + return; + } +#endif + Fl_Window::show(); +} + +#ifdef WIN32 + +// Code used to switch output to an off-screen window. See macros in +// win32.H which save the old state in local variables. + +HDC fl_makeDC(HBITMAP bitmap) { + HDC new_gc = CreateCompatibleDC(fl_gc); + SetTextAlign(new_gc, TA_BASELINE|TA_LEFT); + SetBkMode(new_gc, TRANSPARENT); +#if USE_COLORMAP + if (fl_palette) SelectPalette(new_gc, fl_palette, FALSE); +#endif + SelectObject(new_gc, bitmap); + return new_gc; +} + +void fl_copy_offscreen(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) { + HDC new_gc = CreateCompatibleDC(fl_gc); + int save = SaveDC(new_gc); + SelectObject(new_gc, bitmap); + BitBlt(fl_gc, x, y, w, h, new_gc, srcx, srcy, SRCCOPY); + RestoreDC(new_gc, save); + DeleteDC(new_gc); +} + +extern void fl_restore_clip(); + +#elif defined(__APPLE_QD__) + +GWorldPtr fl_create_offscreen(int w, int h) { + GWorldPtr gw; + Rect bounds; + bounds.left=0; bounds.right=w; bounds.top=0; bounds.bottom=h; + QDErr err = NewGWorld(&gw, 0, &bounds, 0L, 0L, 0); // 'useTempMem' should not be used (says the Carbon port manual) + if ( err == -108 ) + { } +// fl_message( "The application memory is low. Please increase the initial memory assignment.\n" ); + if (err!=noErr || gw==0L) return 0L; + return gw; +} + +void fl_copy_offscreen(int x,int y,int w,int h,GWorldPtr gWorld,int srcx,int srcy) { + Rect src; + if ( !gWorld ) return; + src.top = srcy; src.left = srcx; src.bottom = srcy+h; src.right = srcx+w; + Rect dst; + GrafPtr dstPort; GetPort(&dstPort); + dst.top = y; dst.left = x; dst.bottom = y+h; dst.right = x+w; + RGBColor rgb, oldbg, oldfg; + GetForeColor(&oldfg); + GetBackColor(&oldbg); + rgb.red = 0xffff; rgb.green = 0xffff; rgb.blue = 0xffff; + RGBBackColor( &rgb ); + rgb.red = 0x0000; rgb.green = 0x0000; rgb.blue = 0x0000; + RGBForeColor( &rgb ); + CopyBits(GetPortBitMapForCopyBits(gWorld), GetPortBitMapForCopyBits(dstPort), &src, &dst, srcCopy, 0L); + RGBBackColor(&oldbg); + RGBForeColor(&oldfg); +} + +void fl_delete_offscreen(GWorldPtr gWorld) { + DisposeGWorld(gWorld); +} + +static GrafPtr prevPort; +static GDHandle prevGD; + +void fl_begin_offscreen(GWorldPtr gWorld) { + GetGWorld( &prevPort, &prevGD ); + if ( gWorld ) + { + SetGWorld( gWorld, 0 ); // sets the correct port + PixMapHandle pm = GetGWorldPixMap(gWorld); + Boolean ret = LockPixels(pm); + if ( ret == false ) + { + Rect rect; + GetPortBounds( gWorld, &rect ); + UpdateGWorld( &gWorld, 0, &rect, 0, 0, 0 ); + pm = GetGWorldPixMap( gWorld ); + LockPixels( pm ); + } + fl_window = 0; + } + fl_push_no_clip(); +} + +void fl_end_offscreen() { + GWorldPtr currPort; + GDHandle currGD; + GetGWorld( &currPort, &currGD ); + fl_pop_clip(); + PixMapHandle pm = GetGWorldPixMap(currPort); + UnlockPixels(pm); + SetGWorld( prevPort, prevGD ); + fl_window = GetWindowFromPort( prevPort ); +} + +extern void fl_restore_clip(); + +#elif defined(__APPLE_QUARTZ__) + +Fl_Offscreen fl_create_offscreen(int w, int h) { + void *data = calloc(w*h,4); + CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); + CGContextRef ctx = CGBitmapContextCreate( + data, w, h, 8, w*4, lut, kCGImageAlphaNoneSkipLast); + CGColorSpaceRelease(lut); + return (Fl_Offscreen)ctx; +} + +Fl_Offscreen fl_create_offscreen_with_alpha(int w, int h) { + void *data = calloc(w*h,4); + CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); + CGContextRef ctx = CGBitmapContextCreate( + data, w, h, 8, w*4, lut, kCGImageAlphaPremultipliedLast); + CGColorSpaceRelease(lut); + return (Fl_Offscreen)ctx; +} + +void fl_copy_offscreen(int x,int y,int w,int h,Fl_Offscreen osrc,int srcx,int srcy) { + CGContextRef src = (CGContextRef)osrc; + void *data = CGBitmapContextGetData(src); + int sw = CGBitmapContextGetWidth(src); + int sh = CGBitmapContextGetHeight(src); + CGImageAlphaInfo alpha = CGBitmapContextGetAlphaInfo(src); + CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); + CGDataProviderRef src_bytes = CGDataProviderCreateWithData( 0L, data, sw*sh*4, 0L); + CGImageRef img = CGImageCreate( sw, sh, 8, 4*8, 4*sw, lut, alpha, + src_bytes, 0L, false, kCGRenderingIntentDefault); + // fl_push_clip(); + CGRect rect = { x, y, w, h }; + Fl_X::q_begin_image(rect, srcx, srcy, sw, sh); + CGContextDrawImage(fl_gc, rect, img); + Fl_X::q_end_image(); + CGImageRelease(img); + CGColorSpaceRelease(lut); + CGDataProviderRelease(src_bytes); +} + +void fl_delete_offscreen(Fl_Offscreen ctx) { + if (!ctx) return; + void *data = CGBitmapContextGetData((CGContextRef)ctx); + CGContextRelease((CGContextRef)ctx); + if (!data) return; + free(data); +} + +static CGContextRef prev_gc = 0; +static Window prev_window = 0; + +void fl_begin_offscreen(Fl_Offscreen ctx) { + prev_gc = fl_gc; + prev_window = fl_window; + fl_gc = (CGContextRef)ctx; + fl_window = 0; + //fl_push_no_clip(); + CGContextSaveGState(fl_gc); + Fl_X::q_fill_context(); +} + +void fl_end_offscreen() { + Fl_X::q_release_context(); + //fl_pop_clip(); + fl_gc = prev_gc; + fl_window = prev_window; +} + +extern void fl_restore_clip(); + +#endif + +// Fl_Overlay_Window relies on flush(1) copying the back buffer to the +// front everywhere, even if damage() == 0, thus erasing the overlay, +// and leaving the clip region set to the entire window. + +void Fl_Double_Window::flush() {flush(0);} + +void Fl_Double_Window::flush(int eraseoverlay) { + make_current(); // make sure fl_gc is non-zero + Fl_X *myi = Fl_X::i(this); + if (!myi->other_xid) { +#if USE_XDBE + if (can_xdbe()) myi->other_xid = + XdbeAllocateBackBufferName(fl_display, fl_xid(this), XdbeUndefined); + else +#endif +#ifdef __APPLE_QD__ + if ( ( !QDIsPortBuffered( GetWindowPort(myi->xid) ) ) + || force_doublebuffering_ ) { + myi->other_xid = fl_create_offscreen(w(), h()); + clear_damage(FL_DAMAGE_ALL); + } +#elif defined(__APPLE_QUARTZ__) + if (force_doublebuffering_) { + myi->other_xid = fl_create_offscreen(w(), h()); + clear_damage(FL_DAMAGE_ALL); + } +#else + myi->other_xid = fl_create_offscreen(w(), h()); + clear_damage(FL_DAMAGE_ALL); +#endif + } +#if USE_XDBE + if (use_xdbe) { + // if this is true, copy rather than swap so back buffer is preserved: + int copy = (myi->region || eraseoverlay); + if (myi->backbuffer_bad) { // make sure we do a complete redraw... + if (myi->region) {XDestroyRegion(myi->region); myi->region = 0;} + clear_damage(FL_DAMAGE_ALL); + } + if (damage()) { + fl_clip_region(myi->region); myi->region = 0; + fl_window = myi->other_xid; + draw(); + fl_window = myi->xid; + } + if (!copy) { + XdbeSwapInfo s; + s.swap_window = fl_xid(this); + s.swap_action = XdbeUndefined; + XdbeSwapBuffers(fl_display, &s, 1); + myi->backbuffer_bad = 1; + return; + } + // otherwise just use normal copy from back to front: + myi->backbuffer_bad = 0; // which won't destroy the back buffer... + } else +#endif + if (damage() & ~FL_DAMAGE_EXPOSE) { + fl_clip_region(myi->region); myi->region = 0; +#ifdef WIN32 + HDC _sgc = fl_gc; + fl_gc = fl_makeDC(myi->other_xid); + int save = SaveDC(fl_gc); + fl_restore_clip(); // duplicate region into new gc + draw(); + RestoreDC(fl_gc, save); + DeleteDC(fl_gc); + fl_gc = _sgc; +#elif defined(__APPLE__) + if ( myi->other_xid ) { + fl_begin_offscreen( myi->other_xid ); + fl_clip_region( 0 ); + draw(); + fl_end_offscreen(); + } else { + draw(); + } +#else // X: + fl_window = myi->other_xid; + draw(); + fl_window = myi->xid; +#endif + } + if (eraseoverlay) fl_clip_region(0); + // on Irix (at least) it is faster to reduce the area copied to + // the current clip region: + int X,Y,W,H; fl_clip_box(0,0,w(),h(),X,Y,W,H); + if (myi->other_xid) fl_copy_offscreen(X, Y, W, H, myi->other_xid, X, Y); +} + +void Fl_Double_Window::resize(int X,int Y,int W,int H) { + int ow = w(); + int oh = h(); + Fl_Window::resize(X,Y,W,H); +#if USE_XDBE + if (use_xdbe) return; +#endif + Fl_X* myi = Fl_X::i(this); + if (myi && myi->other_xid && (ow != w() || oh != h())) { + fl_delete_offscreen(myi->other_xid); + myi->other_xid = 0; + } +} + +void Fl_Double_Window::hide() { + Fl_X* myi = Fl_X::i(this); + if (myi && myi->other_xid) { +#if USE_XDBE + if (!use_xdbe) +#endif + fl_delete_offscreen(myi->other_xid); + } + Fl_Window::hide(); +} + +Fl_Double_Window::~Fl_Double_Window() { + hide(); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_File_Browser.cxx b/Utilities/FLTK/src/Fl_File_Browser.cxx new file mode 100644 index 0000000000..7698a8083b --- /dev/null +++ b/Utilities/FLTK/src/Fl_File_Browser.cxx @@ -0,0 +1,636 @@ +// +// "$Id$" +// +// Fl_File_Browser routines. +// +// Copyright 1999-2005 by Michael Sweet. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +// Contents: +// +// Fl_File_Browser::full_height() - Return the height of the list. +// Fl_File_Browser::item_height() - Return the height of a list item. +// Fl_File_Browser::item_width() - Return the width of a list item. +// Fl_File_Browser::item_draw() - Draw a list item. +// Fl_File_Browser::Fl_File_Browser() - Create a Fl_File_Browser widget. +// Fl_File_Browser::load() - Load a directory into the browser. +// Fl_File_Browser::filter() - Set the filename filter. +// + +// +// Include necessary header files... +// + +#include <FL/Fl_File_Browser.H> +#include <FL/fl_draw.H> +#include <FL/filename.H> +#include <stdio.h> +#include <stdlib.h> +#include "flstring.h" + +#ifdef __CYGWIN__ +# include <mntent.h> +#elif defined(WIN32) +# include <windows.h> +# include <direct.h> +// Apparently Borland C++ defines DIRECTORY in <direct.h>, which +// interfers with the Fl_File_Icon enumeration of the same name. +# ifdef DIRECTORY +# undef DIRECTORY +# endif // DIRECTORY +#endif // __CYGWIN__ + +#ifdef __EMX__ +# define INCL_DOS +# define INCL_DOSMISC +# include <os2.h> +#endif // __EMX__ + +// CodeWarrior (__MWERKS__) gets its include paths confused, so we +// temporarily disable this... +#if defined(__APPLE__) && !defined(__MWERKS__) +# include <sys/param.h> +# include <sys/ucred.h> +# include <sys/mount.h> +#endif // __APPLE__ && !__MWERKS__ + + +// +// FL_BLINE definition from "Fl_Browser.cxx"... +// + +#define SELECTED 1 +#define NOTDISPLAYED 2 + +struct FL_BLINE // data is in a linked list of these +{ + FL_BLINE *prev; // Previous item in list + FL_BLINE *next; // Next item in list + void *data; // Pointer to data (function) + short length; // sizeof(txt)-1, may be longer than string + char flags; // selected, displayed + char txt[1]; // start of allocated array +}; + + +// +// 'Fl_File_Browser::full_height()' - Return the height of the list. +// + +int // O - Height in pixels +Fl_File_Browser::full_height() const +{ + int i, // Looping var + th; // Total height of list. + + + for (i = 0, th = 0; i < size(); i ++) + th += item_height(find_line(i)); + + return (th); +} + + +// +// 'Fl_File_Browser::item_height()' - Return the height of a list item. +// + +int // O - Height in pixels +Fl_File_Browser::item_height(void *p) const // I - List item data +{ + FL_BLINE *line; // Pointer to line + char *t; // Pointer into text + int height; // Width of line + int textheight; // Height of text + + + // Figure out the standard text height... + fl_font(textfont(), textsize()); + textheight = fl_height(); + + // We always have at least 1 line... + height = textheight; + + // Scan for newlines... + line = (FL_BLINE *)p; + + if (line != NULL) + for (t = line->txt; *t != '\0'; t ++) + if (*t == '\n') + height += textheight; + + // If we have enabled icons then add space for them... + if (Fl_File_Icon::first() != NULL && height < iconsize_) + height = iconsize_; + + // Add space for the selection border.. + height += 2; + + // Return the height + return (height); +} + + +// +// 'Fl_File_Browser::item_width()' - Return the width of a list item. +// + +int // O - Width in pixels +Fl_File_Browser::item_width(void *p) const // I - List item data +{ + int i; // Looping var + FL_BLINE *line; // Pointer to line + char *t, // Pointer into text + *ptr, // Pointer into fragment + fragment[10240]; // Fragment of text + int width, // Width of line + tempwidth; // Width of fragment + int column; // Current column + const int *columns; // Columns + + + // Set the font and size... + fl_font(textfont(), textsize()); + + // Scan for newlines... + line = (FL_BLINE *)p; + columns = column_widths(); + + if (strchr(line->txt, '\n') == NULL && + strchr(line->txt, column_char()) == NULL) + { + // Do a fast width calculation... + width = (int)fl_width(line->txt); + } + else + { + // More than 1 line or have columns; find the maximum width... + width = 0; + tempwidth = 0; + column = 0; + + for (t = line->txt, ptr = fragment; *t != '\0'; t ++) + if (*t == '\n') + { + // Newline - nul terminate this fragment and get the width... + *ptr = '\0'; + + tempwidth += (int)fl_width(fragment); + + // Update the max width as needed... + if (tempwidth > width) + width = tempwidth; + + // Point back to the start of the fragment... + ptr = fragment; + tempwidth = 0; + column = 0; + } + else if (*t == column_char()) + { + // Advance to the next column... + column ++; + if (columns) + { + for (i = 0, tempwidth = 0; i < column && columns[i]; i ++) + tempwidth += columns[i]; + } + else + tempwidth = column * (int)(fl_height() * 0.6 * 8.0); + + if (tempwidth > width) + width = tempwidth; + + ptr = fragment; + } + else + *ptr++ = *t; + + if (ptr > fragment) + { + // Nul terminate this fragment and get the width... + *ptr = '\0'; + + tempwidth += (int)fl_width(fragment); + + // Update the max width as needed... + if (tempwidth > width) + width = tempwidth; + } + } + + // If we have enabled icons then add space for them... + if (Fl_File_Icon::first() != NULL) + width += iconsize_ + 8; + + // Add space for the selection border.. + width += 2; + + // Return the width + return (width); +} + + +// +// 'Fl_File_Browser::item_draw()' - Draw a list item. +// + +void +Fl_File_Browser::item_draw(void *p, // I - List item data + int X, // I - Upper-lefthand X coordinate + int Y, // I - Upper-lefthand Y coordinate + int W, // I - Width of item + int) const // I - Height of item +{ + int i; // Looping var + FL_BLINE *line; // Pointer to line + Fl_Color c; // Text color + char *t, // Pointer into text + *ptr, // Pointer into fragment + fragment[10240]; // Fragment of text + int width, // Width of line + height; // Height of line + int column; // Current column + const int *columns; // Columns + + + // Draw the list item text... + line = (FL_BLINE *)p; + + if (line->txt[strlen(line->txt) - 1] == '/') + fl_font(textfont() | FL_BOLD, textsize()); + else + fl_font(textfont(), textsize()); + + if (line->flags & SELECTED) + c = fl_contrast(textcolor(), selection_color()); + else + c = textcolor(); + + if (Fl_File_Icon::first() == NULL) + { + // No icons, just draw the text... + X ++; + W -= 2; + } + else + { + // Draw the icon if it is set... + if (line->data) + ((Fl_File_Icon *)line->data)->draw(X, Y, iconsize_, iconsize_, + (line->flags & SELECTED) ? FL_YELLOW : + FL_LIGHT2, + active_r()); + + // Draw the text offset to the right... + X += iconsize_ + 9; + W -= iconsize_ - 10; + + // Center the text vertically... + height = fl_height(); + + for (t = line->txt; *t != '\0'; t ++) + if (*t == '\n') + height += fl_height(); + + if (height < iconsize_) + Y += (iconsize_ - height) / 2; + } + + // Draw the text... + line = (FL_BLINE *)p; + columns = column_widths(); + width = 0; + column = 0; + + if (active_r()) + fl_color(c); + else + fl_color(fl_inactive(c)); + + for (t = line->txt, ptr = fragment; *t != '\0'; t ++) + if (*t == '\n') + { + // Newline - nul terminate this fragment and draw it... + *ptr = '\0'; + + fl_draw(fragment, X + width, Y, W - width, fl_height(), + (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_CLIP), 0, 0); + + // Point back to the start of the fragment... + ptr = fragment; + width = 0; + Y += fl_height(); + column = 0; + } + else if (*t == column_char()) + { + // Tab - nul terminate this fragment and draw it... + *ptr = '\0'; + + int cW = W - width; // Clip width... + + if (columns) + { + // Try clipping inside this column... + for (i = 0; i < column && columns[i]; i ++); + + if (columns[i]) + cW = columns[i]; + } + + fl_draw(fragment, X + width, Y, cW, fl_height(), + (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_CLIP), 0, 0); + + // Advance to the next column... + column ++; + if (columns) + { + for (i = 0, width = 0; i < column && columns[i]; i ++) + width += columns[i]; + } + else + width = column * (int)(fl_height() * 0.6 * 8.0); + + ptr = fragment; + } + else + *ptr++ = *t; + + if (ptr > fragment) + { + // Nul terminate this fragment and draw it... + *ptr = '\0'; + + fl_draw(fragment, X + width, Y, W - width, fl_height(), + (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_CLIP), 0, 0); + } +} + + +// +// 'Fl_File_Browser::Fl_File_Browser()' - Create a Fl_File_Browser widget. +// + +Fl_File_Browser::Fl_File_Browser(int X, // I - Upper-lefthand X coordinate + int Y, // I - Upper-lefthand Y coordinate + int W, // I - Width in pixels + int H, // I - Height in pixels + const char *l) // I - Label text + : Fl_Browser(X, Y, W, H, l) +{ + // Initialize the filter pattern, current directory, and icon size... + pattern_ = "*"; + directory_ = ""; + iconsize_ = (uchar)(3 * textsize() / 2); + filetype_ = FILES; +} + + +// +// 'Fl_File_Browser::load()' - Load a directory into the browser. +// + +int // O - Number of files loaded +Fl_File_Browser::load(const char *directory,// I - Directory to load + Fl_File_Sort_F *sort) // I - Sort function to use +{ + int i; // Looping var + int num_files; // Number of files in directory + int num_dirs; // Number of directories in list + char filename[4096]; // Current file + Fl_File_Icon *icon; // Icon to use + + +// printf("Fl_File_Browser::load(\"%s\")\n", directory); + + clear(); + + directory_ = directory; + + if (!directory) + return (0); + + if (directory_[0] == '\0') + { + // + // No directory specified; for UNIX list all mount points. For DOS + // list all valid drive letters... + // + + num_files = 0; + if ((icon = Fl_File_Icon::find("any", Fl_File_Icon::DEVICE)) == NULL) + icon = Fl_File_Icon::find("any", Fl_File_Icon::DIRECTORY); + +#ifdef WIN32 +# ifdef __CYGWIN__ + // + // Cygwin provides an implementation of setmntent() to get the list + // of available drives... + // + FILE *m = setmntent("/-not-used-", "r"); + struct mntent *p; + + while ((p = getmntent (m)) != NULL) { + add(p->mnt_dir, icon); + num_files ++; + } + + endmntent(m); +# else + // + // Normal WIN32 code uses drive bits... + // + DWORD drives; // Drive available bits + + drives = GetLogicalDrives(); + for (i = 'A'; i <= 'Z'; i ++, drives >>= 1) + if (drives & 1) + { + sprintf(filename, "%c:/", i); + + if (i < 'C') + add(filename, icon); + else + add(filename, icon); + + num_files ++; + } +# endif // __CYGWIN__ +#elif defined(__EMX__) + // + // OS/2 code uses drive bits... + // + ULONG curdrive; // Current drive + ULONG drives; // Drive available bits + int start = 3; // 'C' (MRS - dunno if this is correct!) + + + DosQueryCurrentDisk(&curdrive, &drives); + drives >>= start - 1; + for (i = 'A'; i <= 'Z'; i ++, drives >>= 1) + if (drives & 1) + { + sprintf(filename, "%c:/", i); + add(filename, icon); + + num_files ++; + } +#elif defined(__APPLE__) && !defined(__MWERKS__) + // MacOS X and Darwin use getfsstat() system call... + int numfs; // Number of file systems + struct statfs *fs; // Buffer for file system info + + + // We always have the root filesystem. + add("/", icon); + + // Get the mounted filesystems... + numfs = getfsstat(NULL, 0, MNT_NOWAIT); + if (numfs > 0) { + // We have file systems, get them... + fs = new struct statfs[numfs]; + getfsstat(fs, sizeof(struct statfs) * numfs, MNT_NOWAIT); + + // Add filesystems to the list... + for (i = 0; i < numfs; i ++) { + // Ignore "/", "/dev", and "/.vol"... + if (fs[i].f_mntonname[1] && strcmp(fs[i].f_mntonname, "/dev") && + strcmp(fs[i].f_mntonname, "/.vol")) { + snprintf(filename, sizeof(filename), "%s/", fs[i].f_mntonname); + add(filename, icon); + } + num_files ++; + } + + // Free the memory used for the file system info array... + delete[] fs; + } +#else + // + // UNIX code uses /etc/fstab or similar... + // + FILE *mtab; // /etc/mtab or /etc/mnttab file + char line[1024]; // Input line + + // + // Open the file that contains a list of mounted filesystems... + // + + mtab = fopen("/etc/mnttab", "r"); // Fairly standard + if (mtab == NULL) + mtab = fopen("/etc/mtab", "r"); // More standard + if (mtab == NULL) + mtab = fopen("/etc/fstab", "r"); // Otherwise fallback to full list + if (mtab == NULL) + mtab = fopen("/etc/vfstab", "r"); // Alternate full list file + + if (mtab != NULL) + { + while (fgets(line, sizeof(line), mtab) != NULL) + { + if (line[0] == '#' || line[0] == '\n') + continue; + if (sscanf(line, "%*s%4095s", filename) != 1) + continue; + + strlcat(filename, "/", sizeof(filename)); + +// printf("Fl_File_Browser::load() - adding \"%s\" to list...\n", filename); + add(filename, icon); + num_files ++; + } + + fclose(mtab); + } +#endif // WIN32 || __EMX__ + } + else + { + dirent **files; // Files in in directory + + + // + // Build the file list... + // + +#if (defined(WIN32) && !defined(__CYGWIN__)) || defined(__EMX__) + strlcpy(filename, directory_, sizeof(filename)); + i = strlen(filename) - 1; + + if (i == 2 && filename[1] == ':' && + (filename[2] == '/' || filename[2] == '\\')) + filename[2] = '/'; + else if (filename[i] != '/' && filename[i] != '\\') + strlcat(filename, "/", sizeof(filename)); + + num_files = fl_filename_list(filename, &files, sort); +#else + num_files = fl_filename_list(directory_, &files, sort); +#endif /* WIN32 || __EMX__ */ + + if (num_files <= 0) + return (0); + + for (i = 0, num_dirs = 0; i < num_files; i ++) { + if (strcmp(files[i]->d_name, "./")) { + snprintf(filename, sizeof(filename), "%s/%s", directory_, + files[i]->d_name); + + icon = Fl_File_Icon::find(filename); + if ((icon && icon->type() == Fl_File_Icon::DIRECTORY) || + fl_filename_isdir(filename)) { + num_dirs ++; + insert(num_dirs, files[i]->d_name, icon); + } else if (filetype_ == FILES && + fl_filename_match(files[i]->d_name, pattern_)) { + add(files[i]->d_name, icon); + } + } + + free(files[i]); + } + + free(files); + } + + return (num_files); +} + + +// +// 'Fl_File_Browser::filter()' - Set the filename filter. +// + +void +Fl_File_Browser::filter(const char *pattern) // I - Pattern string +{ + // If pattern is NULL set the pattern to "*"... + if (pattern) + pattern_ = pattern; + else + pattern_ = "*"; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_File_Chooser.cxx b/Utilities/FLTK/src/Fl_File_Chooser.cxx new file mode 100644 index 0000000000..356e97ddee --- /dev/null +++ b/Utilities/FLTK/src/Fl_File_Chooser.cxx @@ -0,0 +1,445 @@ +// +// "$Id$" +// +// Fl_File_Chooser dialog for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// generated by Fast Light User Interface Designer (fluid) version 1.0107 + +#include "../FL/Fl_File_Chooser.H" +#include <FL/fl_draw.H> + +void Fl_File_Chooser::cb_window_i(Fl_Double_Window*, void*) { + fileName->value(""); +fileList->deselect(); +Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this); +window->hide(); +} +void Fl_File_Chooser::cb_window(Fl_Double_Window* o, void* v) { + ((Fl_File_Chooser*)(o->user_data()))->cb_window_i(o,v); +} + +void Fl_File_Chooser::cb_showChoice_i(Fl_Choice*, void*) { + showChoiceCB(); +} +void Fl_File_Chooser::cb_showChoice(Fl_Choice* o, void* v) { + ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_showChoice_i(o,v); +} + +void Fl_File_Chooser::cb_favoritesButton_i(Fl_Menu_Button*, void*) { + favoritesButtonCB(); +} +void Fl_File_Chooser::cb_favoritesButton(Fl_Menu_Button* o, void* v) { + ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favoritesButton_i(o,v); +} + +void Fl_File_Chooser::cb_newButton_i(Fl_Button*, void*) { + newdir(); +} +void Fl_File_Chooser::cb_newButton(Fl_Button* o, void* v) { + ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_newButton_i(o,v); +} + +#include <FL/Fl_Bitmap.H> +static unsigned char idata_new[] = +{0,0,120,0,132,0,2,1,1,254,1,128,49,128,49,128,253,128,253,128,49,128,49, +128,1,128,1,128,255,255,0,0}; +static Fl_Bitmap image_new(idata_new, 16, 16); + +void Fl_File_Chooser::cb__i(Fl_Tile*, void*) { + update_preview(); +} +void Fl_File_Chooser::cb_(Fl_Tile* o, void* v) { + ((Fl_File_Chooser*)(o->parent()->user_data()))->cb__i(o,v); +} + +void Fl_File_Chooser::cb_fileList_i(Fl_File_Browser*, void*) { + fileListCB(); +} +void Fl_File_Chooser::cb_fileList(Fl_File_Browser* o, void* v) { + ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_fileList_i(o,v); +} + +void Fl_File_Chooser::cb_previewButton_i(Fl_Check_Button*, void*) { + preview(previewButton->value()); +} +void Fl_File_Chooser::cb_previewButton(Fl_Check_Button* o, void* v) { + ((Fl_File_Chooser*)(o->parent()->parent()->parent()->user_data()))->cb_previewButton_i(o,v); +} + +void Fl_File_Chooser::cb_fileName_i(Fl_File_Input*, void*) { + fileNameCB(); +} +void Fl_File_Chooser::cb_fileName(Fl_File_Input* o, void* v) { + ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_fileName_i(o,v); +} + +void Fl_File_Chooser::cb_okButton_i(Fl_Return_Button*, void*) { + // Do any callback that is registered... +if (callback_) + (*callback_)(this, data_); + +window->hide(); +} +void Fl_File_Chooser::cb_okButton(Fl_Return_Button* o, void* v) { + ((Fl_File_Chooser*)(o->parent()->parent()->parent()->user_data()))->cb_okButton_i(o,v); +} + +void Fl_File_Chooser::cb_cancelButton_i(Fl_Button*, void*) { + fileName->value(""); +fileList->deselect(); +Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this); +window->hide(); +} +void Fl_File_Chooser::cb_cancelButton(Fl_Button* o, void* v) { + ((Fl_File_Chooser*)(o->parent()->parent()->parent()->user_data()))->cb_cancelButton_i(o,v); +} + +void Fl_File_Chooser::cb_favList_i(Fl_File_Browser*, void*) { + favoritesCB(favList); +} +void Fl_File_Chooser::cb_favList(Fl_File_Browser* o, void* v) { + ((Fl_File_Chooser*)(o->parent()->user_data()))->cb_favList_i(o,v); +} + +void Fl_File_Chooser::cb_favUpButton_i(Fl_Button*, void*) { + favoritesCB(favUpButton); +} +void Fl_File_Chooser::cb_favUpButton(Fl_Button* o, void* v) { + ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favUpButton_i(o,v); +} + +void Fl_File_Chooser::cb_favDeleteButton_i(Fl_Button*, void*) { + favoritesCB(favDeleteButton); +} +void Fl_File_Chooser::cb_favDeleteButton(Fl_Button* o, void* v) { + ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favDeleteButton_i(o,v); +} + +void Fl_File_Chooser::cb_favDownButton_i(Fl_Button*, void*) { + favoritesCB(favDownButton); +} +void Fl_File_Chooser::cb_favDownButton(Fl_Button* o, void* v) { + ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favDownButton_i(o,v); +} + +void Fl_File_Chooser::cb_favCancelButton_i(Fl_Button*, void*) { + favWindow->hide(); +} +void Fl_File_Chooser::cb_favCancelButton(Fl_Button* o, void* v) { + ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favCancelButton_i(o,v); +} + +void Fl_File_Chooser::cb_favOkButton_i(Fl_Return_Button*, void*) { + favoritesCB(favOkButton); +} +void Fl_File_Chooser::cb_favOkButton(Fl_Return_Button* o, void* v) { + ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favOkButton_i(o,v); +} + +Fl_File_Chooser::Fl_File_Chooser(const char *d, const char *p, int t, const char *title) { + Fl_Double_Window* w; + { Fl_Double_Window* o = window = new Fl_Double_Window(490, 380, "Choose File"); + w = o; + o->callback((Fl_Callback*)cb_window, (void*)(this)); + { Fl_Group* o = new Fl_Group(10, 10, 470, 25); + { Fl_Choice* o = showChoice = new Fl_Choice(65, 10, 215, 25, "Show:"); + o->down_box(FL_BORDER_BOX); + o->labelfont(1); + o->callback((Fl_Callback*)cb_showChoice); + Fl_Group::current()->resizable(o); + showChoice->label(show_label); + } + { Fl_Menu_Button* o = favoritesButton = new Fl_Menu_Button(290, 10, 155, 25, "Favorites"); + o->down_box(FL_BORDER_BOX); + o->callback((Fl_Callback*)cb_favoritesButton); + o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + favoritesButton->label(favorites_label); + } + { Fl_Button* o = newButton = new Fl_Button(455, 10, 25, 25); + o->image(image_new); + o->labelsize(8); + o->callback((Fl_Callback*)cb_newButton); + o->tooltip(new_directory_tooltip); + } + o->end(); + } + { Fl_Tile* o = new Fl_Tile(10, 45, 470, 225); + o->callback((Fl_Callback*)cb_); + { Fl_File_Browser* o = fileList = new Fl_File_Browser(10, 45, 295, 225); + o->type(2); + o->callback((Fl_Callback*)cb_fileList); + w->hotspot(o); + } + { Fl_Box* o = previewBox = new Fl_Box(305, 45, 175, 225, "?"); + o->box(FL_DOWN_BOX); + o->labelsize(100); + o->align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE); + } + o->end(); + Fl_Group::current()->resizable(o); + } + { Fl_Group* o = new Fl_Group(10, 275, 470, 95); + { Fl_Group* o = new Fl_Group(10, 275, 470, 20); + { Fl_Check_Button* o = previewButton = new Fl_Check_Button(10, 275, 73, 20, "Preview"); + o->down_box(FL_DOWN_BOX); + o->value(1); + o->shortcut(0x80070); + o->callback((Fl_Callback*)cb_previewButton); + previewButton->label(preview_label); + } + { Fl_Box* o = new Fl_Box(115, 275, 365, 20); + Fl_Group::current()->resizable(o); + } + o->end(); + } + { Fl_File_Input* o = fileName = new Fl_File_Input(115, 300, 365, 35); + o->labelfont(1); + o->callback((Fl_Callback*)cb_fileName); + o->when(FL_WHEN_ENTER_KEY); + Fl_Group::current()->resizable(o); + fileName->when(FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY_ALWAYS); + } + { Fl_Box* o = new Fl_Box(10, 310, 105, 25, "Filename:"); + o->labelfont(1); + o->align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE); + o->label(filename_label); + } + { Fl_Group* o = new Fl_Group(10, 345, 470, 25); + { Fl_Return_Button* o = okButton = new Fl_Return_Button(313, 345, 85, 25, "OK"); + o->callback((Fl_Callback*)cb_okButton); + okButton->label(fl_ok); + } + { Fl_Button* o = cancelButton = new Fl_Button(408, 345, 72, 25, "Cancel"); + o->callback((Fl_Callback*)cb_cancelButton); + o->label(fl_cancel); + } + { Fl_Box* o = new Fl_Box(10, 345, 30, 25); + Fl_Group::current()->resizable(o); + } + o->end(); + } + o->end(); + } + if (title) window->label(title); + o->set_modal(); + o->end(); + } + { Fl_Double_Window* o = favWindow = new Fl_Double_Window(355, 150, "Manage Favorites"); + w = o; + o->user_data((void*)(this)); + { Fl_File_Browser* o = favList = new Fl_File_Browser(10, 10, 300, 95); + o->type(2); + o->callback((Fl_Callback*)cb_favList); + Fl_Group::current()->resizable(o); + } + { Fl_Group* o = new Fl_Group(320, 10, 25, 95); + { Fl_Button* o = favUpButton = new Fl_Button(320, 10, 25, 25, "@8>"); + o->callback((Fl_Callback*)cb_favUpButton); + } + { Fl_Button* o = favDeleteButton = new Fl_Button(320, 45, 25, 25, "X"); + o->labelfont(1); + o->callback((Fl_Callback*)cb_favDeleteButton); + Fl_Group::current()->resizable(o); + } + { Fl_Button* o = favDownButton = new Fl_Button(320, 80, 25, 25, "@2>"); + o->callback((Fl_Callback*)cb_favDownButton); + } + o->end(); + } + { Fl_Group* o = new Fl_Group(10, 113, 335, 29); + { Fl_Button* o = favCancelButton = new Fl_Button(273, 115, 72, 25, "Cancel"); + o->callback((Fl_Callback*)cb_favCancelButton); + favCancelButton->label(fl_cancel); + } + { Fl_Return_Button* o = favOkButton = new Fl_Return_Button(181, 115, 79, 25, "Save"); + o->callback((Fl_Callback*)cb_favOkButton); + favOkButton->label(save_label); + } + { Fl_Box* o = new Fl_Box(10, 115, 161, 25); + Fl_Group::current()->resizable(o); + } + o->end(); + } + favWindow->label(manage_favorites_label); + o->set_modal(); + o->size_range(181, 150); + o->end(); + } + callback_ = 0; +data_ = 0; +directory_[0] = 0; +window->size_range(window->w(), window->h(), Fl::w(), Fl::h()); +type(t); +filter(p); +update_favorites(); +value(d); +type(t); +int e; +prefs_.get("preview", e, 1); +preview(e); +} + +Fl_File_Chooser::~Fl_File_Chooser() { + Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this); +delete window; +delete favWindow; +} + +void Fl_File_Chooser::callback(void (*cb)(Fl_File_Chooser *, void *), void *d ) { + callback_ = cb; +data_ = d; +} + +void Fl_File_Chooser::color(Fl_Color c) { + fileList->color(c); +} + +Fl_Color Fl_File_Chooser::color() { + return (fileList->color()); +} + +char * Fl_File_Chooser::directory() { + return directory_; +} + +const char * Fl_File_Chooser::filter() { + return (fileList->filter()); +} + +int Fl_File_Chooser::filter_value() { + return showChoice->value(); +} + +void Fl_File_Chooser::filter_value(int f) { + showChoice->value(f); +showChoiceCB(); +} + +void Fl_File_Chooser::hide() { + window->hide(); +} + +void Fl_File_Chooser::iconsize(uchar s) { + fileList->iconsize(s); +} + +uchar Fl_File_Chooser::iconsize() { + return (fileList->iconsize()); +} + +void Fl_File_Chooser::label(const char *l) { + window->label(l); +} + +const char * Fl_File_Chooser::label() { + return (window->label()); +} + +void Fl_File_Chooser::ok_label(const char *l) { + okButton->label(l); +int w=0, h=0; +okButton->measure_label(w, h); +okButton->resize(cancelButton->x() - 50 - w, cancelButton->y(), + w + 40, 25); +okButton->parent()->init_sizes(); +} + +const char * Fl_File_Chooser::ok_label() { + return (okButton->label()); +} + +void Fl_File_Chooser::show() { + window->hotspot(fileList); +window->show(); +Fl::flush(); +fl_cursor(FL_CURSOR_WAIT); +rescan(); +fl_cursor(FL_CURSOR_DEFAULT); +fileName->take_focus(); +} + +int Fl_File_Chooser::shown() { + return window->shown(); +} + +void Fl_File_Chooser::textcolor(Fl_Color c) { + fileList->textcolor(c); +} + +Fl_Color Fl_File_Chooser::textcolor() { + return (fileList->textcolor()); +} + +void Fl_File_Chooser::textfont(uchar f) { + fileList->textfont(f); +} + +uchar Fl_File_Chooser::textfont() { + return (fileList->textfont()); +} + +void Fl_File_Chooser::textsize(uchar s) { + fileList->textsize(s); +} + +uchar Fl_File_Chooser::textsize() { + return (fileList->textsize()); +} + +void Fl_File_Chooser::type(int t) { + type_ = t; +if (t & MULTI) + fileList->type(FL_MULTI_BROWSER); +else + fileList->type(FL_HOLD_BROWSER); +if (t & CREATE) + newButton->activate(); +else + newButton->deactivate(); +if (t & DIRECTORY) + fileList->filetype(Fl_File_Browser::DIRECTORIES); +else + fileList->filetype(Fl_File_Browser::FILES); +} + +int Fl_File_Chooser::type() { + return (type_); +} + +void * Fl_File_Chooser::user_data() const { + return (data_); +} + +void Fl_File_Chooser::user_data(void *d) { + data_ = d; +} + +int Fl_File_Chooser::visible() { + return window->visible(); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_File_Chooser.fl b/Utilities/FLTK/src/Fl_File_Chooser.fl new file mode 100644 index 0000000000..b9687d54c4 --- /dev/null +++ b/Utilities/FLTK/src/Fl_File_Chooser.fl @@ -0,0 +1,422 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {../FL/Fl_File_Chooser.H} +code_name {.cxx} +comment {// +// "$Id: Fl_File_Chooser.fl 4723 2005-12-30 10:13:17Z matt $" +// +// Fl_File_Chooser dialog for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +} {in_source in_header +} + +decl {\#include <FL/fl_draw.H>} {} + +class FL_EXPORT Fl_File_Chooser {open +} { + decl {enum { SINGLE = 0, MULTI = 1, CREATE = 2, DIRECTORY = 4 };} {public + } + decl {static Fl_Preferences prefs_;} {} + decl {void (*callback_)(Fl_File_Chooser*, void *);} {} + decl {void *data_;} {} + decl {char directory_[1024];} {} + decl {char pattern_[1024];} {} + decl {char preview_text_[2048];} {} + decl {int type_;} {} + decl {void favoritesButtonCB();} {} + decl {void favoritesCB(Fl_Widget *w);} {} + decl {void fileListCB();} {} + decl {void fileNameCB();} {} + decl {void newdir();} {} + decl {static void previewCB(Fl_File_Chooser *fc);} {} + decl {void showChoiceCB();} {} + decl {void update_favorites();} {} + decl {void update_preview();} {} + Function {Fl_File_Chooser(const char *d, const char *p, int t, const char *title)} {open + } { + Fl_Window window { + label {Choose File} + callback {fileName->value(""); +fileList->deselect(); +Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this); +window->hide();} + private xywh {387 242 490 380} type Double resizable + code0 {if (title) window->label(title);} + code1 {\#include <stdio.h>} + code2 {\#include <stdlib.h>} + code3 {\#include <string.h>} modal visible + } { + Fl_Group {} { + private xywh {10 10 470 25} + } { + Fl_Choice showChoice { + label {Show:} + callback {showChoiceCB();} open + private xywh {65 10 215 25} down_box BORDER_BOX labelfont 1 resizable + code0 {showChoice->label(show_label);} + } {} + Fl_Menu_Button favoritesButton { + label Favorites + callback {favoritesButtonCB();} open + private xywh {290 10 155 25} down_box BORDER_BOX align 20 + code0 {favoritesButton->label(favorites_label);} + } {} + Fl_Button newButton { + callback {newdir();} + image {new.xbm} xywh {455 10 25 25} labelsize 8 + code0 {\#include <FL/Fl_Preferences.H>} + code1 {o->tooltip(new_directory_tooltip);} + } + } + Fl_Tile {} { + callback {update_preview();} + private xywh {10 45 470 225} resizable + } { + Fl_File_Browser fileList { + callback {fileListCB();} + private xywh {10 45 295 225} type Hold hotspot + code0 {\#include <FL/Fl_File_Browser.H>} + } + Fl_Box previewBox { + label {?} + private xywh {305 45 175 225} box DOWN_BOX labelsize 100 align 80 + } + } + Fl_Group {} { + private xywh {10 275 470 95} + } { + Fl_Group {} {open + private xywh {10 275 470 20} + } { + Fl_Check_Button previewButton { + label Preview + callback {preview(previewButton->value());} + xywh {10 275 73 20} down_box DOWN_BOX shortcut 0x80070 value 1 + code0 {previewButton->label(preview_label);} + } + Fl_Box {} { + private xywh {115 275 365 20} resizable + } + } + Fl_File_Input fileName { + callback {fileNameCB();} + private xywh {115 300 365 35} labelfont 1 when 8 resizable + code0 {fileName->when(FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY_ALWAYS);} + } + Fl_Box {} { + label {Filename:} + private xywh {10 310 105 25} labelfont 1 align 24 + code0 {o->label(filename_label);} + } + Fl_Group {} {open + private xywh {10 345 470 25} + } { + Fl_Return_Button okButton { + label OK + callback {// Do any callback that is registered... +if (callback_) + (*callback_)(this, data_); + +window->hide();} selected + private xywh {313 345 85 25} + code0 {\#include <FL/fl_ask.H>} + code1 {okButton->label(fl_ok);} + } + Fl_Button cancelButton { + label Cancel + callback {fileName->value(""); +fileList->deselect(); +Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this); +window->hide();} + private xywh {408 345 72 25} + code0 {o->label(fl_cancel);} + } + Fl_Box {} { + private xywh {10 345 30 25} resizable + } + } + } + } + Fl_Window favWindow { + label {Manage Favorites} + private xywh {437 187 355 150} type Double resizable + code0 {favWindow->label(manage_favorites_label);} modal size_range {181 150 0 0} visible + } { + Fl_File_Browser favList { + callback {favoritesCB(favList);} + private xywh {10 10 300 95} type Hold resizable + } + Fl_Group {} {open + xywh {320 10 25 95} + } { + Fl_Button favUpButton { + label {@8>} + callback {favoritesCB(favUpButton);} + private xywh {320 10 25 25} + } + Fl_Button favDeleteButton { + label X + callback {favoritesCB(favDeleteButton);} + private xywh {320 45 25 25} labelfont 1 resizable + } + Fl_Button favDownButton { + label {@2>} + callback {favoritesCB(favDownButton);} + private xywh {320 80 25 25} + } + } + Fl_Group {} {open + xywh {10 113 335 29} + } { + Fl_Button favCancelButton { + label Cancel + callback {favWindow->hide();} + private xywh {273 115 72 25} + code0 {favCancelButton->label(fl_cancel);} + } + Fl_Return_Button favOkButton { + label Save + callback {favoritesCB(favOkButton);} + private xywh {181 115 79 25} + code0 {\#include <FL/fl_ask.H>} + code1 {favOkButton->label(save_label);} + } + Fl_Box {} { + xywh {10 115 161 25} resizable + } + } + } + code {callback_ = 0; +data_ = 0; +directory_[0] = 0; +window->size_range(window->w(), window->h(), Fl::w(), Fl::h()); +type(t); +filter(p); +update_favorites(); +value(d); +type(t); +int e; +prefs_.get("preview", e, 1); +preview(e);} {} + } + Function {~Fl_File_Chooser()} {} { + code {Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this); +delete window; +delete favWindow;} {} + } + Function {callback(void (*cb)(Fl_File_Chooser *, void *), void *d = 0)} {return_type void + } { + code {callback_ = cb; +data_ = d;} {} + } + Function {color(Fl_Color c)} {} { + code {fileList->color(c);} {} + } + Function {color()} {return_type Fl_Color + } { + code {return (fileList->color());} {} + } + decl {int count();} {public + } + decl {void directory(const char *d);} {public + } + Function {directory()} {return_type {char *} + } { + code {return directory_;} {} + } + decl {void filter(const char *p);} {public + } + Function {filter()} {return_type {const char *} + } { + code {return (fileList->filter());} {} + } + Function {filter_value()} {return_type int + } { + code {return showChoice->value();} {} + } + Function {filter_value(int f)} {return_type void + } { + code {showChoice->value(f); +showChoiceCB();} {} + } + Function {hide()} {return_type void + } { + code {window->hide();} {} + } + Function {iconsize(uchar s)} {return_type void + } { + code {fileList->iconsize(s);} {} + } + Function {iconsize()} {return_type uchar + } { + code {return (fileList->iconsize());} {} + } + Function {label(const char *l)} {return_type void + } { + code {window->label(l);} {} + } + Function {label()} {return_type {const char *} + } { + code {return (window->label());} {} + } + Function {ok_label(const char *l)} {return_type void + } { + code {okButton->label(l); +int w=0, h=0; +okButton->measure_label(w, h); +okButton->resize(cancelButton->x() - 50 - w, cancelButton->y(), + w + 40, 25); +okButton->parent()->init_sizes();} {} + } + Function {ok_label()} {return_type {const char *} + } { + code {return (okButton->label());} {} + } + decl {void preview(int e);} {public + } + decl {int preview() const { return previewButton->value(); }} {public + } + decl {void rescan();} {public + } + Function {show()} {return_type void + } { + code {window->hotspot(fileList); +window->show(); +Fl::flush(); +fl_cursor(FL_CURSOR_WAIT); +rescan(); +fl_cursor(FL_CURSOR_DEFAULT); +fileName->take_focus();} {} + } + Function {shown()} {return_type int + } { + code {return window->shown();} {} + } + Function {textcolor(Fl_Color c)} {return_type void + } { + code {fileList->textcolor(c);} {} + } + Function {textcolor()} {return_type Fl_Color + } { + code {return (fileList->textcolor());} {} + } + Function {textfont(uchar f)} {return_type void + } { + code {fileList->textfont(f);} {} + } + Function {textfont()} {return_type uchar + } { + code {return (fileList->textfont());} {} + } + Function {textsize(uchar s)} {return_type void + } { + code {fileList->textsize(s);} {} + } + Function {textsize()} {return_type uchar + } { + code {return (fileList->textsize());} {} + } + Function {type(int t)} {return_type void + } { + code {type_ = t; +if (t & MULTI) + fileList->type(FL_MULTI_BROWSER); +else + fileList->type(FL_HOLD_BROWSER); +if (t & CREATE) + newButton->activate(); +else + newButton->deactivate(); +if (t & DIRECTORY) + fileList->filetype(Fl_File_Browser::DIRECTORIES); +else + fileList->filetype(Fl_File_Browser::FILES);} {} + } + Function {type()} {return_type int + } { + code {return (type_);} {} + } + Function {user_data() const} {return_type {void *} + } { + code {return (data_);} {} + } + Function {user_data(void *d)} {return_type void + } { + code {data_ = d;} {} + } + decl {const char *value(int f = 1);} {public + } + decl {void value(const char *filename);} {public + } + Function {visible()} {return_type int + } { + code {return window->visible();} {} + } + decl {static const char *add_favorites_label;} {public + } + decl {static const char *all_files_label;} {public + } + decl {static const char *custom_filter_label;} {public + } + decl {static const char *existing_file_label;} {public + } + decl {static const char *favorites_label;} {public + } + decl {static const char *filename_label;} {public + } + decl {static const char *filesystems_label;} {public + } + decl {static const char *manage_favorites_label;} {public + } + decl {static const char *new_directory_label;} {public + } + decl {static const char *new_directory_tooltip;} {public + } + decl {static const char *preview_label;} {public + } + decl {static const char *save_label;} {public + } + decl {static const char *show_label;} {public + } + decl {static Fl_File_Sort_F *sort;} {public + } +} + +decl {FL_EXPORT char *fl_dir_chooser(const char *message,const char *fname,int relative=0);} {public +} + +decl {FL_EXPORT char *fl_file_chooser(const char *message,const char *pat,const char *fname,int relative=0);} {public +} + +decl {FL_EXPORT void fl_file_chooser_callback(void (*cb)(const char*));} {public +} + +decl {FL_EXPORT void fl_file_chooser_ok_label(const char*l);} {public +} + +comment { +// +// End of "$Id: Fl_File_Chooser.fl 4723 2005-12-30 10:13:17Z matt $". +//} {in_source in_header +} diff --git a/Utilities/FLTK/src/Fl_File_Chooser2.cxx b/Utilities/FLTK/src/Fl_File_Chooser2.cxx new file mode 100644 index 0000000000..648d8a7abe --- /dev/null +++ b/Utilities/FLTK/src/Fl_File_Chooser2.cxx @@ -0,0 +1,1251 @@ +// +// "$Id$" +// +// More Fl_File_Chooser routines. +// +// Copyright 1999-2005 by Michael Sweet. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +// Contents: +// +// Fl_File_Chooser::count() - Return the number of selected files. +// Fl_File_Chooser::directory() - Set the directory in the file chooser. +// Fl_File_Chooser::filter() - Set the filter(s) for the chooser. +// Fl_File_Chooser::newdir() - Make a new directory. +// Fl_File_Chooser::value() - Return a selected filename. +// Fl_File_Chooser::rescan() - Rescan the current directory. +// Fl_File_Chooser::favoritesButtonCB() - Handle favorites selections. +// Fl_File_Chooser::fileListCB() - Handle clicks (and double-clicks) +// in the Fl_File_Browser. +// Fl_File_Chooser::fileNameCB() - Handle text entry in the FileBrowser. +// Fl_File_Chooser::showChoiceCB() - Handle show selections. +// compare_dirnames() - Compare two directory names. +// quote_pathname() - Quote a pathname for a menu. +// unquote_pathname() - Unquote a pathname from a menu. +// + +// +// Include necessary headers. +// + +#include <FL/Fl_File_Chooser.H> +#include <FL/filename.H> +#include <FL/fl_ask.H> +#include <FL/x.H> +#include <FL/Fl_Shared_Image.H> + +#include <stdio.h> +#include <stdlib.h> +#include "flstring.h" +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> + +#if defined(WIN32) && ! defined (__CYGWIN__) +# include <direct.h> +# include <io.h> +// Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs +// on Windows, which is supposed to be POSIX compliant... +# define access _access +# define mkdir _mkdir +// Apparently Borland C++ defines DIRECTORY in <direct.h>, which +// interfers with the Fl_File_Icon enumeration of the same name. +# ifdef DIRECTORY +# undef DIRECTORY +# endif // DIRECTORY +#else +# include <unistd.h> +# include <pwd.h> +#endif /* WIN32 */ + + +// +// File chooser label strings and sort function... +// + +Fl_Preferences Fl_File_Chooser::prefs_(Fl_Preferences::USER, "fltk.org", "filechooser"); + +const char *Fl_File_Chooser::add_favorites_label = "Add to Favorites"; +const char *Fl_File_Chooser::all_files_label = "All Files (*)"; +const char *Fl_File_Chooser::custom_filter_label = "Custom Filter"; +const char *Fl_File_Chooser::existing_file_label = "Please choose an existing file!"; +const char *Fl_File_Chooser::favorites_label = "Favorites"; +const char *Fl_File_Chooser::filename_label = "Filename:"; +#ifdef WIN32 +const char *Fl_File_Chooser::filesystems_label = "My Computer"; +#else +const char *Fl_File_Chooser::filesystems_label = "File Systems"; +#endif // WIN32 +const char *Fl_File_Chooser::manage_favorites_label = "Manage Favorites"; +const char *Fl_File_Chooser::new_directory_label = "New Directory?"; +const char *Fl_File_Chooser::new_directory_tooltip = "Create a new directory."; +const char *Fl_File_Chooser::preview_label = "Preview"; +const char *Fl_File_Chooser::save_label = "Save"; +const char *Fl_File_Chooser::show_label = "Show:"; +Fl_File_Sort_F *Fl_File_Chooser::sort = fl_numericsort; + + +// +// Local functions... +// + +static int compare_dirnames(const char *a, const char *b); +static void quote_pathname(char *, const char *, int); +static void unquote_pathname(char *, const char *, int); + + +// +// 'Fl_File_Chooser::count()' - Return the number of selected files. +// + +int // O - Number of selected files +Fl_File_Chooser::count() { + int i; // Looping var + int fcount; // Number of selected files + const char *filename; // Filename in input field or list + + + filename = fileName->value(); + + if (!(type_ & MULTI)) { + // Check to see if the file name input field is blank... + if (!filename || !filename[0]) return 0; + else return 1; + } + + for (i = 1, fcount = 0; i <= fileList->size(); i ++) + if (fileList->selected(i)) { + // See if this file is a directory... + filename = (char *)fileList->text(i); + + if (filename[strlen(filename) - 1] != '/') + fcount ++; + } + + if (fcount) return fcount; + else if (!filename || !filename[0]) return 0; + else return 1; +} + + +// +// 'Fl_File_Chooser::directory()' - Set the directory in the file chooser. +// + +void +Fl_File_Chooser::directory(const char *d)// I - Directory to change to +{ + char *dirptr; // Pointer into directory + + +// printf("Fl_File_Chooser::directory(\"%s\")\n", d == NULL ? "(null)" : d); + + // NULL == current directory + if (d == NULL) + d = "."; + +#ifdef WIN32 + // See if the filename contains backslashes... + char *slash; // Pointer to slashes + char fixpath[1024]; // Path with slashes converted + if (strchr(d, '\\')) { + // Convert backslashes to slashes... + strlcpy(fixpath, d, sizeof(fixpath)); + + for (slash = strchr(fixpath, '\\'); slash; slash = strchr(slash + 1, '\\')) + *slash = '/'; + + d = fixpath; + } +#endif // WIN32 + + if (d[0] != '\0') + { + // Make the directory absolute... +#if (defined(WIN32) && ! defined(__CYGWIN__))|| defined(__EMX__) + if (d[0] != '/' && d[0] != '\\' && d[1] != ':') +#else + if (d[0] != '/' && d[0] != '\\') +#endif /* WIN32 || __EMX__ */ + fl_filename_absolute(directory_, d); + else + strlcpy(directory_, d, sizeof(directory_)); + + // Strip any trailing slash... + dirptr = directory_ + strlen(directory_) - 1; + if ((*dirptr == '/' || *dirptr == '\\') && dirptr > directory_) + *dirptr = '\0'; + + // See if we have a trailing .. or . in the filename... + dirptr = directory_ + strlen(directory_) - 3; + if (dirptr >= directory_ && strcmp(dirptr, "/..") == 0) { + // Yes, we have "..", so strip the trailing path... + *dirptr = '\0'; + while (dirptr > directory_) { + if (*dirptr == '/') break; + dirptr --; + } + + if (dirptr >= directory_ && *dirptr == '/') + *dirptr = '\0'; + } else if ((dirptr + 1) >= directory_ && strcmp(dirptr + 1, "/.") == 0) { + // Strip trailing "."... + dirptr[1] = '\0'; + } + } + else + directory_[0] = '\0'; + + if (shown()) { + // Rescan the directory... + rescan(); + } +} + + +// +// 'Fl_File_Chooser::favoritesButtonCB()' - Handle favorites selections. +// + +void +Fl_File_Chooser::favoritesButtonCB() +{ + int v; // Current selection + char pathname[1024], // Pathname + menuname[2048]; // Menu name + + + v = favoritesButton->value(); + + if (!v) { + // Add current directory to favorites... + if (getenv("HOME")) v = favoritesButton->size() - 5; + else v = favoritesButton->size() - 4; + + sprintf(menuname, "favorite%02d", v); + + prefs_.set(menuname, directory_); + + quote_pathname(menuname, directory_, sizeof(menuname)); + favoritesButton->add(menuname); + + if (favoritesButton->size() > 104) { + ((Fl_Menu_Item *)favoritesButton->menu())[0].deactivate(); + } + } else if (v == 1) { + // Manage favorites... + favoritesCB(0); + } else if (v == 2) { + // Filesystems/My Computer + directory(""); + } else { + unquote_pathname(pathname, favoritesButton->text(v), sizeof(pathname)); + directory(pathname); + } +} + + +// +// 'Fl_File_Chooser::favoritesCB()' - Handle favorites dialog. +// + +void +Fl_File_Chooser::favoritesCB(Fl_Widget *w) + // I - Widget +{ + int i; // Looping var + char name[32], // Preference name + pathname[1024]; // Directory in list + + + if (!w) { + // Load the favorites list... + favList->clear(); + favList->deselect(); + + for (i = 0; i < 100; i ++) { + // Get favorite directory 0 to 99... + sprintf(name, "favorite%02d", i); + + prefs_.get(name, pathname, "", sizeof(pathname)); + + // Stop on the first empty favorite... + if (!pathname[0]) break; + + // Add the favorite to the list... + favList->add(pathname, + Fl_File_Icon::find(pathname, Fl_File_Icon::DIRECTORY)); + } + + favUpButton->deactivate(); + favDeleteButton->deactivate(); + favDownButton->deactivate(); + favOkButton->deactivate(); + + favWindow->hotspot(favList); + favWindow->show(); + } else if (w == favList) { + i = favList->value(); + if (i) { + if (i > 1) favUpButton->activate(); + else favUpButton->deactivate(); + + favDeleteButton->activate(); + + if (i < favList->size()) favDownButton->activate(); + else favDownButton->deactivate(); + } else { + favUpButton->deactivate(); + favDeleteButton->deactivate(); + favDownButton->deactivate(); + } + } else if (w == favUpButton) { + i = favList->value(); + + favList->insert(i - 1, favList->text(i), favList->data(i)); + favList->remove(i + 1); + favList->select(i - 1); + + if (i == 2) favUpButton->deactivate(); + + favDownButton->activate(); + + favOkButton->activate(); + } else if (w == favDeleteButton) { + i = favList->value(); + + favList->remove(i); + + if (i > favList->size()) i --; + favList->select(i); + + if (i < favList->size()) favDownButton->activate(); + else favDownButton->deactivate(); + + if (i > 1) favUpButton->activate(); + else favUpButton->deactivate(); + + if (!i) favDeleteButton->deactivate(); + + favOkButton->activate(); + } else if (w == favDownButton) { + i = favList->value(); + + favList->insert(i + 2, favList->text(i), favList->data(i)); + favList->remove(i); + favList->select(i + 1); + + if ((i + 1) == favList->size()) favDownButton->deactivate(); + + favUpButton->activate(); + + favOkButton->activate(); + } else if (w == favOkButton) { + // Copy the new list over... + for (i = 0; i < favList->size(); i ++) { + // Set favorite directory 0 to 99... + sprintf(name, "favorite%02d", i); + + prefs_.set(name, favList->text(i + 1)); + } + + // Clear old entries as necessary... + for (; i < 100; i ++) { + // Clear favorite directory 0 to 99... + sprintf(name, "favorite%02d", i); + + prefs_.get(name, pathname, "", sizeof(pathname)); + + if (pathname[0]) prefs_.set(name, ""); + else break; + } + + update_favorites(); + + favWindow->hide(); + } +} + + +// +// 'Fl_File_Chooser::fileListCB()' - Handle clicks (and double-clicks) in the +// Fl_File_Browser. +// + +void +Fl_File_Chooser::fileListCB() +{ + char *filename, // New filename + pathname[1024]; // Full pathname to file + + + filename = (char *)fileList->text(fileList->value()); + if (!filename) + return; + + if (!directory_[0]) { + strlcpy(pathname, filename, sizeof(pathname)); + } else if (strcmp(directory_, "/") == 0) { + snprintf(pathname, sizeof(pathname), "/%s", filename); + } else { + snprintf(pathname, sizeof(pathname), "%s/%s", directory_, filename); + } + + if (Fl::event_clicks()) { +#if (defined(WIN32) && ! defined(__CYGWIN__)) || defined(__EMX__) + if ((strlen(pathname) == 2 && pathname[1] == ':') || + fl_filename_isdir(pathname)) +#else + if (fl_filename_isdir(pathname)) +#endif /* WIN32 || __EMX__ */ + { + // Change directories... + directory(pathname); + + // Reset the click count so that a click in the same spot won't + // be treated as a triple-click. We use a value of -1 because + // the next click will increment click count to 0, which is what + // we really want... + Fl::event_clicks(-1); + } + else + { + // Hide the window - picked the file... + window->hide(); + } + } + else + { + // Check if the user clicks on a directory when picking files; + // if so, make sure only that item is selected... + filename = pathname + strlen(pathname) - 1; + + if ((type_ & MULTI) && !(type_ & DIRECTORY)) { + if (*filename == '/') { + // Clicked on a directory, deselect everything else... + int i = fileList->value(); + fileList->deselect(); + fileList->select(i); + } else { + // Clicked on a file - see if there are other directories selected... + int i; + const char *temp; + for (i = 1; i <= fileList->size(); i ++) { + if (i != fileList->value() && fileList->selected(i)) { + temp = fileList->text(i); + temp += strlen(temp) - 1; + if (*temp == '/') break; // Yes, selected directory + } + } + + if (i <= fileList->size()) { + i = fileList->value(); + fileList->deselect(); + fileList->select(i); + } + } + } + // Strip any trailing slash from the directory name... + if (*filename == '/') *filename = '\0'; + +// puts("Setting fileName from fileListCB..."); + fileName->value(pathname); + + // Update the preview box... + Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this); + Fl::add_timeout(1.0, (Fl_Timeout_Handler)previewCB, this); + + // Do any callback that is registered... + if (callback_) (*callback_)(this, data_); + + // Activate the OK button as needed... + if (!fl_filename_isdir(pathname) || (type_ & DIRECTORY)) + okButton->activate(); + else + okButton->deactivate(); + } +} + + +// +// 'Fl_File_Chooser::fileNameCB()' - Handle text entry in the FileBrowser. +// + +void +Fl_File_Chooser::fileNameCB() +{ + char *filename, // New filename + *slash, // Pointer to trailing slash + pathname[1024], // Full pathname to file + matchname[256]; // Matching filename + int i, // Looping var + min_match, // Minimum number of matching chars + max_match, // Maximum number of matching chars + num_files, // Number of files in directory + first_line; // First matching line + const char *file; // File from directory + + +// puts("fileNameCB()"); + + // Get the filename from the text field... + filename = (char *)fileName->value(); + + if (!filename || !filename[0]) { + okButton->deactivate(); + return; + } + + // Expand ~ and $ variables as needed... + if (strchr(filename, '~') || strchr(filename, '$')) { + fl_filename_expand(pathname, sizeof(pathname), filename); + filename = pathname; + value(pathname); + } + + // Make sure we have an absolute path... +#if (defined(WIN32) && !defined(__CYGWIN__)) || defined(__EMX__) + if (directory_[0] != '\0' && filename[0] != '/' && + filename[0] != '\\' && + !(isalpha(filename[0] & 255) && (!filename[1] || filename[1] == ':'))) { +#else + if (directory_[0] != '\0' && filename[0] != '/') { +#endif /* WIN32 || __EMX__ */ + fl_filename_absolute(pathname, sizeof(pathname), filename); + value(pathname); + fileName->mark(fileName->position()); // no selection after expansion + } else if (filename != pathname) { + // Finally, make sure that we have a writable copy... + strlcpy(pathname, filename, sizeof(pathname)); + } + + filename = pathname; + + // Now process things according to the key pressed... + if (Fl::event_key() == FL_Enter || Fl::event_key() == FL_KP_Enter) { + // Enter pressed - select or change directory... +#if (defined(WIN32) && ! defined(__CYGWIN__)) || defined(__EMX__) + if ((isalpha(pathname[0] & 255) && pathname[1] == ':' && !pathname[2]) || + fl_filename_isdir(pathname) && + compare_dirnames(pathname, directory_)) { +#else + if (fl_filename_isdir(pathname) && + compare_dirnames(pathname, directory_)) { +#endif /* WIN32 || __EMX__ */ + directory(pathname); + } else if ((type_ & CREATE) || access(pathname, 0) == 0) { + if (!fl_filename_isdir(pathname) || (type_ & DIRECTORY)) { + // Update the preview box... + update_preview(); + + // Do any callback that is registered... + if (callback_) (*callback_)(this, data_); + + // Hide the window to signal things are done... + window->hide(); + } + } else { + // File doesn't exist, so beep at and alert the user... + fl_alert(existing_file_label); + } + } + else if (Fl::event_key() != FL_Delete && + Fl::event_key() != FL_BackSpace) { + // Check to see if the user has entered a directory... + if ((slash = strrchr(pathname, '/')) == NULL) + slash = strrchr(pathname, '\\'); + + if (!slash) return; + + // Yes, change directories if necessary... + *slash++ = '\0'; + filename = slash; + +#if defined(WIN32) || defined(__EMX__) + if (strcasecmp(pathname, directory_) && + (pathname[0] || strcasecmp("/", directory_))) { +#else + if (strcmp(pathname, directory_) && + (pathname[0] || strcasecmp("/", directory_))) { +#endif // WIN32 || __EMX__ + int p = fileName->position(); + int m = fileName->mark(); + + directory(pathname); + + if (filename[0]) { + char tempname[1024]; + + snprintf(tempname, sizeof(tempname), "%s/%s", directory_, filename); + fileName->value(tempname); + strlcpy(pathname, tempname, sizeof(pathname)); + } + + fileName->position(p, m); + } + + // Other key pressed - do filename completion as possible... + num_files = fileList->size(); + min_match = strlen(filename); + max_match = min_match + 1; + first_line = 0; + + for (i = 1; i <= num_files && max_match > min_match; i ++) { + file = fileList->text(i); + +#if (defined(WIN32) && ! defined(__CYGWIN__)) || defined(__EMX__) + if (strncasecmp(filename, file, min_match) == 0) { +#else + if (strncmp(filename, file, min_match) == 0) { +#endif // WIN32 || __EMX__ + // OK, this one matches; check against the previous match + if (!first_line) { + // First match; copy stuff over... + strlcpy(matchname, file, sizeof(matchname)); + max_match = strlen(matchname); + + // Strip trailing /, if any... + if (matchname[max_match - 1] == '/') { + max_match --; + matchname[max_match] = '\0'; + } + + // And then make sure that the item is visible + fileList->topline(i); + first_line = i; + } else { + // Succeeding match; compare to find maximum string match... + while (max_match > min_match) +#if (defined(WIN32) && ! defined(__CYGWIN__)) || defined(__EMX__) + if (strncasecmp(file, matchname, max_match) == 0) +#else + if (strncmp(file, matchname, max_match) == 0) +#endif // WIN32 || __EMX__ + break; + else + max_match --; + + // Truncate the string as needed... + matchname[max_match] = '\0'; + } + } + } + + // If we have any matches, add them to the input field... + if (first_line > 0 && min_match == max_match && + max_match == (int)strlen(fileList->text(first_line))) { + // This is the only possible match... + fileList->deselect(0); + fileList->select(first_line); + fileList->redraw(); + } else if (max_match > min_match && first_line) { + // Add the matching portion... + fileName->replace(filename - pathname, filename - pathname + min_match, + matchname); + + // Highlight it with the cursor at the end of the selection so + // s/he can press the right arrow to accept the selection + // (Tab and End also do this for both cases.) + fileName->position(filename - pathname + max_match, + filename - pathname + min_match); + } else if (max_match == 0) { + fileList->deselect(0); + fileList->redraw(); + } + + // See if we need to enable the OK button... + if (((type_ & CREATE) || !access(fileName->value(), 0)) && + (!fl_filename_isdir(fileName->value()) || (type_ & DIRECTORY))) { + okButton->activate(); + } else { + okButton->deactivate(); + } + } else { + // FL_Delete or FL_BackSpace + fileList->deselect(0); + fileList->redraw(); + if (((type_ & CREATE) || !access(fileName->value(), 0)) && + (!fl_filename_isdir(fileName->value()) || (type_ & DIRECTORY))) { + okButton->activate(); + } else { + okButton->deactivate(); + } + } +} + + +// +// 'Fl_File_Chooser::filter()' - Set the filter(s) for the chooser. +// + +void +Fl_File_Chooser::filter(const char *p) // I - Pattern(s) +{ + char *copyp, // Copy of pattern + *start, // Start of pattern + *end; // End of pattern + int allfiles; // Do we have a "*" pattern? + char temp[1024]; // Temporary pattern string + + + // Make sure we have a pattern... + if (!p || !*p) p = "*"; + + // Copy the pattern string... + copyp = strdup(p); + + // Separate the pattern string as necessary... + showChoice->clear(); + + for (start = copyp, allfiles = 0; start && *start; start = end) { + end = strchr(start, '\t'); + if (end) *end++ = '\0'; + + if (strcmp(start, "*") == 0) { + showChoice->add(all_files_label); + allfiles = 1; + } else { + quote_pathname(temp, start, sizeof(temp)); + showChoice->add(temp); + if (strstr(start, "(*)") != NULL) allfiles = 1; + } + } + + free(copyp); + + if (!allfiles) showChoice->add(all_files_label); + + showChoice->add(custom_filter_label); + + showChoice->value(0); + showChoiceCB(); +} + + +// +// 'Fl_File_Chooser::newdir()' - Make a new directory. +// + +void +Fl_File_Chooser::newdir() +{ + const char *dir; // New directory name + char pathname[1024]; // Full path of directory + + + // Get a directory name from the user + if ((dir = fl_input(new_directory_label, NULL)) == NULL) + return; + + // Make it relative to the current directory as needed... +#if (defined(WIN32) && ! defined (__CYGWIN__)) || defined(__EMX__) + if (dir[0] != '/' && dir[0] != '\\' && dir[1] != ':') +#else + if (dir[0] != '/' && dir[0] != '\\') +#endif /* WIN32 || __EMX__ */ + snprintf(pathname, sizeof(pathname), "%s/%s", directory_, dir); + else + strlcpy(pathname, dir, sizeof(pathname)); + + // Create the directory; ignore EEXIST errors... +#if defined(WIN32) && ! defined (__CYGWIN__) + if (mkdir(pathname)) +#else + if (mkdir(pathname, 0777)) +#endif /* WIN32 */ + if (errno != EEXIST) + { + fl_alert("%s", strerror(errno)); + return; + } + + // Show the new directory... + directory(pathname); +} + + +// +// 'Fl_File_Chooser::preview()' - Enable or disable the preview tile. +// + +void +Fl_File_Chooser::preview(int e)// I - 1 = enable preview, 0 = disable preview +{ + previewButton->value(e); + prefs_.set("preview", e); + + Fl_Group *p = previewBox->parent(); + if (e) { + int w = p->w() * 2 / 3; + fileList->resize(fileList->x(), fileList->y(), + w, fileList->h()); + previewBox->resize(fileList->x()+w, previewBox->y(), + p->w()-w, previewBox->h()); + previewBox->show(); + update_preview(); + } else { + fileList->resize(fileList->x(), fileList->y(), + p->w(), fileList->h()); + previewBox->resize(p->x()+p->w(), previewBox->y(), + 0, previewBox->h()); + previewBox->hide(); + } + p->init_sizes(); + + fileList->parent()->redraw(); +} + + +// +// 'Fl_File_Chooser::previewCB()' - Timeout handler for the preview box. +// + +void +Fl_File_Chooser::previewCB(Fl_File_Chooser *fc) { // I - File chooser + fc->update_preview(); +} + + +// +// 'Fl_File_Chooser::rescan()' - Rescan the current directory. +// + +void +Fl_File_Chooser::rescan() +{ + char pathname[1024]; // New pathname for filename field + + + // Clear the current filename + strlcpy(pathname, directory_, sizeof(pathname)); + if (pathname[0] && pathname[strlen(pathname) - 1] != '/') { + strlcat(pathname, "/", sizeof(pathname)); + } +// puts("Setting fileName in rescan()"); + fileName->value(pathname); + + if (type_ & DIRECTORY) + okButton->activate(); + else + okButton->deactivate(); + + // Build the file list... + fileList->load(directory_, sort); + + // Update the preview box... + update_preview(); +} + + +// +// 'Fl_File_Chooser::showChoiceCB()' - Handle show selections. +// + +void +Fl_File_Chooser::showChoiceCB() +{ + const char *item, // Selected item + *patstart; // Start of pattern + char *patend; // End of pattern + char temp[1024]; // Temporary string for pattern + + + item = showChoice->text(showChoice->value()); + + if (strcmp(item, custom_filter_label) == 0) { + if ((item = fl_input(custom_filter_label, pattern_)) != NULL) { + strlcpy(pattern_, item, sizeof(pattern_)); + + quote_pathname(temp, item, sizeof(temp)); + showChoice->add(temp); + showChoice->value(showChoice->size() - 2); + } + } else if ((patstart = strchr(item, '(')) == NULL) { + strlcpy(pattern_, item, sizeof(pattern_)); + } else { + strlcpy(pattern_, patstart + 1, sizeof(pattern_)); + if ((patend = strrchr(pattern_, ')')) != NULL) *patend = '\0'; + } + + fileList->filter(pattern_); + + if (shown()) { + // Rescan the directory... + rescan(); + } +} + + +// +// 'Fl_File_Chooser::update_favorites()' - Update the favorites menu. +// + +void +Fl_File_Chooser::update_favorites() +{ + int i; // Looping var + char pathname[1024], // Pathname + menuname[2048]; // Menu name + const char *home; // Home directory + + + favoritesButton->clear(); + favoritesButton->add("bla"); + favoritesButton->clear(); + favoritesButton->add(add_favorites_label, FL_ALT + 'a', 0); + favoritesButton->add(manage_favorites_label, FL_ALT + 'm', 0, 0, FL_MENU_DIVIDER); + favoritesButton->add(filesystems_label, FL_ALT + 'f', 0); + + if ((home = getenv("HOME")) != NULL) { + quote_pathname(menuname, home, sizeof(menuname)); + favoritesButton->add(menuname, FL_ALT + 'h', 0); + } + + for (i = 0; i < 100; i ++) { + sprintf(menuname, "favorite%02d", i); + prefs_.get(menuname, pathname, "", sizeof(pathname)); + if (!pathname[0]) break; + + quote_pathname(menuname, pathname, sizeof(menuname)); + + if (i < 10) favoritesButton->add(menuname, FL_ALT + '0' + i, 0); + else favoritesButton->add(menuname); + } + + if (i == 100) ((Fl_Menu_Item *)favoritesButton->menu())[0].deactivate(); +} + + +// +// 'Fl_File_Chooser::update_preview()' - Update the preview box... +// + +void +Fl_File_Chooser::update_preview() +{ + const char *filename; // Current filename + Fl_Shared_Image *image, // New image + *oldimage; // Old image + int pbw, pbh; // Width and height of preview box + int w, h; // Width and height of preview image + + + if (!previewButton->value()) return; + + if ((filename = value()) == NULL || fl_filename_isdir(filename)) image = NULL; + else { + window->cursor(FL_CURSOR_WAIT); + Fl::check(); + + image = Fl_Shared_Image::get(filename); + + if (image) { + window->cursor(FL_CURSOR_DEFAULT); + Fl::check(); + } + } + + oldimage = (Fl_Shared_Image *)previewBox->image(); + + if (oldimage) oldimage->release(); + + previewBox->image(0); + + if (!image) { + FILE *fp; + int bytes; + char *ptr; + + if (filename) fp = fopen(filename, "rb"); + else fp = NULL; + + if (fp != NULL) { + // Try reading the first 1k of data for a label... + bytes = fread(preview_text_, 1, sizeof(preview_text_) - 1, fp); + preview_text_[bytes] = '\0'; + fclose(fp); + } else { + // Assume we can't read any data... + preview_text_[0] = '\0'; + } + + window->cursor(FL_CURSOR_DEFAULT); + Fl::check(); + + // Scan the buffer for printable chars... + for (ptr = preview_text_; + *ptr && (isprint(*ptr & 255) || isspace(*ptr & 255)); + ptr ++); + + if (*ptr || ptr == preview_text_) { + // Non-printable file, just show a big ?... + previewBox->label(filename ? "?" : 0); + previewBox->align(FL_ALIGN_CLIP); + previewBox->labelsize(100); + previewBox->labelfont(FL_HELVETICA); + } else { + // Show the first 1k of text... + int size = previewBox->h() / 20; + if (size < 6) size = 6; + else if (size > 14) size = 14; + + previewBox->label(preview_text_); + previewBox->align((Fl_Align)(FL_ALIGN_CLIP | FL_ALIGN_INSIDE | + FL_ALIGN_LEFT | FL_ALIGN_TOP)); + previewBox->labelsize((uchar)size); + previewBox->labelfont(FL_COURIER); + } + } else { + pbw = previewBox->w() - 20; + pbh = previewBox->h() - 20; + + if (image->w() > pbw || image->h() > pbh) { + w = pbw; + h = w * image->h() / image->w(); + + if (h > pbh) { + h = pbh; + w = h * image->w() / image->h(); + } + + oldimage = (Fl_Shared_Image *)image->copy(w, h); + previewBox->image((Fl_Image *)oldimage); + + image->release(); + } else { + previewBox->image((Fl_Image *)image); + } + + previewBox->align(FL_ALIGN_CLIP); + previewBox->label(0); + } + + previewBox->redraw(); +} + + +// +// 'Fl_File_Chooser::value()' - Return a selected filename. +// + +const char * // O - Filename or NULL +Fl_File_Chooser::value(int f) // I - File number +{ + int i; // Looping var + int fcount; // Number of selected files + const char *name; // Current filename + static char pathname[1024]; // Filename + directory + + + name = fileName->value(); + + if (!(type_ & MULTI)) { + // Return the filename in the filename field... + if (!name || !name[0]) return NULL; + else return name; + } + + // Return a filename from the list... + for (i = 1, fcount = 0; i <= fileList->size(); i ++) + if (fileList->selected(i)) { + // See if this file is a selected file/directory... + name = fileList->text(i); + + fcount ++; + + if (fcount == f) { + if (directory_[0]) { + snprintf(pathname, sizeof(pathname), "%s/%s", directory_, name); + } else { + strlcpy(pathname, name, sizeof(pathname)); + } + + return pathname; + } + } + + // If nothing is selected, use the filename field... + if (!name || !name[0]) return NULL; + else return name; +} + + +// +// 'Fl_File_Chooser::value()' - Set the current filename. +// + +void +Fl_File_Chooser::value(const char *filename) + // I - Filename + directory +{ + int i, // Looping var + fcount; // Number of items in list + char *slash; // Directory separator + char pathname[1024]; // Local copy of filename + + +// printf("Fl_File_Chooser::value(\"%s\")\n", filename == NULL ? "(null)" : filename); + + // See if the filename is the "My System" directory... + if (filename == NULL || !filename[0]) { + // Yes, just change the current directory... + directory(filename); + fileName->value(""); + okButton->deactivate(); + return; + } + +#ifdef WIN32 + // See if the filename contains backslashes... + char fixpath[1024]; // Path with slashes converted + if (strchr(filename, '\\')) { + // Convert backslashes to slashes... + strlcpy(fixpath, filename, sizeof(fixpath)); + + for (slash = strchr(fixpath, '\\'); slash; slash = strchr(slash + 1, '\\')) + *slash = '/'; + + filename = fixpath; + } +#endif // WIN32 + + // See if there is a directory in there... + fl_filename_absolute(pathname, sizeof(pathname), filename); + + if ((slash = strrchr(pathname, '/')) != NULL) { + // Yes, change the display to the directory... + if (!fl_filename_isdir(pathname)) *slash++ = '\0'; + + directory(pathname); + if (*slash == '/') slash = pathname; + } else { + directory("."); + slash = pathname; + } + + // Set the input field to the absolute path... + if (slash > pathname) slash[-1] = '/'; + + fileName->value(pathname); + fileName->position(0, strlen(pathname)); + okButton->activate(); + + // Then find the file in the file list and select it... + fcount = fileList->size(); + + fileList->deselect(0); + fileList->redraw(); + + for (i = 1; i <= fcount; i ++) +#if defined(WIN32) || defined(__EMX__) + if (strcasecmp(fileList->text(i), slash) == 0) { +#else + if (strcmp(fileList->text(i), slash) == 0) { +#endif // WIN32 || __EMX__ +// printf("Selecting line %d...\n", i); + fileList->topline(i); + fileList->select(i); + break; + } +} + + +// +// 'compare_dirnames()' - Compare two directory names. +// + +static int +compare_dirnames(const char *a, const char *b) { + int alen, blen; + + // Get length of each string... + alen = strlen(a) - 1; + blen = strlen(b) - 1; + + if (alen < 0 || blen < 0) return alen - blen; + + // Check for trailing slashes... + if (a[alen] != '/') alen ++; + if (b[blen] != '/') blen ++; + + // If the lengths aren't the same, then return the difference... + if (alen != blen) return alen - blen; + + // Do a comparison of the first N chars (alen == blen at this point)... +#ifdef WIN32 + return strncasecmp(a, b, alen); +#else + return strncmp(a, b, alen); +#endif // WIN32 +} + + +// +// 'quote_pathname()' - Quote a pathname for a menu. +// + +static void +quote_pathname(char *dst, // O - Destination string + const char *src, // I - Source string + int dstsize) // I - Size of destination string +{ + dstsize --; + + while (*src && dstsize > 1) { + if (*src == '\\') { + // Convert backslash to forward slash... + *dst++ = '\\'; + *dst++ = '/'; + src ++; + } else { + if (*src == '/') *dst++ = '\\'; + + *dst++ = *src++; + } + } + + *dst = '\0'; +} + + +// +// 'unquote_pathname()' - Unquote a pathname from a menu. +// + +static void +unquote_pathname(char *dst, // O - Destination string + const char *src, // I - Source string + int dstsize) // I - Size of destination string +{ + dstsize --; + + while (*src && dstsize > 1) { + if (*src == '\\') src ++; + *dst++ = *src++; + } + + *dst = '\0'; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_File_Icon.cxx b/Utilities/FLTK/src/Fl_File_Icon.cxx new file mode 100644 index 0000000000..d1791d476b --- /dev/null +++ b/Utilities/FLTK/src/Fl_File_Icon.cxx @@ -0,0 +1,485 @@ +// +// "$Id$" +// +// Fl_File_Icon routines. +// +// KDE icon code donated by Maarten De Boer. +// +// Copyright 1999-2005 by Michael Sweet. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +// Contents: +// +// Fl_File_Icon::Fl_File_Icon() - Create a new file icon. +// Fl_File_Icon::~Fl_File_Icon() - Remove a file icon. +// Fl_File_Icon::add() - Add data to an icon. +// Fl_File_Icon::find() - Find an icon based upon a given file. +// Fl_File_Icon::draw() - Draw an icon. +// Fl_File_Icon::label() - Set the widgets label to an icon. +// Fl_File_Icon::labeltype() - Draw the icon label. +// + +// +// Include necessary header files... +// + +#include <stdio.h> +#include <stdlib.h> +#include "flstring.h" +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#if (defined(WIN32) && ! defined(__CYGWIN__)) || defined(__EMX__) +# include <io.h> +# define F_OK 0 +#else +# include <unistd.h> +#endif /* WIN32 || __EMX__ */ + +#include <FL/Fl_File_Icon.H> +#include <FL/Fl_Widget.H> +#include <FL/fl_draw.H> +#include <FL/filename.H> + + +// +// Define missing POSIX/XPG4 macros as needed... +// + +#ifndef S_ISDIR +# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#endif /* !S_ISDIR */ + + +// +// Icon cache... +// + +Fl_File_Icon *Fl_File_Icon::first_ = (Fl_File_Icon *)0; + + +// +// 'Fl_File_Icon::Fl_File_Icon()' - Create a new file icon. +// + +Fl_File_Icon::Fl_File_Icon(const char *p, /* I - Filename pattern */ + int t, /* I - File type */ + int nd, /* I - Number of data values */ + short *d) /* I - Data values */ +{ + // Initialize the pattern and type... + pattern_ = p; + type_ = t; + + // Copy icon data as needed... + if (nd) + { + num_data_ = nd; + alloc_data_ = nd + 1; + data_ = (short *)calloc(sizeof(short), nd + 1); + memcpy(data_, d, nd * sizeof(short)); + } + else + { + num_data_ = 0; + alloc_data_ = 0; + } + + // And add the icon to the list of icons... + next_ = first_; + first_ = this; +} + + +// +// 'Fl_File_Icon::~Fl_File_Icon()' - Remove a file icon. +// + +Fl_File_Icon::~Fl_File_Icon() +{ + Fl_File_Icon *current, // Current icon in list + *prev; // Previous icon in list + + + // Find the icon in the list... + for (current = first_, prev = (Fl_File_Icon *)0; + current != this && current != (Fl_File_Icon *)0; + prev = current, current = current->next_); + + // Remove the icon from the list as needed... + if (current) + { + if (prev) + prev->next_ = current->next_; + else + first_ = current->next_; + } + + // Free any memory used... + if (alloc_data_) + free(data_); +} + + +// +// 'Fl_File_Icon::add()' - Add data to an icon. +// + +short * // O - Pointer to new data value +Fl_File_Icon::add(short d) // I - Data to add +{ + short *dptr; // Pointer to new data value + + + // Allocate/reallocate memory as needed + if ((num_data_ + 1) >= alloc_data_) + { + alloc_data_ += 128; + + if (alloc_data_ == 128) + dptr = (short *)malloc(sizeof(short) * alloc_data_); + else + dptr = (short *)realloc(data_, sizeof(short) * alloc_data_); + + if (dptr == NULL) + return (NULL); + + data_ = dptr; + } + + // Store the new data value and return + data_[num_data_++] = d; + data_[num_data_] = END; + + return (data_ + num_data_ - 1); +} + + +// +// 'Fl_File_Icon::find()' - Find an icon based upon a given file. +// + +Fl_File_Icon * // O - Matching file icon or NULL +Fl_File_Icon::find(const char *filename,// I - Name of file */ + int filetype) // I - Enumerated file type +{ + Fl_File_Icon *current; // Current file in list +#ifndef WIN32 + struct stat fileinfo; // Information on file +#endif // !WIN32 + const char *name; // Base name of filename + + + // Get file information if needed... + if (filetype == ANY) + { +#ifdef WIN32 + if (filename[strlen(filename) - 1] == '/') + filetype = DIRECTORY; + else if (fl_filename_isdir(filename)) + filetype = DIRECTORY; + else + filetype = PLAIN; +#else + if (!stat(filename, &fileinfo)) + { + if (S_ISDIR(fileinfo.st_mode)) + filetype = DIRECTORY; +# ifdef S_IFIFO + else if (S_ISFIFO(fileinfo.st_mode)) + filetype = FIFO; +# endif // S_IFIFO +# if defined(S_ICHR) && defined(S_IBLK) + else if (S_ISCHR(fileinfo.st_mode) || S_ISBLK(fileinfo.st_mode)) + filetype = DEVICE; +# endif // S_ICHR && S_IBLK +# ifdef S_ILNK + else if (S_ISLNK(fileinfo.st_mode)) + filetype = LINK; +# endif // S_ILNK + else + filetype = PLAIN; + } + else + filetype = PLAIN; +#endif // WIN32 + } + + // Look at the base name in the filename + name = fl_filename_name(filename); + + // Loop through the available file types and return any match that + // is found... + for (current = first_; current != (Fl_File_Icon *)0; current = current->next_) + if ((current->type_ == filetype || current->type_ == ANY) && + (fl_filename_match(filename, current->pattern_) || + fl_filename_match(name, current->pattern_))) + break; + + // Return the match (if any)... + return (current); +} + + +// +// 'Fl_File_Icon::draw()' - Draw an icon. +// + +void +Fl_File_Icon::draw(int x, // I - Upper-lefthand X + int y, // I - Upper-lefthand Y + int w, // I - Width of bounding box + int h, // I - Height of bounding box + Fl_Color ic, // I - Icon color... + int active) // I - Active or inactive? +{ + Fl_Color c, // Current color + oc; // Outline color + short *d, // Pointer to data + *dend; // End of data... + short *prim; // Pointer to start of primitive... + double scale; // Scale of icon + + + // Don't try to draw a NULL array! + if (num_data_ == 0) + return; + + // Setup the transform matrix as needed... + scale = w < h ? w : h; + + fl_push_matrix(); + fl_translate((float)x + 0.5 * ((float)w - scale), + (float)y + 0.5 * ((float)h + scale)); + fl_scale(scale, -scale); + + // Loop through the array until we see an unmatched END... + d = data_; + dend = data_ + num_data_; + prim = NULL; + c = ic; + + if (active) + fl_color(c); + else + fl_color(fl_inactive(c)); + + while (d < dend) + switch (*d) + { + case END : + if (prim) + switch (*prim) + { + case LINE : + fl_end_line(); + break; + + case CLOSEDLINE : + fl_end_loop(); + break; + + case POLYGON : + fl_end_complex_polygon(); + break; + + case OUTLINEPOLYGON : + fl_end_complex_polygon(); + + oc = (Fl_Color)((((unsigned short *)prim)[1] << 16) | + ((unsigned short *)prim)[2]); + if (active) + { + if (oc == FL_ICON_COLOR) + fl_color(ic); + else + fl_color(oc); + } + else + { + if (oc == FL_ICON_COLOR) + fl_color(fl_inactive(ic)); + else + fl_color(fl_inactive(oc)); + } + + fl_begin_loop(); + + prim += 3; + while (*prim == VERTEX) + { + fl_vertex(prim[1] * 0.0001, prim[2] * 0.0001); + prim += 3; + } + + fl_end_loop(); + fl_color(c); + break; + } + + prim = NULL; + d ++; + break; + + case COLOR : + c = (Fl_Color)((((unsigned short *)d)[1] << 16) | + ((unsigned short *)d)[2]); + + if (c == FL_ICON_COLOR) + c = ic; + + if (!active) + c = fl_inactive(c); + + fl_color(c); + d += 3; + break; + + case LINE : + prim = d; + d ++; + fl_begin_line(); + break; + + case CLOSEDLINE : + prim = d; + d ++; + fl_begin_loop(); + break; + + case POLYGON : + prim = d; + d ++; + fl_begin_complex_polygon(); + break; + + case OUTLINEPOLYGON : + prim = d; + d += 3; + fl_begin_complex_polygon(); + break; + + case VERTEX : + if (prim) + fl_vertex(d[1] * 0.0001, d[2] * 0.0001); + d += 3; + break; + + default : // Ignore invalid data... + d ++; + } + + // If we still have an open primitive, close it... + if (prim) + switch (*prim) + { + case LINE : + fl_end_line(); + break; + + case CLOSEDLINE : + fl_end_loop(); + break; + + case POLYGON : + fl_end_polygon(); + break; + + case OUTLINEPOLYGON : + fl_end_polygon(); + + oc = (Fl_Color)((((unsigned short *)prim)[1] << 16) | + ((unsigned short *)prim)[2]); + if (active) + { + if (oc == FL_ICON_COLOR) + fl_color(ic); + else + fl_color(oc); + } + else + { + if (oc == FL_ICON_COLOR) + fl_color(fl_inactive(ic)); + else + fl_color(fl_inactive(oc)); + } + + fl_begin_loop(); + + prim += 3; + while (*prim == VERTEX) + { + fl_vertex(prim[1] * 0.0001, prim[2] * 0.0001); + prim += 3; + } + + fl_end_loop(); + fl_color(c); + break; + } + + // Restore the transform matrix + fl_pop_matrix(); +} + + +// +// 'Fl_File_Icon::label()' - Set the widget's label to an icon. +// + +void +Fl_File_Icon::label(Fl_Widget *w) // I - Widget to label +{ + Fl::set_labeltype(_FL_ICON_LABEL, labeltype, 0); + w->label(_FL_ICON_LABEL, (const char*)this); +} + + +// +// 'Fl_File_Icon::labeltype()' - Draw the icon label. +// + +void +Fl_File_Icon::labeltype(const Fl_Label *o, // I - Label data + int x, // I - X position of label + int y, // I - Y position of label + int w, // I - Width of label + int h, // I - Height of label + Fl_Align a) // I - Label alignment (not used) +{ + Fl_File_Icon *icon; // Pointer to icon data + + + (void)a; + + icon = (Fl_File_Icon *)(o->value); + if (icon) icon->draw(x, y, w, h, (Fl_Color)(o->color)); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_File_Icon2.cxx b/Utilities/FLTK/src/Fl_File_Icon2.cxx new file mode 100644 index 0000000000..29ab501918 --- /dev/null +++ b/Utilities/FLTK/src/Fl_File_Icon2.cxx @@ -0,0 +1,1015 @@ +// +// "$Id$" +// +// Fl_File_Icon system icon routines. +// +// KDE icon code donated by Maarten De Boer. +// +// Copyright 1999-2005 by Michael Sweet. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +// Contents: +// +// Fl_File_Icon::load() - Load an icon file... +// Fl_File_Icon::load_fti() - Load an SGI-format FTI file... +// Fl_File_Icon::load_image() - Load an image icon file... +// Fl_File_Icon::load_system_icons() - Load the standard system icons/filetypes. +// load_kde_icons() - Load KDE icon files. +// load_kde_mimelnk() - Load a KDE "mimelnk" file. +// kde_to_fltk_pattern() - Convert a KDE pattern to a FLTK pattern. +// get_kde_val() - Get a KDE value. +// + +// +// Include necessary header files... +// + +#include <stdio.h> +#include <stdlib.h> +#include "flstring.h" +#include <ctype.h> +#include <errno.h> +#include <FL/math.h> +#include <sys/types.h> +#include <sys/stat.h> +#if defined(WIN32) && !defined(__CYGWIN__) +# include <io.h> +# define F_OK 0 +// Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs +// on Windows, which is supposed to be POSIX compliant... +# define access _access +#else +# include <unistd.h> +#endif // WIN32 + +#include <FL/Fl_File_Icon.H> +#include <FL/Fl_Shared_Image.H> +#include <FL/Fl_Widget.H> +#include <FL/fl_draw.H> +#include <FL/filename.H> + + +// +// Define missing POSIX/XPG4 macros as needed... +// + +#ifndef S_ISDIR +# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#endif /* !S_ISDIR */ + + +// +// Local functions... +// + +static void load_kde_icons(const char *directory, const char *icondir); +static void load_kde_mimelnk(const char *filename, const char *icondir); +static char *kde_to_fltk_pattern(const char *kdepattern); +static char *get_kde_val(char *str, const char *key); + + +// +// Local globals... +// + +static const char *kdedir = NULL; + + +// +// 'Fl_File_Icon::load()' - Load an icon file... +// + +void +Fl_File_Icon::load(const char *f) // I - File to read from +{ + int i; // Load status... + const char *ext; // File extension + + + ext = fl_filename_ext(f); + + if (ext && strcmp(ext, ".fti") == 0) + i = load_fti(f); + else + i = load_image(f); + + if (i) + { + Fl::warning("Fl_File_Icon::load(): Unable to load icon file \"%s\".", f); + return; + } +} + + +// +// 'Fl_File_Icon::load_fti()' - Load an SGI-format FTI file... +// + +int // O - 0 on success, non-zero on error +Fl_File_Icon::load_fti(const char *fti) // I - File to read from +{ + FILE *fp; // File pointer + int ch; // Current character + char command[255], // Command string ("vertex", etc.) + params[255], // Parameter string ("10.0,20.0", etc.) + *ptr; // Pointer into strings + int outline; // Outline polygon + + + // Try to open the file... + if ((fp = fopen(fti, "rb")) == NULL) + { + Fl::error("Fl_File_Icon::load_fti(): Unable to open \"%s\" - %s", + fti, strerror(errno)); + return -1; + } + + // Read the entire file, adding data as needed... + outline = 0; + + while ((ch = getc(fp)) != EOF) + { + // Skip whitespace + if (isspace(ch)) + continue; + + // Skip comments starting with "#"... + if (ch == '#') + { + while ((ch = getc(fp)) != EOF) + if (ch == '\n') + break; + + if (ch == EOF) + break; + else + continue; + } + + // OK, this character better be a letter... + if (!isalpha(ch)) + { + Fl::error("Fl_File_Icon::load_fti(): Expected a letter at file position %ld (saw '%c')", + ftell(fp) - 1, ch); + break; + } + + // Scan the command name... + ptr = command; + *ptr++ = ch; + + while ((ch = getc(fp)) != EOF) + { + if (ch == '(') + break; + else if (ptr < (command + sizeof(command) - 1)) + *ptr++ = ch; + } + + *ptr++ = '\0'; + + // Make sure we stopped on a parenthesis... + if (ch != '(') + { + Fl::error("Fl_File_Icon::load_fti(): Expected a ( at file position %ld (saw '%c')", + ftell(fp) - 1, ch); + break; + } + + // Scan the parameters... + ptr = params; + + while ((ch = getc(fp)) != EOF) + { + if (ch == ')') + break; + else if (ptr < (params + sizeof(params) - 1)) + *ptr++ = ch; + } + + *ptr++ = '\0'; + + // Make sure we stopped on a parenthesis... + if (ch != ')') + { + Fl::error("Fl_File_Icon::load_fti(): Expected a ) at file position %ld (saw '%c')", + ftell(fp) - 1, ch); + break; + } + + // Make sure the next character is a semicolon... + if ((ch = getc(fp)) != ';') + { + Fl::error("Fl_File_Icon::load_fti(): Expected a ; at file position %ld (saw '%c')", + ftell(fp) - 1, ch); + break; + } + + // Now process the command... + if (strcmp(command, "color") == 0) + { + // Set the color; for negative colors blend the two primaries to + // produce a composite color. Also, the following symbolic color + // names are understood: + // + // name FLTK color + // ------------- ---------- + // iconcolor FL_ICON_COLOR; mapped to the icon color in + // Fl_File_Icon::draw() + // shadowcolor FL_DARK3 + // outlinecolor FL_BLACK + if (strcmp(params, "iconcolor") == 0) + add_color(FL_ICON_COLOR); + else if (strcmp(params, "shadowcolor") == 0) + add_color(FL_DARK3); + else if (strcmp(params, "outlinecolor") == 0) + add_color(FL_BLACK); + else + { + int c = atoi(params); // Color value + + + if (c < 0) + { + // Composite color; compute average... + c = -c; + add_color(fl_color_average((Fl_Color)(c >> 4), + (Fl_Color)(c & 15), 0.5f)); + } + else + add_color((Fl_Color)c); + } + } + else if (strcmp(command, "bgnline") == 0) + add(LINE); + else if (strcmp(command, "bgnclosedline") == 0) + add(CLOSEDLINE); + else if (strcmp(command, "bgnpolygon") == 0) + add(POLYGON); + else if (strcmp(command, "bgnoutlinepolygon") == 0) + { + add(OUTLINEPOLYGON); + outline = add(0) - data_; + add(0); + } + else if (strcmp(command, "endoutlinepolygon") == 0 && outline) + { + unsigned cval; // Color value + + // Set the outline color; see above for valid values... + if (strcmp(params, "iconcolor") == 0) + cval = FL_ICON_COLOR; + else if (strcmp(params, "shadowcolor") == 0) + cval = FL_DARK3; + else if (strcmp(params, "outlinecolor") == 0) + cval = FL_BLACK; + else + { + int c = atoi(params); // Color value + + + if (c < 0) + { + // Composite color; compute average... + c = -c; + cval = fl_color_average((Fl_Color)(c >> 4), (Fl_Color)(c & 15), 0.5f); + } + else + cval = c; + } + + // Store outline color... + data_[outline] = cval >> 16; + data_[outline + 1] = cval; + + outline = 0; + add(END); + } + else if (strncmp(command, "end", 3) == 0) + add(END); + else if (strcmp(command, "vertex") == 0) + { + float x, y; // Coordinates of vertex + + + if (sscanf(params, "%f,%f", &x, &y) != 2) + break; + + add_vertex((short)(int)rint(x * 100.0), (short)(int)rint(y * 100.0)); + } + else + { + Fl::error("Fl_File_Icon::load_fti(): Unknown command \"%s\" at file position %ld.", + command, ftell(fp) - 1); + break; + } + } + + // Close the file and return... + fclose(fp); + +#ifdef DEBUG + printf("Icon File \"%s\":\n", fti); + for (int i = 0; i < num_data_; i ++) + printf(" %d,\n", data_[i]); +#endif /* DEBUG */ + + return 0; +} + + +// +// 'Fl_File_Icon::load_image()' - Load an image icon file... +// + +int // O - 0 on success, non-0 on error +Fl_File_Icon::load_image(const char *ifile) // I - File to read from +{ + Fl_Shared_Image *img; // Image file + + + img = Fl_Shared_Image::get(ifile); + if (!img || !img->count() || !img->w() || !img->h()) return -1; + + if (img->count() == 1) { + int x, y; // X & Y in image + int startx; // Starting X coord + Fl_Color c, // Current color + temp; // Temporary color + const uchar *row; // Pointer into image + + + // Loop through grayscale or RGB image... + for (y = 0, row = (const uchar *)(*(img->data())); y < img->h(); y ++, row += img->ld()) + { + for (x = 0, startx = 0, c = (Fl_Color)-1; + x < img->w(); + x ++, row += img->d()) + { + switch (img->d()) + { + case 1 : + temp = fl_rgb_color(row[0], row[0], row[0]); + break; + case 2 : + if (row[1] > 127) + temp = fl_rgb_color(row[0], row[0], row[0]); + else + temp = (Fl_Color)-1; + break; + case 3 : + temp = fl_rgb_color(row[0], row[1], row[2]); + break; + default : + if (row[3] > 127) + temp = fl_rgb_color(row[0], row[1], row[2]); + else + temp = (Fl_Color)-1; + break; + } + + if (temp != c) + { + if (x > startx && c != (Fl_Color)-1) + { + add_color(c); + add(POLYGON); + add_vertex(startx * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h()); + add_vertex(x * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h()); + add_vertex(x * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h()); + add_vertex(startx * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h()); + add(END); + } + + c = temp; + startx = x; + } + } + + if (x > startx && c != (Fl_Color)-1) + { + add_color(c); + add(POLYGON); + add_vertex(startx * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h()); + add_vertex(x * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h()); + add_vertex(x * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h()); + add_vertex(startx * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h()); + add(END); + } + } + } else { + int i, j; // Looping vars + int ch; // Current character + int newch; // New character + int bg; // Background color + char val[16]; // Color value + const char *lineptr, // Pointer into line + *const*ptr; // Pointer into data array + int ncolors, // Number of colors + chars_per_color; // Characters per color + Fl_Color *colors; // Colors + int red, green, blue; // Red, green, and blue values + int x, y; // X & Y in image + int startx; // Starting X coord + + + // Get the pixmap data... + ptr = img->data(); + sscanf(*ptr, "%*d%*d%d%d", &ncolors, &chars_per_color); + + colors = new Fl_Color[1 << (chars_per_color * 8)]; + + // Read the colormap... + memset(colors, 0, sizeof(Fl_Color) << (chars_per_color * 8)); + bg = ' '; + + ptr ++; + + if (ncolors < 0) { + // Read compressed colormap... + const uchar *cmapptr; + + ncolors = -ncolors; + + for (i = 0, cmapptr = (const uchar *)*ptr; i < ncolors; i ++, cmapptr += 4) + colors[cmapptr[0]] = fl_rgb_color(cmapptr[1], cmapptr[2], cmapptr[3]); + + ptr ++; + } else { + for (i = 0; i < ncolors; i ++, ptr ++) { + // Get the color's character + lineptr = *ptr; + ch = *lineptr++; + + if (chars_per_color > 1) ch = (ch << 8) | *lineptr++; + + // Get the color value... + if ((lineptr = strstr(lineptr, "c ")) == NULL) { + // No color; make this black... + colors[ch] = FL_BLACK; + } else if (lineptr[2] == '#') { + // Read the RGB triplet... + lineptr += 3; + for (j = 0; j < 12; j ++) + if (!isxdigit(lineptr[j])) + break; + + switch (j) { + case 0 : + bg = ch; + default : + red = green = blue = 0; + break; + + case 3 : + val[0] = lineptr[0]; + val[1] = '\0'; + red = 255 * strtol(val, NULL, 16) / 15; + + val[0] = lineptr[1]; + val[1] = '\0'; + green = 255 * strtol(val, NULL, 16) / 15; + + val[0] = lineptr[2]; + val[1] = '\0'; + blue = 255 * strtol(val, NULL, 16) / 15; + break; + + case 6 : + case 9 : + case 12 : + j /= 3; + + val[0] = lineptr[0]; + val[1] = lineptr[1]; + val[2] = '\0'; + red = strtol(val, NULL, 16); + + val[0] = lineptr[j + 0]; + val[1] = lineptr[j + 1]; + val[2] = '\0'; + green = strtol(val, NULL, 16); + + val[0] = lineptr[2 * j + 0]; + val[1] = lineptr[2 * j + 1]; + val[2] = '\0'; + blue = strtol(val, NULL, 16); + break; + } + + colors[ch] = fl_rgb_color((uchar)red, (uchar)green, (uchar)blue); + } else { + // Read a color name... + if (strncasecmp(lineptr + 2, "white", 5) == 0) colors[ch] = FL_WHITE; + else if (strncasecmp(lineptr + 2, "black", 5) == 0) colors[ch] = FL_BLACK; + else if (strncasecmp(lineptr + 2, "none", 4) == 0) { + colors[ch] = FL_BLACK; + bg = ch; + } else colors[ch] = FL_GRAY; + } + } + } + + // Read the image data... + for (y = 0; y < img->h(); y ++, ptr ++) { + lineptr = *ptr; + startx = 0; + ch = bg; + + for (x = 0; x < img->w(); x ++) { + newch = *lineptr++; + + if (chars_per_color > 1) newch = (newch << 8) | *lineptr++; + + if (newch != ch) { + if (ch != bg) { + add_color(colors[ch]); + add(POLYGON); + add_vertex(startx * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h()); + add_vertex(x * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h()); + add_vertex(x * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h()); + add_vertex(startx * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h()); + add(END); + } + + ch = newch; + startx = x; + } + } + + if (ch != bg) { + add_color(colors[ch]); + add(POLYGON); + add_vertex(startx * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h()); + add_vertex(x * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h()); + add_vertex(x * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h()); + add_vertex(startx * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h()); + add(END); + } + } + + // Free the colormap... + delete[] colors; + } + + img->release(); + +#ifdef DEBUG + printf("Icon File \"%s\":\n", xpm); + for (i = 0; i < num_data_; i ++) + printf(" %d,\n", data_[i]); +#endif // DEBUG + + return 0; +} + + +// +// 'Fl_File_Icon::load_system_icons()' - Load the standard system icons/filetypes. + +void +Fl_File_Icon::load_system_icons(void) { + int i; // Looping var + Fl_File_Icon *icon; // New icons + char filename[1024]; // Filename + char icondir[1024]; // Icon directory + static int init = 0; // Have the icons been initialized? + const char * const icondirs[] = { + "Bluecurve", // Icon directories to look for, in order + "crystalsvg", + "default.kde", + "hicolor", + NULL + }; + static short plain[] = { // Plain file icon + COLOR, -1, -1, OUTLINEPOLYGON, 0, FL_GRAY, + VERTEX, 2000, 1000, VERTEX, 2000, 9000, + VERTEX, 6000, 9000, VERTEX, 8000, 7000, + VERTEX, 8000, 1000, END, OUTLINEPOLYGON, 0, FL_GRAY, + VERTEX, 6000, 9000, VERTEX, 6000, 7000, + VERTEX, 8000, 7000, END, + COLOR, 0, FL_BLACK, LINE, VERTEX, 6000, 7000, + VERTEX, 8000, 7000, VERTEX, 8000, 1000, + VERTEX, 2000, 1000, END, LINE, VERTEX, 3000, 7000, + VERTEX, 5000, 7000, END, LINE, VERTEX, 3000, 6000, + VERTEX, 5000, 6000, END, LINE, VERTEX, 3000, 5000, + VERTEX, 7000, 5000, END, LINE, VERTEX, 3000, 4000, + VERTEX, 7000, 4000, END, LINE, VERTEX, 3000, 3000, + VERTEX, 7000, 3000, END, LINE, VERTEX, 3000, 2000, + VERTEX, 7000, 2000, END, + END + }; + static short image[] = { // Image file icon + COLOR, -1, -1, OUTLINEPOLYGON, 0, FL_GRAY, + VERTEX, 2000, 1000, VERTEX, 2000, 9000, + VERTEX, 6000, 9000, VERTEX, 8000, 7000, + VERTEX, 8000, 1000, END, OUTLINEPOLYGON, 0, FL_GRAY, + VERTEX, 6000, 9000, VERTEX, 6000, 7000, + VERTEX, 8000, 7000, END, + COLOR, 0, FL_BLACK, LINE, VERTEX, 6000, 7000, + VERTEX, 8000, 7000, VERTEX, 8000, 1000, + VERTEX, 2000, 1000, END, + COLOR, 0, FL_RED, POLYGON, VERTEX, 3500, 2500, + VERTEX, 3000, 3000, VERTEX, 3000, 4000, + VERTEX, 3500, 4500, VERTEX, 4500, 4500, + VERTEX, 5000, 4000, VERTEX, 5000, 3000, + VERTEX, 4500, 2500, END, + COLOR, 0, FL_GREEN, POLYGON, VERTEX, 5500, 2500, + VERTEX, 5000, 3000, VERTEX, 5000, 4000, + VERTEX, 5500, 4500, VERTEX, 6500, 4500, + VERTEX, 7000, 4000, VERTEX, 7000, 3000, + VERTEX, 6500, 2500, END, + COLOR, 0, FL_BLUE, POLYGON, VERTEX, 4500, 3500, + VERTEX, 4000, 4000, VERTEX, 4000, 5000, + VERTEX, 4500, 5500, VERTEX, 5500, 5500, + VERTEX, 6000, 5000, VERTEX, 6000, 4000, + VERTEX, 5500, 3500, END, + END + }; + static short dir[] = { // Directory icon + COLOR, -1, -1, POLYGON, VERTEX, 1000, 1000, + VERTEX, 1000, 7500, VERTEX, 9000, 7500, + VERTEX, 9000, 1000, END, + POLYGON, VERTEX, 1000, 7500, VERTEX, 2500, 9000, + VERTEX, 5000, 9000, VERTEX, 6500, 7500, END, + COLOR, 0, FL_WHITE, LINE, VERTEX, 1500, 1500, + VERTEX, 1500, 7000, VERTEX, 9000, 7000, END, + COLOR, 0, FL_BLACK, LINE, VERTEX, 9000, 7500, + VERTEX, 9000, 1000, VERTEX, 1000, 1000, END, + COLOR, 0, FL_GRAY, LINE, VERTEX, 1000, 1000, + VERTEX, 1000, 7500, VERTEX, 2500, 9000, + VERTEX, 5000, 9000, VERTEX, 6500, 7500, + VERTEX, 9000, 7500, END, + END + }; + + + // Add symbols if they haven't been added already... + if (!init) { + // This method requires the images library... + fl_register_images(); + + if (!kdedir) { + // Figure out where KDE is installed... + if ((kdedir = getenv("KDEDIR")) == NULL) { + if (!access("/opt/kde", F_OK)) kdedir = "/opt/kde"; + else if (!access("/usr/local/share/mimelnk", F_OK)) kdedir = "/usr/local"; + else kdedir = "/usr"; + } + } + + snprintf(filename, sizeof(filename), "%s/share/mimelnk", kdedir); + + if (!access(filename, F_OK)) { + // Load KDE icons... + icon = new Fl_File_Icon("*", Fl_File_Icon::PLAIN); + + for (i = 0; icondirs[i]; i ++) { + snprintf(icondir, sizeof(icondir), "%s/share/icons/%s", kdedir, + icondirs[i]); + + if (!access(icondir, F_OK)) break; + } + + if (icondirs[i]) { + snprintf(filename, sizeof(filename), "%s/16x16/mimetypes/unknown.png", + icondir); + } else { + snprintf(filename, sizeof(filename), "%s/share/icons/unknown.xpm", + kdedir); + } + + if (!access(filename, F_OK)) icon->load_image(filename); + + icon = new Fl_File_Icon("*", Fl_File_Icon::LINK); + + snprintf(filename, sizeof(filename), "%s/16x16/filesystems/link.png", + icondir); + + if (!access(filename, F_OK)) icon->load_image(filename); + + snprintf(filename, sizeof(filename), "%s/share/mimelnk", kdedir); + load_kde_icons(filename, icondir); + } else if (!access("/usr/share/icons/folder.xpm", F_OK)) { + // Load GNOME icons... + icon = new Fl_File_Icon("*", Fl_File_Icon::PLAIN); + icon->load_image("/usr/share/icons/page.xpm"); + + icon = new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY); + icon->load_image("/usr/share/icons/folder.xpm"); + } else if (!access("/usr/dt/appconfig/icons", F_OK)) { + // Load CDE icons... + icon = new Fl_File_Icon("*", Fl_File_Icon::PLAIN); + icon->load_image("/usr/dt/appconfig/icons/C/Dtdata.m.pm"); + + icon = new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY); + icon->load_image("/usr/dt/appconfig/icons/C/DtdirB.m.pm"); + + icon = new Fl_File_Icon("core", Fl_File_Icon::PLAIN); + icon->load_image("/usr/dt/appconfig/icons/C/Dtcore.m.pm"); + + icon = new Fl_File_Icon("*.{bmp|bw|gif|jpg|pbm|pcd|pgm|ppm|png|ras|rgb|tif|xbm|xpm}", Fl_File_Icon::PLAIN); + icon->load_image("/usr/dt/appconfig/icons/C/Dtimage.m.pm"); + + icon = new Fl_File_Icon("*.{eps|pdf|ps}", Fl_File_Icon::PLAIN); + icon->load_image("/usr/dt/appconfig/icons/C/Dtps.m.pm"); + + icon = new Fl_File_Icon("*.ppd", Fl_File_Icon::PLAIN); + icon->load_image("/usr/dt/appconfig/icons/C/DtPrtpr.m.pm"); + } else if (!access("/usr/lib/filetype", F_OK)) { + // Load SGI icons... + icon = new Fl_File_Icon("*", Fl_File_Icon::PLAIN); + icon->load_fti("/usr/lib/filetype/iconlib/generic.doc.fti"); + + icon = new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY); + icon->load_fti("/usr/lib/filetype/iconlib/generic.folder.closed.fti"); + + icon = new Fl_File_Icon("core", Fl_File_Icon::PLAIN); + icon->load_fti("/usr/lib/filetype/default/iconlib/CoreFile.fti"); + + icon = new Fl_File_Icon("*.{bmp|bw|gif|jpg|pbm|pcd|pgm|ppm|png|ras|rgb|tif|xbm|xpm}", Fl_File_Icon::PLAIN); + icon->load_fti("/usr/lib/filetype/system/iconlib/ImageFile.fti"); + + if (!access("/usr/lib/filetype/install/iconlib/acroread.doc.fti", F_OK)) { + icon = new Fl_File_Icon("*.{eps|ps}", Fl_File_Icon::PLAIN); + icon->load_fti("/usr/lib/filetype/system/iconlib/PostScriptFile.closed.fti"); + + icon = new Fl_File_Icon("*.pdf", Fl_File_Icon::PLAIN); + icon->load_fti("/usr/lib/filetype/install/iconlib/acroread.doc.fti"); + } else { + icon = new Fl_File_Icon("*.{eps|pdf|ps}", Fl_File_Icon::PLAIN); + icon->load_fti("/usr/lib/filetype/system/iconlib/PostScriptFile.closed.fti"); + } + + if (!access("/usr/lib/filetype/install/iconlib/html.fti", F_OK)) { + icon = new Fl_File_Icon("*.{htm|html|shtml}", Fl_File_Icon::PLAIN); + icon->load_fti("/usr/lib/filetype/iconlib/generic.doc.fti"); + icon->load_fti("/usr/lib/filetype/install/iconlib/html.fti"); + } + + if (!access("/usr/lib/filetype/install/iconlib/color.ps.idle.fti", F_OK)) { + icon = new Fl_File_Icon("*.ppd", Fl_File_Icon::PLAIN); + icon->load_fti("/usr/lib/filetype/install/iconlib/color.ps.idle.fti"); + } + } else { + // Create the default icons... + new Fl_File_Icon("*", Fl_File_Icon::PLAIN, sizeof(plain) / sizeof(plain[0]), plain); + new Fl_File_Icon("*.{bm|bmp|bw|gif|jpg|pbm|pcd|pgm|ppm|png|ras|rgb|tif|xbm|xpm}", Fl_File_Icon::PLAIN, + sizeof(image) / sizeof(image[0]), image); + new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY, sizeof(dir) / sizeof(dir[0]), dir); + } + + // Mark things as initialized... + init = 1; + +#ifdef DEBUG + int count; + Fl_File_Icon *temp; + for (count = 0, temp = first_; temp; temp = temp->next_, count ++); + printf("count of Fl_File_Icon's is %d...\n", count); +#endif // DEBUG + } +} + + +// +// 'load_kde_icons()' - Load KDE icon files. +// + +static void +load_kde_icons(const char *directory, // I - Directory to load + const char *icondir) { // I - Location of icons + int i; // Looping var + int n; // Number of entries in directory + dirent **entries; // Entries in directory + char full[1024]; // Full name of file + + + entries = (dirent **)0; + n = fl_filename_list(directory, &entries); + + for (i = 0; i < n; i ++) { + if (entries[i]->d_name[0] != '.') { + snprintf(full, sizeof(full), "%s/%s", directory, entries[i]->d_name); + + if (fl_filename_isdir(full)) load_kde_icons(full, icondir); + else load_kde_mimelnk(full, icondir); + } + + free((void *)entries[i]); + } + + free((void*)entries); +} + + +// +// 'load_kde_mimelnk()' - Load a KDE "mimelnk" file. +// + +static void +load_kde_mimelnk(const char *filename, // I - mimelnk filename + const char *icondir) { // I - Location of icons + FILE *fp; + char tmp[1024]; + char iconfilename[1024]; + char pattern[1024]; + char mimetype[1024]; + char *val; + char full_iconfilename[1024]; + Fl_File_Icon *icon; + + + mimetype[0] = '\0'; + pattern[0] = '\0'; + iconfilename[0] = '\0'; + + if ((fp = fopen(filename, "rb")) != NULL) { + while (fgets(tmp, sizeof(tmp), fp)) { + if ((val = get_kde_val(tmp, "Icon")) != NULL) + strlcpy(iconfilename, val, sizeof(iconfilename)); + else if ((val = get_kde_val(tmp, "MimeType")) != NULL) + strlcpy(mimetype, val, sizeof(mimetype)); + else if ((val = get_kde_val(tmp, "Patterns")) != NULL) + strlcpy(pattern, val, sizeof(pattern)); + } + + fclose(fp); + +#ifdef DEBUG + printf("%s: Icon=\"%s\", MimeType=\"%s\", Patterns=\"%s\"\n", filename, + iconfilename, mimetype, pattern); +#endif // DEBUG + + if (!pattern[0] && strncmp(mimetype, "inode/", 6)) return; + + if (iconfilename[0]) { + if (iconfilename[0] == '/') { + strlcpy(full_iconfilename, iconfilename, sizeof(full_iconfilename)); + } else if (!access(icondir, F_OK)) { + // KDE 3.x and 2.x icons + int i; // Looping var + static const char *paths[] = { // Subdirs to look in... + "16x16/actions", + "16x16/apps", + "16x16/devices", + "16x16/filesystems", + "16x16/mimetypes", +/* + "20x20/actions", + "20x20/apps", + "20x20/devices", + "20x20/filesystems", + "20x20/mimetypes", + + "22x22/actions", + "22x22/apps", + "22x22/devices", + "22x22/filesystems", + "22x22/mimetypes", + + "24x24/actions", + "24x24/apps", + "24x24/devices", + "24x24/filesystems", + "24x24/mimetypes", +*/ + "32x32/actions", + "32x32/apps", + "32x32/devices", + "32x32/filesystems", + "32x32/mimetypes", +/* + "36x36/actions", + "36x36/apps", + "36x36/devices", + "36x36/filesystems", + "36x36/mimetypes", + + "48x48/actions", + "48x48/apps", + "48x48/devices", + "48x48/filesystems", + "48x48/mimetypes", + + "64x64/actions", + "64x64/apps", + "64x64/devices", + "64x64/filesystems", + "64x64/mimetypes", + + "96x96/actions", + "96x96/apps", + "96x96/devices", + "96x96/filesystems", + "96x96/mimetypes" +*/ }; + + for (i = 0; i < (int)(sizeof(paths) / sizeof(paths[0])); i ++) { + snprintf(full_iconfilename, sizeof(full_iconfilename), + "%s/%s/%s.png", icondir, paths[i], iconfilename); + + if (!access(full_iconfilename, F_OK)) break; + } + + if (i >= (int)(sizeof(paths) / sizeof(paths[0]))) return; + } else { + // KDE 1.x icons + snprintf(full_iconfilename, sizeof(full_iconfilename), + "%s/%s", tmp, iconfilename); + + if (access(full_iconfilename, F_OK)) return; + } + + if (strncmp(mimetype, "inode/", 6) == 0) { + if (!strcmp(mimetype + 6, "directory")) + icon = new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY); + else if (!strcmp(mimetype + 6, "blockdevice")) + icon = new Fl_File_Icon("*", Fl_File_Icon::DEVICE); + else if (!strcmp(mimetype + 6, "fifo")) + icon = new Fl_File_Icon("*", Fl_File_Icon::FIFO); + else return; + } else { + icon = new Fl_File_Icon(kde_to_fltk_pattern(pattern), + Fl_File_Icon::PLAIN); + } + + icon->load(full_iconfilename); + } + } +} + + +// +// 'kde_to_fltk_pattern()' - Convert a KDE pattern to a FLTK pattern. +// + +static char * +kde_to_fltk_pattern(const char *kdepattern) { + char *pattern, + *patptr; + + + pattern = (char *)malloc(strlen(kdepattern) + 3); + strcpy(pattern, "{"); + strcpy(pattern + 1, kdepattern); + + if (pattern[strlen(pattern) - 1] == ';') pattern[strlen(pattern) - 1] = '\0'; + + strcat(pattern, "}"); + + for (patptr = pattern; *patptr; patptr ++) { + if (*patptr == ';') *patptr = '|'; + } + + return (pattern); +} + + +// +// 'get_kde_val()' - Get a KDE value. +// + +static char * +get_kde_val(char *str, + const char *key) { + while (*str == *key) { + str ++; + key ++; + } + + if (*key == '\0' && *str == '=') { + if (str[strlen(str) - 1] == '\n') str[strlen(str) - 1] = '\0'; + + return (str + 1); + } + + return ((char *)0); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_File_Input.cxx b/Utilities/FLTK/src/Fl_File_Input.cxx new file mode 100644 index 0000000000..45625b5ee1 --- /dev/null +++ b/Utilities/FLTK/src/Fl_File_Input.cxx @@ -0,0 +1,283 @@ +// +// "$Id$" +// +// File_Input header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// Original version Copyright 1998 by Curtis Edwards. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_File_Input.H> +#include <FL/Fl_Window.H> +#include <FL/fl_draw.H> +#include <stdio.h> +#include "flstring.h" + + +// +// Height of directory buttons... +// + +#define DIR_HEIGHT 10 + + +// +// Redraw bit for directory bar... +// + +#define FL_DAMAGE_BAR 0x10 + + +// +// 'Fl_File_Input::Fl_File_Input()' - Create a Fl_File_Input widget. +// + +Fl_File_Input::Fl_File_Input(int X, int Y, int W, int H, const char *l) + : Fl_Input(X, Y, W, H, l) { + buttons_[0] = 0; + errorcolor_ = FL_RED; + ok_entry_ = 1; + pressed_ = -1; + + down_box(FL_UP_BOX); +} + +// +// 'Fl_File_Input::draw_buttons()' - Draw directory buttons. +// + +void +Fl_File_Input::draw_buttons() { + int i, // Looping var + X; // Current X position + + + if (damage() & (FL_DAMAGE_BAR | FL_DAMAGE_ALL)) { + update_buttons(); + } + + for (X = 0, i = 0; buttons_[i]; i ++) + { + if ((X + buttons_[i]) > xscroll()) { + if (X < xscroll()) { + draw_box(pressed_ == i ? fl_down(down_box()) : down_box(), + x(), y(), X + buttons_[i] - xscroll(), DIR_HEIGHT, FL_GRAY); + } else if ((X + buttons_[i] - xscroll()) > w()) { + draw_box(pressed_ == i ? fl_down(down_box()) : down_box(), + x() + X - xscroll(), y(), w() - X + xscroll(), DIR_HEIGHT, + FL_GRAY); + } else { + draw_box(pressed_ == i ? fl_down(down_box()) : down_box(), + x() + X - xscroll(), y(), buttons_[i], DIR_HEIGHT, FL_GRAY); + } + } + + X += buttons_[i]; + } + + if (X < w()) { + draw_box(pressed_ == i ? fl_down(down_box()) : down_box(), + x() + X - xscroll(), y(), w() - X + xscroll(), DIR_HEIGHT, FL_GRAY); + } +} + +// +// 'Fl_File_Input::update_buttons()' - Update the sizes of the directory buttons. +// + +void +Fl_File_Input::update_buttons() { + int i; // Looping var + const char *start, // Start of path component + *end; // End of path component + + +// puts("update_buttons()"); + + // Set the current font & size... + fl_font(textfont(), textsize()); + + // Loop through the value string, setting widths... + for (i = 0, start = value(); + start && i < (int)(sizeof(buttons_) / sizeof(buttons_[0]) - 1); + start = end, i ++) { +// printf(" start = \"%s\"\n", start); + if ((end = strchr(start, '/')) == NULL) +#if defined(WIN32) || defined(__EMX__) + if ((end = strchr(start, '\\')) == NULL) +#endif // WIN32 || __EMX__ + break; + + end ++; + + buttons_[i] = (short)fl_width(start, end - start); + if (!i) buttons_[i] += Fl::box_dx(box()) + 6; + } + +// printf(" found %d components/buttons...\n", i); + + buttons_[i] = 0; +} + + +// +// 'Fl_File_Input::value()' - Set the value of the widget... +// + +int // O - TRUE on success +Fl_File_Input::value(const char *str, // I - New string value + int len) { // I - Length of value + damage(FL_DAMAGE_BAR); + return Fl_Input::value(str,len); +} + + +int // O - TRUE on success +Fl_File_Input::value(const char *str) { // I - New string value + damage(FL_DAMAGE_BAR); + return Fl_Input::value(str); +} + + +// +// 'Fl_File_Input::draw()' - Draw the file input widget... +// + +void +Fl_File_Input::draw() { + Fl_Boxtype b = box(); + if (damage() & (FL_DAMAGE_BAR | FL_DAMAGE_ALL)) draw_buttons(); + // this flag keeps Fl_Input_::drawtext from drawing a bogus box! + char must_trick_fl_input_ = + Fl::focus()!=this && !size() && !(damage()&FL_DAMAGE_ALL); + if ((damage() & FL_DAMAGE_ALL) || must_trick_fl_input_) + draw_box(b,x(),y()+DIR_HEIGHT,w(),h()-DIR_HEIGHT,color()); + if (!must_trick_fl_input_) + Fl_Input_::drawtext(x()+Fl::box_dx(b)+3, y()+Fl::box_dy(b)+DIR_HEIGHT, + w()-Fl::box_dw(b)-6, h()-Fl::box_dh(b)-DIR_HEIGHT); +} + + +// +// 'Fl_File_Input::handle()' - Handle events in the widget... +// + +int // O - TRUE if we handled event +Fl_File_Input::handle(int event) // I - Event +{ +// printf("handle(event = %d)\n", event); + + switch (event) { + case FL_MOVE : + case FL_ENTER : + if (active_r()) { + if (Fl::event_y() < (y() + DIR_HEIGHT)) window()->cursor(FL_CURSOR_DEFAULT); + else window()->cursor(FL_CURSOR_INSERT); + } + + return 1; + + case FL_PUSH : + case FL_RELEASE : + case FL_DRAG : + if (Fl::event_y() < (y() + DIR_HEIGHT) || pressed_ >= 0) return handle_button(event); + + return Fl_Input::handle(event); + + default : + if (Fl_Input::handle(event)) { + damage(FL_DAMAGE_BAR); + return 1; + } + + return 0; + } +} + + +// +// 'Fl_File_Input::handle_button()' - Handle button events in the widget... +// + +int // O - TRUE if we handled event +Fl_File_Input::handle_button(int event) // I - Event +{ + int i, // Looping var + X; // Current X position + char *start, // Start of path component + *end; // End of path component + char newvalue[1024]; // New value + + + // Figure out which button is being pressed... + for (X = 0, i = 0; buttons_[i]; i ++) + { + X += buttons_[i]; + + if (X > xscroll() && Fl::event_x() < (x() + X - xscroll())) break; + } + +// printf("handle_button(event = %d), button = %d\n", event, i); + + // Redraw the directory bar... + if (event == FL_RELEASE) pressed_ = -1; + else pressed_ = (short)i; + + window()->make_current(); + draw_buttons(); + + // Return immediately if the user is clicking on the last button or + // has not released the mouse button... + if (!buttons_[i] || event != FL_RELEASE) return 1; + + // Figure out where to truncate the path... + strlcpy(newvalue, value(), sizeof(newvalue)); + + for (start = newvalue, end = start; start && i >= 0; start = end, i --) { +// printf(" start = \"%s\"\n", start); + if ((end = strchr(start, '/')) == NULL) +#if defined(WIN32) || defined(__EMX__) + if ((end = strchr(start, '\\')) == NULL) +#endif // WIN32 || __EMX__ + break; + + end ++; + } + + if (i < 0) { + // Found the end; truncate the value and update the buttons... + *start = '\0'; + value(newvalue, start - newvalue); + + // Then do the callbacks, if necessary... + set_changed(); + if (when() & FL_WHEN_CHANGED) do_callback(); + } + + return 1; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Font.H b/Utilities/FLTK/src/Fl_Font.H new file mode 100644 index 0000000000..bc93e29970 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Font.H @@ -0,0 +1,107 @@ +// +// "$Id: Fl_Font.H 4288 2005-04-16 00:13:17Z mike $" +// +// Font definitions for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Two internal fltk data structures: +// +// Fl_Fontdesc: an entry into the fl_font() table. There is one of these +// for each fltk font number. +// +// Fl_FontSize: a structure for an actual system font, with junk to +// help choose it and info on character sizes. Each Fl_Fontdesc has a +// linked list of these. These are created the first time each system +// font/size combination is used. + +#ifndef FL_FONT_ +#define FL_FONT_ + +#include <config.h> + +# if USE_XFT +typedef struct _XftFont XftFont; +# endif // USE_XFT + +class Fl_FontSize { +public: + Fl_FontSize *next; // linked list for this Fl_Fontdesc +# ifdef WIN32 + HFONT fid; + int width[256]; + TEXTMETRIC metr; + FL_EXPORT Fl_FontSize(const char* fontname, int size); +# elif defined(__APPLE_QD__) + FL_EXPORT Fl_FontSize(const char* fontname, int size); + short font, face, size; + short ascent, descent; + short width[256]; + bool knowMetrics; +# elif defined(__APPLE_QUARTZ__) + FL_EXPORT Fl_FontSize(const char* fontname, int size); + char *q_name; + int size; + short ascent, descent, q_width; +# elif USE_XFT + XftFont* font; + const char* encoding; + int size; + FL_EXPORT Fl_FontSize(const char* xfontname); +# else + XFontStruct* font; // X font information + FL_EXPORT Fl_FontSize(const char* xfontname); +# endif + int minsize; // smallest point size that should use this + int maxsize; // largest point size that should use this +# if HAVE_GL + unsigned int listbase;// base of display list, 0 = none +# endif + FL_EXPORT ~Fl_FontSize(); +}; + +extern FL_EXPORT Fl_FontSize *fl_fontsize; // the currently selected one + +struct Fl_Fontdesc { + const char *name; + char fontname[128]; // "Pretty" font name + Fl_FontSize *first; // linked list of sizes of this style +# ifndef WIN32 + char **xlist; // matched X font names + int n; // size of xlist, negative = don't free xlist! +# endif +}; + +extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table + +# ifndef WIN32 +// functions for parsing X font names: +FL_EXPORT const char* fl_font_word(const char *p, int n); +FL_EXPORT char *fl_find_fontsize(char *name); +# endif + +#endif + +// +// End of "$Id: Fl_Font.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/src/Fl_GIF_Image.cxx b/Utilities/FLTK/src/Fl_GIF_Image.cxx new file mode 100644 index 0000000000..e40a9d218e --- /dev/null +++ b/Utilities/FLTK/src/Fl_GIF_Image.cxx @@ -0,0 +1,384 @@ +// +// "$Id$" +// +// Fl_GIF_Image routines. +// +// Copyright 1997-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +// Contents: +// +// + +// +// Include necessary header files... +// + +#include <FL/Fl.H> +#include <FL/Fl_GIF_Image.H> +#include <stdio.h> +#include <stdlib.h> +#include "flstring.h" + +// Read a .gif file and convert it to a "xpm" format (actually my +// modified one with compressed colormaps). + +// Extensively modified from original code for gif2ras by +// Patrick J. Naughton of Sun Microsystems. The original +// copyright notice follows: + +/* gif2ras.c - Converts from a Compuserve GIF (tm) image to a Sun Raster image. + * + * Copyright (c) 1988 by Patrick J. Naughton + * + * Author: Patrick J. Naughton + * naughton@wind.sun.com + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Comments and additions should be sent to the author: + * + * Patrick J. Naughton + * Sun Microsystems, Inc. + * 2550 Garcia Ave, MS 14-40 + * Mountain View, CA 94043 + * (415) 336-1080 + */ + +typedef unsigned char uchar; + +#define NEXTBYTE (uchar)getc(GifFile) +#define GETSHORT(var) var = NEXTBYTE; var += NEXTBYTE << 8 + +Fl_GIF_Image::Fl_GIF_Image(const char *infname) : Fl_Pixmap((char *const*)0) { + FILE *GifFile; // File to read + char **new_data; // Data array + + if ((GifFile = fopen(infname, "rb")) == NULL) { + Fl::error("Fl_GIF_Image: Unable to open %s!", infname); + return; + } + + {char b[6]; + if (fread(b,1,6,GifFile)<6) { + fclose(GifFile); + return; /* quit on eof */ + } + if (b[0]!='G' || b[1]!='I' || b[2] != 'F') { + fclose(GifFile); + Fl::error("Fl_GIF_Image: %s is not a GIF file.\n", infname); + return; + } + if (b[3]!='8' || b[4]>'9' || b[5]!= 'a') + Fl::warning("%s is version %c%c%c.",infname,b[3],b[4],b[5]); + } + + int Width; GETSHORT(Width); + int Height; GETSHORT(Height); + + uchar ch = NEXTBYTE; + char HasColormap = ((ch & 0x80) != 0); + int BitsPerPixel = (ch & 7) + 1; + int ColorMapSize = 1 << BitsPerPixel; + // int OriginalResolution = ((ch>>4)&7)+1; + // int SortedTable = (ch&8)!=0; + ch = NEXTBYTE; // Background Color index + ch = NEXTBYTE; // Aspect ratio is N/64 + + // Read in global colormap: + uchar transparent_pixel = 0; + char has_transparent = 0; + uchar Red[256], Green[256], Blue[256]; /* color map */ + if (HasColormap) { + for (int i=0; i < ColorMapSize; i++) { + Red[i] = NEXTBYTE; + Green[i] = NEXTBYTE; + Blue[i] = NEXTBYTE; + } + } else { + Fl::warning("%s does not have a colormap.", infname); + for (int i = 0; i < ColorMapSize; i++) + Red[i] = Green[i] = Blue[i] = (uchar)(255 * i / (ColorMapSize-1)); + } + + int CodeSize; /* Code size, init from GIF header, increases... */ + char Interlace; + + for (;;) { + + int i = NEXTBYTE; + if (i<0) { + fclose(GifFile); + Fl::error("Fl_GIF_Image: %s - unexpected EOF",infname); + return; + } + int blocklen; + + // if (i == 0x3B) return 0; eof code + + if (i == 0x21) { // a "gif extension" + + ch = NEXTBYTE; + blocklen = NEXTBYTE; + + if (ch==0xF9 && blocklen==4) { // Netscape animation extension + + char bits; + bits = NEXTBYTE; + char junk = NEXTBYTE; junk = NEXTBYTE; // GETSHORT(delay); + transparent_pixel = NEXTBYTE; + if (bits & 1) has_transparent = 1; + blocklen = NEXTBYTE; + + } else if (ch == 0xFF) { // Netscape repeat count + ; + + } else if (ch != 0xFE) { //Gif Comment + Fl::warning("%s: unknown gif extension 0x%02x.", infname, ch); + } + } else if (i == 0x2c) { // an image + + ch = NEXTBYTE; ch = NEXTBYTE; // GETSHORT(x_position); + ch = NEXTBYTE; ch = NEXTBYTE; // GETSHORT(y_position); + GETSHORT(Width); + GETSHORT(Height); + ch = NEXTBYTE; + Interlace = ((ch & 0x40) != 0); + if (ch&0x80) { + // read local color map + int n = 2<<(ch&7); + for (i=0; i < n; i++) { + Red[i] = NEXTBYTE; + Green[i] = NEXTBYTE; + Blue[i] = NEXTBYTE; + } + } + CodeSize = NEXTBYTE+1; + break; // okay, this is the image we want + } else { + Fl::warning("%s: unknown gif code 0x%02x", infname, i); + blocklen = 0; + } + + // skip the data: + while (blocklen>0) {while (blocklen--) {ch = NEXTBYTE;} blocklen=NEXTBYTE;} + } + + if (BitsPerPixel >= CodeSize) + { + // Workaround for broken GIF files... + BitsPerPixel = CodeSize - 1; + ColorMapSize = 1 << BitsPerPixel; + } + + uchar *Image = new uchar[Width*Height]; + + int YC = 0, Pass = 0; /* Used to de-interlace the picture */ + uchar *p = Image; + uchar *eol = p+Width; + + int InitCodeSize = CodeSize; + int ClearCode = (1 << (CodeSize-1)); + int EOFCode = ClearCode + 1; + int FirstFree = ClearCode + 2; + int FinChar = 0; + int ReadMask = (1<<CodeSize) - 1; + int FreeCode = FirstFree; + int OldCode = ClearCode; + + // tables used by LZW decompresser: + short int Prefix[4096]; + uchar Suffix[4096]; + + int blocklen = NEXTBYTE; + uchar thisbyte = NEXTBYTE; blocklen--; + int frombit = 0; + + for (;;) { + +/* Fetch the next code from the raster data stream. The codes can be + * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to + * maintain our location as a pointer and a bit offset. + * In addition, gif adds totally useless and annoying block counts + * that must be correctly skipped over. */ + int CurCode = thisbyte; + if (frombit+CodeSize > 7) { + if (blocklen <= 0) { + blocklen = NEXTBYTE; + if (blocklen <= 0) break; + } + thisbyte = NEXTBYTE; blocklen--; + CurCode |= thisbyte<<8; + } + if (frombit+CodeSize > 15) { + if (blocklen <= 0) { + blocklen = NEXTBYTE; + if (blocklen <= 0) break; + } + thisbyte = NEXTBYTE; blocklen--; + CurCode |= thisbyte<<16; + } + CurCode = (CurCode>>frombit)&ReadMask; + frombit = (frombit+CodeSize)%8; + + if (CurCode == ClearCode) { + CodeSize = InitCodeSize; + ReadMask = (1<<CodeSize) - 1; + FreeCode = FirstFree; + OldCode = ClearCode; + continue; + } + + if (CurCode == EOFCode) break; + + uchar OutCode[1025]; // temporary array for reversing codes + uchar *tp = OutCode; + int i; + if (CurCode < FreeCode) i = CurCode; + else if (CurCode == FreeCode) {*tp++ = (uchar)FinChar; i = OldCode;} + else {Fl::error("Fl_GIF_Image: %s - LZW Barf!", infname); break;} + + while (i >= ColorMapSize) {*tp++ = Suffix[i]; i = Prefix[i];} + *tp++ = FinChar = i; + do { + *p++ = *--tp; + if (p >= eol) { + if (!Interlace) YC++; + else switch (Pass) { + case 0: YC += 8; if (YC >= Height) {Pass++; YC = 4;} break; + case 1: YC += 8; if (YC >= Height) {Pass++; YC = 2;} break; + case 2: YC += 4; if (YC >= Height) {Pass++; YC = 1;} break; + case 3: YC += 2; break; + } + if (YC>=Height) YC=0; /* cheap bug fix when excess data */ + p = Image + YC*Width; + eol = p+Width; + } + } while (tp > OutCode); + + if (OldCode != ClearCode) { + Prefix[FreeCode] = (short)OldCode; + Suffix[FreeCode] = FinChar; + FreeCode++; + if (FreeCode > ReadMask) { + if (CodeSize < 12) { + CodeSize++; + ReadMask = (1 << CodeSize) - 1; + } + else FreeCode--; + } + } + OldCode = CurCode; + } + + // We are done reading the file, now convert to xpm: + + // allocate line pointer arrays: + w(Width); + h(Height); + d(1); + new_data = new char*[Height+2]; + + // transparent pixel must be zero, swap if it isn't: + if (has_transparent && transparent_pixel != 0) { + // swap transparent pixel with zero + p = Image+Width*Height; + while (p-- > Image) { + if (*p==transparent_pixel) *p = 0; + else if (!*p) *p = transparent_pixel; + } + uchar t; + t = Red[0]; + Red[0] = Red[transparent_pixel]; + Red[transparent_pixel] = t; + + t = Green[0]; + Green[0] = Green[transparent_pixel]; + Green[transparent_pixel] = t; + + t = Blue[0]; + Blue[0] = Blue[transparent_pixel]; + Blue[transparent_pixel] = t; + } + + // find out what colors are actually used: + uchar used[256]; uchar remap[256]; + int i; + for (i = 0; i < ColorMapSize; i++) used[i] = 0; + p = Image+Width*Height; + while (p-- > Image) used[*p] = 1; + + // remap them to start with printing characters: + int base = has_transparent && used[0] ? ' ' : ' '+1; + int numcolors = 0; + for (i = 0; i < ColorMapSize; i++) if (used[i]) { + remap[i] = (uchar)(base++); + numcolors++; + } + + // write the first line of xpm data (use suffix as temp array): + int length = sprintf((char*)(Suffix), + "%d %d %d %d",Width,Height,-numcolors,1); + new_data[0] = new char[length+1]; + strcpy(new_data[0], (char*)Suffix); + + // write the colormap + new_data[1] = (char*)(p = new uchar[4*numcolors]); + for (i = 0; i < ColorMapSize; i++) if (used[i]) { + *p++ = remap[i]; + *p++ = Red[i]; + *p++ = Green[i]; + *p++ = Blue[i]; + } + + // remap the image data: + p = Image+Width*Height; + while (p-- > Image) *p = remap[*p]; + + // split the image data into lines: + for (i=0; i<Height; i++) { + new_data[i+2] = new char[Width+1]; + memcpy(new_data[i + 2], (char*)(Image + i*Width), Width); + new_data[i + 2][Width] = 0; + } + + data((const char **)new_data, Height + 2); + alloc_data = 1; + + delete[] Image; + + fclose(GifFile); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Gl_Choice.H b/Utilities/FLTK/src/Fl_Gl_Choice.H new file mode 100644 index 0000000000..68a7830440 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Gl_Choice.H @@ -0,0 +1,132 @@ +// +// "$Id: Fl_Gl_Choice.H 4052 2005-02-24 21:55:12Z mike $" +// +// OpenGL definitions for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2001 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to "fltk-bugs@easysw.com". +// + +// Internal interface to set up OpenGL. +// +// A "Fl_Gl_Choice" is created from an OpenGL mode and holds information +// necessary to create a window (on X) and to create an OpenGL "context" +// (on both X and Win32). +// +// fl_create_gl_context takes a window (necessary only on Win32) and an +// Fl_Gl_Choice and returns a new OpenGL context. All contexts share +// display lists with each other. +// +// On X another fl_create_gl_context is provided to create it for any +// X visual. +// +// fl_set_gl_context makes the given OpenGL context current and makes +// it draw into the passed window. It tracks the current one context +// to avoid calling the context switching code when the same context +// is used, though it is a mystery to me why the GLX/WGL libraries +// don't do this themselves... +// +// fl_no_gl_context clears that cache so the next fl_set_gl_context is +// guaranteed to work. +// +// fl_delete_gl_context destroys the context. +// +// This code is used by Fl_Gl_Window, gl_start(), and gl_visual() + +#ifndef Fl_Gl_Choice_H +#define Fl_Gl_Choice_H + +// Warning: whatever GLContext is defined to must take exactly the same +// space in a structure as a void*!!! +#ifdef WIN32 +# include <FL/gl.h> +# define GLContext HGLRC +#elif defined(__APPLE_QD__) +# include <OpenGL/gl.h> +# include <AGL/agl.h> +# define GLContext AGLContext +#elif defined(__APPLE_QUARTZ__) +// warning: the Quartz version should probably use Core GL (CGL) instead of AGL +# include <OpenGL/gl.h> +# include <AGL/agl.h> +# define GLContext AGLContext +#else +# include <GL/glx.h> +# define GLContext GLXContext +#endif + +// Describes crap needed to create a GLContext. +class Fl_Gl_Choice { + int mode; + const int *alist; + Fl_Gl_Choice *next; +public: +#ifdef WIN32 + int pixelformat; // the visual to use + PIXELFORMATDESCRIPTOR pfd; // some wgl calls need this thing +#elif defined(__APPLE_QD__) + AGLPixelFormat pixelformat; +#elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + AGLPixelFormat pixelformat; +#else + XVisualInfo *vis; // the visual to use + Colormap colormap; // a colormap for that visual +#endif + // Return one of these structures for a given gl mode. + // The second argument is a glX attribute list, and is used if mode is + // zero. This is not supported on Win32: + static Fl_Gl_Choice *find(int mode, const int *); +}; + +class Fl_Window; + +#ifdef WIN32 + +GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice*, int layer=0); + +#elif defined(__APPLE_QD__) + +GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice*, int layer=0); + +#elif defined(__APPLE_QUARTZ__) +// warning: the Quartz version should probably use Core GL (CGL) instead of AGL + +GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice*, int layer=0); + +#else + +GLContext fl_create_gl_context(XVisualInfo* vis); + +static inline +GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice* g) { + return fl_create_gl_context(g->vis); +} + +#endif + +void fl_set_gl_context(Fl_Window*, GLContext); +void fl_no_gl_context(); +void fl_delete_gl_context(GLContext); + +#endif + +// +// End of "$Id: Fl_Gl_Choice.H 4052 2005-02-24 21:55:12Z mike $". +// diff --git a/Utilities/FLTK/src/Fl_Gl_Choice.cxx b/Utilities/FLTK/src/Fl_Gl_Choice.cxx new file mode 100644 index 0000000000..849c0c1fbc --- /dev/null +++ b/Utilities/FLTK/src/Fl_Gl_Choice.cxx @@ -0,0 +1,452 @@ +// +// "$Id$" +// +// OpenGL visual selection code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#if HAVE_GL + +# include <FL/Fl.H> +# include <FL/x.H> +# include <stdlib.h> +# include "Fl_Gl_Choice.H" +# include <FL/gl_draw.H> +# include "flstring.h" + +# ifdef __APPLE__ +# include <FL/Fl_Window.H> +# endif + +# ifdef WIN32 +void fl_save_dc(HWND, HDC); +# endif + +static Fl_Gl_Choice *first; + +// this assummes one of the two arguments is zero: +// We keep the list system in Win32 to stay compatible and interpret +// the list later... +Fl_Gl_Choice *Fl_Gl_Choice::find(int m, const int *alistp) { + Fl_Gl_Choice *g; + + for (g = first; g; g = g->next) + if (g->mode == m && g->alist == alistp) + return g; + +# ifdef __APPLE_QD__ + const int *blist; + int list[32]; + + if (alistp) + blist = alistp; + else { + int n = 0; + if (m & FL_INDEX) { + list[n++] = AGL_BUFFER_SIZE; + list[n++] = 8; // glut tries many sizes, but this should work... + } else { + list[n++] = AGL_RGBA; + list[n++] = AGL_GREEN_SIZE; + list[n++] = (m & FL_RGB8) ? 8 : 1; + if (m & FL_ALPHA) { + list[n++] = AGL_ALPHA_SIZE; + list[n++] = (m & FL_RGB8) ? 8 : 1; + } + if (m & FL_ACCUM) { + list[n++] = AGL_ACCUM_GREEN_SIZE; + list[n++] = 1; + if (m & FL_ALPHA) { + list[n++] = AGL_ACCUM_ALPHA_SIZE; + list[n++] = 1; + } + } + } + if (m & FL_DOUBLE) { + list[n++] = AGL_DOUBLEBUFFER; + } + if (m & FL_DEPTH) { + list[n++] = AGL_DEPTH_SIZE; list[n++] = 24; + } + if (m & FL_STENCIL) { + list[n++] = AGL_STENCIL_SIZE; list[n++] = 1; + } +# ifdef AGL_STEREO + if (m & FL_STEREO) { + list[n++] = AGL_STEREO; + } +# endif + list[n] = AGL_NONE; + blist = list; + } + fl_open_display(); + AGLPixelFormat fmt = aglChoosePixelFormat(NULL, 0, (GLint*)blist); + if (!fmt) return 0; + +#elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + const int *blist; + int list[32]; + + if (alistp) + blist = alistp; + else { + int n = 0; + if (m & FL_INDEX) { + list[n++] = AGL_BUFFER_SIZE; + list[n++] = 8; // glut tries many sizes, but this should work... + } else { + list[n++] = AGL_RGBA; + list[n++] = AGL_GREEN_SIZE; + list[n++] = (m & FL_RGB8) ? 8 : 1; + if (m & FL_ALPHA) { + list[n++] = AGL_ALPHA_SIZE; + list[n++] = (m & FL_RGB8) ? 8 : 1; + } + if (m & FL_ACCUM) { + list[n++] = AGL_ACCUM_GREEN_SIZE; + list[n++] = 1; + if (m & FL_ALPHA) { + list[n++] = AGL_ACCUM_ALPHA_SIZE; + list[n++] = 1; + } + } + } + if (m & FL_DOUBLE) { + list[n++] = AGL_DOUBLEBUFFER; + } + if (m & FL_DEPTH) { + list[n++] = AGL_DEPTH_SIZE; list[n++] = 24; + } + if (m & FL_STENCIL) { + list[n++] = AGL_STENCIL_SIZE; list[n++] = 1; + } +# ifdef AGL_STEREO + if (m & FL_STEREO) { + list[n++] = AGL_STEREO; + } +# endif + list[n] = AGL_NONE; + blist = list; + } + fl_open_display(); + AGLPixelFormat fmt = aglChoosePixelFormat(NULL, 0, (GLint*)blist); + if (!fmt) return 0; + +# elif !defined(WIN32) + + const int *blist; + int list[32]; + + if (alistp) + blist = alistp; + else { + int n = 0; + if (m & FL_INDEX) { + list[n++] = GLX_BUFFER_SIZE; + list[n++] = 8; // glut tries many sizes, but this should work... + } else { + list[n++] = GLX_RGBA; + list[n++] = GLX_GREEN_SIZE; + list[n++] = (m & FL_RGB8) ? 8 : 1; + if (m & FL_ALPHA) { + list[n++] = GLX_ALPHA_SIZE; + list[n++] = (m & FL_RGB8) ? 8 : 1; + } + if (m & FL_ACCUM) { + list[n++] = GLX_ACCUM_GREEN_SIZE; + list[n++] = 1; + if (m & FL_ALPHA) { + list[n++] = GLX_ACCUM_ALPHA_SIZE; + list[n++] = 1; + } + } + } + if (m & FL_DOUBLE) { + list[n++] = GLX_DOUBLEBUFFER; + } + if (m & FL_DEPTH) { + list[n++] = GLX_DEPTH_SIZE; list[n++] = 1; + } + if (m & FL_STENCIL) { + list[n++] = GLX_STENCIL_SIZE; list[n++] = 1; + } + if (m & FL_STEREO) { + list[n++] = GLX_STEREO; + } +# if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample) + if (m & FL_MULTISAMPLE) { + list[n++] = GLX_SAMPLES_SGIS; + list[n++] = 4; // value Glut uses + } +# endif + list[n] = 0; + blist = list; + } + + fl_open_display(); + XVisualInfo *visp = glXChooseVisual(fl_display, fl_screen, (int *)blist); + if (!visp) { +# if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample) + if (m&FL_MULTISAMPLE) return find(m&~FL_MULTISAMPLE,0); +# endif + return 0; + } + +# else + + // Replacement for ChoosePixelFormat() that finds one with an overlay + // if possible: + if (!fl_gc) fl_GetDC(0); + int pixelformat = 0; + PIXELFORMATDESCRIPTOR chosen_pfd; + for (int i = 1; ; i++) { + PIXELFORMATDESCRIPTOR pfd; + if (!DescribePixelFormat(fl_gc, i, sizeof(pfd), &pfd)) break; + // continue if it does not satisfy our requirements: + if (~pfd.dwFlags & (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL)) continue; + if (pfd.iPixelType != ((m&FL_INDEX)?PFD_TYPE_COLORINDEX:PFD_TYPE_RGBA)) continue; + if ((m & FL_ALPHA) && !pfd.cAlphaBits) continue; + if ((m & FL_ACCUM) && !pfd.cAccumBits) continue; + if ((!(m & FL_DOUBLE)) != (!(pfd.dwFlags & PFD_DOUBLEBUFFER))) continue; + if ((!(m & FL_STEREO)) != (!(pfd.dwFlags & PFD_STEREO))) continue; + if ((m & FL_DEPTH) && !pfd.cDepthBits) continue; + if ((m & FL_STENCIL) && !pfd.cStencilBits) continue; + // see if better than the one we have already: + if (pixelformat) { + // offering non-generic rendering is better (read: hardware accelleration) + if (!(chosen_pfd.dwFlags & PFD_GENERIC_FORMAT) && + (pfd.dwFlags & PFD_GENERIC_FORMAT)) continue; + // offering overlay is better: + else if (!(chosen_pfd.bReserved & 15) && (pfd.bReserved & 15)) {} + // otherwise more bit planes is better: + else if (chosen_pfd.cColorBits > pfd.cColorBits) continue; + else if (chosen_pfd.cDepthBits > pfd.cDepthBits) continue; + } + pixelformat = i; + chosen_pfd = pfd; + } + //printf("Chosen pixel format is %d\n", pixelformat); + if (!pixelformat) return 0; + +# endif + + g = new Fl_Gl_Choice; + g->mode = m; + g->alist = alistp; + g->next = first; + first = g; + +# ifdef WIN32 + g->pixelformat = pixelformat; + g->pfd = chosen_pfd; +# elif defined(__APPLE_QD__) + g->pixelformat = fmt; +# elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + g->pixelformat = fmt; +# else + g->vis = visp; + + if (/*MaxCmapsOfScreen(ScreenOfDisplay(fl_display,fl_screen))==1 && */ + visp->visualid == fl_visual->visualid && + !getenv("MESA_PRIVATE_CMAP")) + g->colormap = fl_colormap; + else + g->colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen), + visp->visual, AllocNone); +# endif + + return g; +} + +static GLContext *context_list = 0; +static int nContext = 0, NContext = 0; + +static void add_context(GLContext ctx) { + if (!ctx) return; + if (nContext==NContext) { + if (!NContext) NContext = 8; + NContext *= 2; + context_list = (GLContext*)realloc( + context_list, NContext*sizeof(GLContext)); + } + context_list[nContext++] = ctx; +} + +static void del_context(GLContext ctx) { + int i; + for (i=0; i<nContext; i++) { + if (context_list[i]==ctx) { + memmove(context_list+i, context_list+i+1, + (nContext-i-1) * sizeof(GLContext)); + context_list[--nContext] = 0; + break; + } + } + if (!nContext) gl_remove_displaylist_fonts(); +} + +# ifdef WIN32 + +GLContext fl_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) { + Fl_X* i = Fl_X::i(window); + HDC hdc = i->private_dc; + if (!hdc) { + hdc = i->private_dc = GetDCEx(i->xid, 0, DCX_CACHE); + fl_save_dc(i->xid, hdc); + SetPixelFormat(hdc, g->pixelformat, (PIXELFORMATDESCRIPTOR*)(&g->pfd)); +# if USE_COLORMAP + if (fl_palette) SelectPalette(hdc, fl_palette, FALSE); +# endif + } + GLContext context = + layer ? wglCreateLayerContext(hdc, layer) : wglCreateContext(hdc); + if (context) { + if (context_list && context_list[0]) + wglShareLists(context_list[0], context); + add_context(context); + } + return context; +} + +# elif defined(__APPLE_QD__) +GLContext fl_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) { + GLContext context, shared_ctx = context_list ? context_list[0] : 0; + context = aglCreateContext( g->pixelformat, shared_ctx); + if (!context) return 0; + add_context((GLContext)context); + if ( window->parent() ) { + Rect wrect; GetWindowPortBounds( fl_xid(window), &wrect ); + GLint rect[] = { window->x(), wrect.bottom-window->h()-window->y(), window->w(), window->h() }; + aglSetInteger( (GLContext)context, AGL_BUFFER_RECT, rect ); + aglEnable( (GLContext)context, AGL_BUFFER_RECT ); + } + aglSetDrawable( context, GetWindowPort( fl_xid(window) ) ); + return (context); +} +# elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + GLContext fl_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) { + GLContext context, shared_ctx = context_list ? context_list[0] : 0; + context = aglCreateContext( g->pixelformat, shared_ctx); + if (!context) return 0; + add_context((GLContext)context); + if ( window->parent() ) { + Rect wrect; GetWindowPortBounds( fl_xid(window), &wrect ); + GLint rect[] = { window->x(), wrect.bottom-window->h()-window->y(), window->w(), window->h() }; + aglSetInteger( (GLContext)context, AGL_BUFFER_RECT, rect ); + aglEnable( (GLContext)context, AGL_BUFFER_RECT ); + } + aglSetDrawable( context, GetWindowPort( fl_xid(window) ) ); + return (context); +} +# else + +GLContext fl_create_gl_context(XVisualInfo* vis) { + GLContext shared_ctx = context_list ? context_list[0] : 0; + GLContext context = glXCreateContext(fl_display, vis, shared_ctx, 1); + if (context) + add_context(context); + return context; +} + +# endif + +static GLContext cached_context; +static Fl_Window* cached_window; + +void fl_set_gl_context(Fl_Window* w, GLContext context) { + if (context != cached_context || w != cached_window) { + cached_context = context; + cached_window = w; +# ifdef WIN32 + wglMakeCurrent(Fl_X::i(w)->private_dc, context); +# elif defined(__APPLE_QD__) + if ( w->parent() ) { //: resize our GL buffer rectangle + Rect wrect; GetWindowPortBounds( fl_xid(w), &wrect ); + GLint rect[] = { w->x(), wrect.bottom-w->h()-w->y(), w->w(), w->h() }; + aglSetInteger( context, AGL_BUFFER_RECT, rect ); + aglEnable( context, AGL_BUFFER_RECT ); + } + aglSetDrawable(context, GetWindowPort( fl_xid(w) ) ); + aglSetCurrentContext(context); +# elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + if ( w->parent() ) { //: resize our GL buffer rectangle + Rect wrect; GetWindowPortBounds( fl_xid(w), &wrect ); + GLint rect[] = { w->x(), wrect.bottom-w->h()-w->y(), w->w(), w->h() }; + aglSetInteger( context, AGL_BUFFER_RECT, rect ); + aglEnable( context, AGL_BUFFER_RECT ); + } + aglSetDrawable(context, GetWindowPort( fl_xid(w) ) ); + aglSetCurrentContext(context); +# else + glXMakeCurrent(fl_display, fl_xid(w), context); +# endif + } +} + +void fl_no_gl_context() { + cached_context = 0; + cached_window = 0; +# ifdef WIN32 + wglMakeCurrent(0, 0); +# elif defined(__APPLE_QD__) + aglSetCurrentContext(0); +# elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + aglSetCurrentContext(0); +# else + glXMakeCurrent(fl_display, 0, 0); +# endif +} + +void fl_delete_gl_context(GLContext context) { + if (cached_context == context) fl_no_gl_context(); +# ifdef WIN32 + wglDeleteContext(context); +# elif defined(__APPLE_QD__) + aglSetCurrentContext( NULL ); + aglSetDrawable( context, NULL ); + aglDestroyContext( context ); +# elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + aglSetCurrentContext( NULL ); + aglSetDrawable( context, NULL ); + aglDestroyContext( context ); +# else + glXDestroyContext(fl_display, context); +# endif + del_context(context); +} + +#endif // HAVE_GL + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Gl_Overlay.cxx b/Utilities/FLTK/src/Fl_Gl_Overlay.cxx new file mode 100644 index 0000000000..2e25830249 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Gl_Overlay.cxx @@ -0,0 +1,250 @@ +// +// "$Id$" +// +// OpenGL overlay code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#if HAVE_GL + +#include <FL/Fl.H> +#include <FL/x.H> +#include "Fl_Gl_Choice.H" +#include <FL/Fl_Gl_Window.H> +#include <stdlib.h> + +#if !HAVE_GL_OVERLAY + +int Fl_Gl_Window::can_do_overlay() {return 0;} + +void Fl_Gl_Window::make_overlay() {overlay = this;} + +#else + +// Methods on Fl_Gl_Window that create an overlay window. Because +// many programs don't need the overlay, this is seperated into this +// source file so it is not linked in if not used. + +// Under X this is done by creating another window, of class _Fl_Gl_Overlay +// which is a subclass of Fl_Gl_Window except it uses the overlay planes. +// A pointer to this is stored in the "overlay" pointer of the Fl_Gl_Window. + +// Under win32 another GLX context is created to draw into the overlay +// and it is stored in into the "overlay" pointer. + +// In both cases if overlay hardware is unavailable, the overlay is +// "faked" by drawing into the main layers. This is indicated by +// setting overlay == this. + +#ifndef WIN32 +//////////////////////////////////////////////////////////////// +// X version + +extern XVisualInfo *fl_find_overlay_visual(); +extern XVisualInfo *fl_overlay_visual; +extern Colormap fl_overlay_colormap; +extern unsigned long fl_transparent_pixel; +extern uchar fl_overlay; + +class _Fl_Gl_Overlay : public Fl_Gl_Window { + void flush(); + void draw(); +public: + void show(); + _Fl_Gl_Overlay(int x, int y, int w, int h) : + Fl_Gl_Window(x,y,w,h) { + set_flag(INACTIVE); + } +}; + +void _Fl_Gl_Overlay::flush() { + make_current(); +#ifdef BOXX_BUGS + // The BoXX overlay is broken and you must not call swap-buffers. This + // code will make it work, but we lose because machines that do support + // double-buffered overlays will blink when they don't have to + glDrawBuffer(GL_FRONT); + draw(); +#else + draw(); + swap_buffers(); +#endif + glFlush(); + valid(1); +} + +void _Fl_Gl_Overlay::draw() { + if (!valid_) glClearIndex((GLfloat)fl_transparent_pixel); + if (damage() != FL_DAMAGE_EXPOSE) glClear(GL_COLOR_BUFFER_BIT); + Fl_Gl_Window *w = (Fl_Gl_Window *)parent(); + uchar save_valid = w->valid_; + w->valid_ = valid_; + fl_overlay = 1; + w->draw_overlay(); + fl_overlay = 0; + valid_ = w->valid_; + w->valid_ = save_valid; +} + +void _Fl_Gl_Overlay::show() { + if (!shown()) { + fl_background_pixel = int(fl_transparent_pixel); + Fl_X::make_xid(this, fl_overlay_visual, fl_overlay_colormap); + fl_background_pixel = -1; + // find the outermost window to tell wm about the colormap: + Fl_Window *w = window(); + for (;;) {Fl_Window *w1 = w->window(); if (!w1) break; w = w1;} + XSetWMColormapWindows(fl_display, fl_xid(w), &(Fl_X::i(this)->xid), 1); + context(fl_create_gl_context(fl_overlay_visual), 1); + valid(0); + } + Fl_Gl_Window::show(); +} + +int Fl_Gl_Window::can_do_overlay() { + return fl_find_overlay_visual() != 0; +} + +void Fl_Gl_Window::make_overlay() { + if (overlay) return; + if (can_do_overlay()) { + _Fl_Gl_Overlay* o = new _Fl_Gl_Overlay(0,0,w(),h()); + overlay = o; + add(*o); + o->show(); + } else { + overlay = this; // fake the overlay + } +} + +#else +//////////////////////////////////////////////////////////////// +// WIN32 version: + +//static COLORREF *palette; +extern int fl_overlay_depth; + +void Fl_Gl_Window::make_overlay() { + if (overlay) return; + + GLContext context = fl_create_gl_context(this, g, 1); + if (!context) {overlay = this; return;} // fake the overlay + + HDC hdc = Fl_X::i(this)->private_dc; + overlay = context; + LAYERPLANEDESCRIPTOR pfd; + wglDescribeLayerPlane(hdc, g->pixelformat, 1, sizeof(pfd), &pfd); + if (!pfd.iPixelType) { + ; // full-color overlay + } else { + fl_overlay_depth = pfd.cColorBits; // used by gl_color() + if (fl_overlay_depth > 8) fl_overlay_depth = 8; + COLORREF palette[256]; + int n = (1<<fl_overlay_depth)-1; + // copy all colors except #0 into the overlay palette: + for (int i = 0; i <= n; i++) { + uchar r,g,b; Fl::get_color((Fl_Color)i,r,g,b); + palette[i] = RGB(r,g,b); + } + // always provide black & white in the last 2 pixels: + if (fl_overlay_depth < 8) { + palette[n-1] = RGB(0,0,0); + palette[n] = RGB(255,255,255); + } + // and use it: + wglSetLayerPaletteEntries(hdc, 1, 1, n, palette+1); + wglRealizeLayerPalette(hdc, 1, TRUE); + } + valid(0); + return; +} + +int Fl_Gl_Window::can_do_overlay() { + if (!g) { + g = Fl_Gl_Choice::find(mode_,alist); + if (!g) return 0; + } + return (g->pfd.bReserved & 15) != 0; +} + +//////////////////////////////////////////////////////////////// +#endif + +#endif + +void Fl_Gl_Window::redraw_overlay() { + if (!shown()) return; + make_overlay(); +#ifdef __APPLE__ + redraw(); +#else +#ifndef WIN32 + if (overlay != this) + ((Fl_Gl_Window*)overlay)->redraw(); + else +#endif + damage(FL_DAMAGE_OVERLAY); +#endif +} + +void Fl_Gl_Window::make_overlay_current() { + make_overlay(); +#ifdef __APPLE__ + // this is not very useful, but unfortunatly, Apple decided + // that front buffer drawing can no longer (OS X 10.4) be + // supported on their platforms. + make_current(); +#else +#if HAVE_GL_OVERLAY + if (overlay != this) { +#ifdef WIN32 + fl_set_gl_context(this, (GLContext)overlay); +// if (fl_overlay_depth) +// wglRealizeLayerPalette(Fl_X::i(this)->private_dc, 1, TRUE); +#else + ((Fl_Gl_Window*)overlay)->make_current(); +#endif + } else +#endif + glDrawBuffer(GL_FRONT); +#endif +} + +void Fl_Gl_Window::hide_overlay() { +#if HAVE_GL_OVERLAY +#ifdef WIN32 + // nothing needs to be done? Or should it be erased? +#else + if (overlay && overlay!=this) ((Fl_Gl_Window*)overlay)->hide(); +#endif +#endif +} + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Gl_Window.cxx b/Utilities/FLTK/src/Fl_Gl_Window.cxx new file mode 100644 index 0000000000..97246c278b --- /dev/null +++ b/Utilities/FLTK/src/Fl_Gl_Window.cxx @@ -0,0 +1,427 @@ +// +// "$Id$" +// +// OpenGL window code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2006 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include "flstring.h" +#if HAVE_GL + +#include <FL/Fl.H> +#include <FL/x.H> +#include "Fl_Gl_Choice.H" +#include <FL/Fl_Gl_Window.H> +#include <stdlib.h> + +//////////////////////////////////////////////////////////////// + +// The symbol SWAP_TYPE defines what is in the back buffer after doing +// a glXSwapBuffers(). + +// The OpenGl documentation says that the contents of the backbuffer +// are "undefined" after glXSwapBuffers(). However, if we know what +// is in the backbuffers then we can save a good deal of time. For +// this reason you can define some symbols to describe what is left in +// the back buffer. + +// Having not found any way to determine this from glx (or wgl) I have +// resorted to letting the user specify it with an environment variable, +// GL_SWAP_TYPE, it should be equal to one of these symbols: + +// contents of back buffer after glXSwapBuffers(): +#define UNDEFINED 1 // anything +#define SWAP 2 // former front buffer (same as unknown) +#define COPY 3 // unchanged +#define NODAMAGE 4 // unchanged even by X expose() events + +static char SWAP_TYPE = 0 ; // 0 = determine it from environment variable + +//////////////////////////////////////////////////////////////// + +int Fl_Gl_Window::can_do(int a, const int *b) { + return Fl_Gl_Choice::find(a,b) != 0; +} + +void Fl_Gl_Window::show() { + if (!shown()) { + if (!g) { + g = Fl_Gl_Choice::find(mode_,alist); + + if (!g && (mode_ & FL_DOUBLE) == FL_SINGLE) { + g = Fl_Gl_Choice::find(mode_ | FL_DOUBLE,alist); + if (g) mode_ |= FL_FAKE_SINGLE; + } + + if (!g) { + Fl::error("Insufficient GL support"); + return; + } + } +#if !defined(WIN32) && !defined(__APPLE__) + Fl_X::make_xid(this, g->vis, g->colormap); + if (overlay && overlay != this) ((Fl_Gl_Window*)overlay)->show(); +#endif + } + Fl_Window::show(); +} + +void Fl_Gl_Window::invalidate() { + valid(0); +#ifndef WIN32 + if (overlay) ((Fl_Gl_Window*)overlay)->valid(0); +#endif +} + +int Fl_Gl_Window::mode(int m, const int *a) { + if (m == mode_ && a == alist) return 0; +#ifndef __APPLE__ + int oldmode = mode_; +#endif // !__APPLE__ +#if !defined(WIN32) && !defined(__APPLE__) + Fl_Gl_Choice* oldg = g; +#endif // !WIN32 && !__APPLE__ + context(0); + mode_ = m; alist = a; + if (shown()) { + g = Fl_Gl_Choice::find(m, a); +#if defined(WIN32) + if (!g || (oldmode^m)&FL_DOUBLE) { + hide(); + show(); + } +#elif defined(__APPLE_QD__) + redraw(); +#elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + redraw(); +#else + // under X, if the visual changes we must make a new X window (yuck!): + if (!g || g->vis->visualid!=oldg->vis->visualid || (oldmode^m)&FL_DOUBLE) { + hide(); + show(); + } +#endif + } else { + g = 0; + } + return 1; +} + +#define NON_LOCAL_CONTEXT 0x80000000 + +void Fl_Gl_Window::make_current() { +// puts("Fl_Gl_Window::make_current()"); +// printf("make_current: context_=%p\n", context_); + if (!context_) { + mode_ &= ~NON_LOCAL_CONTEXT; + context_ = fl_create_gl_context(this, g); + valid(0); + } + fl_set_gl_context(this, context_); + +#ifdef __APPLE__ + // Set the buffer rectangle here, since in resize() we won't have the + // correct parent window size to work with... + GLint xywh[4]; + + if (window()) { + xywh[0] = x(); + xywh[1] = window()->h() - y() - h(); + } else { + xywh[0] = 0; + xywh[1] = 0; + } + + xywh[2] = w(); + xywh[3] = h(); + + aglEnable(context_, AGL_BUFFER_RECT); + aglSetInteger(context_, AGL_BUFFER_RECT, xywh); +// printf("make_current: xywh=[%d %d %d %d]\n", xywh[0], xywh[1], xywh[2], xywh[3]); +#endif // __APPLE__ + +#if defined(WIN32) && USE_COLORMAP + if (fl_palette) { + fl_GetDC(fl_xid(this)); + SelectPalette(fl_gc, fl_palette, FALSE); + RealizePalette(fl_gc); + } +#endif // USE_COLORMAP + if (mode_ & FL_FAKE_SINGLE) { + glDrawBuffer(GL_FRONT); + glReadBuffer(GL_FRONT); + } + current_ = this; +} + +void Fl_Gl_Window::ortho() { +// Alpha NT seems to have a broken OpenGL that does not like negative coords: +#ifdef _M_ALPHA + glLoadIdentity(); + glViewport(0, 0, w(), h()); + glOrtho(0, w(), 0, h(), -1, 1); +#else + GLint v[2]; + glGetIntegerv(GL_MAX_VIEWPORT_DIMS, v); + glLoadIdentity(); + glViewport(w()-v[0], h()-v[1], v[0], v[1]); + glOrtho(w()-v[0], w(), h()-v[1], h(), -1, 1); +#endif +} + +void Fl_Gl_Window::swap_buffers() { +#ifdef WIN32 +# if HAVE_GL_OVERLAY + // Do not swap the overlay, to match GLX: + BOOL ret = wglSwapLayerBuffers(Fl_X::i(this)->private_dc, WGL_SWAP_MAIN_PLANE); + DWORD err = GetLastError();; +# else + SwapBuffers(Fl_X::i(this)->private_dc); +# endif +#elif defined(__APPLE_QD__) + aglSwapBuffers((AGLContext)context_); +#elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + aglSwapBuffers((AGLContext)context_); +#else + glXSwapBuffers(fl_display, fl_xid(this)); +#endif +} + +#if HAVE_GL_OVERLAY && defined(WIN32) +uchar fl_overlay; // changes how fl_color() works +int fl_overlay_depth = 0; +#endif + +void Fl_Gl_Window::flush() { + uchar save_valid = valid_; + +#ifdef __APPLE_QD__ + //: clear previous clipping in this shared port + GrafPtr port = GetWindowPort( fl_xid(this) ); + Rect rect; SetRect( &rect, 0, 0, 0x7fff, 0x7fff ); + GrafPtr old; GetPort( &old ); + SetPort( port ); + ClipRect( &rect ); + SetPort( old ); +#elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + //: clear previous clipping in this shared port + GrafPtr port = GetWindowPort( fl_xid(this) ); + Rect rect; SetRect( &rect, 0, 0, 0x7fff, 0x7fff ); + GrafPtr old; GetPort( &old ); + SetPort( port ); + ClipRect( &rect ); + SetPort( old ); +#endif + +#if HAVE_GL_OVERLAY && defined(WIN32) + + bool fixcursor = false; // for fixing the SGI 320 bug + + // Draw into hardware overlay planes if they are damaged: + if (overlay && overlay != this + && (damage()&(FL_DAMAGE_OVERLAY|FL_DAMAGE_EXPOSE) || !save_valid)) { + // SGI 320 messes up overlay with user-defined cursors: + if (Fl_X::i(this)->cursor && Fl_X::i(this)->cursor != fl_default_cursor) { + fixcursor = true; // make it restore cursor later + SetCursor(0); + } + fl_set_gl_context(this, (GLContext)overlay); + if (fl_overlay_depth) + wglRealizeLayerPalette(Fl_X::i(this)->private_dc, 1, TRUE); + glDisable(GL_SCISSOR_TEST); + glClear(GL_COLOR_BUFFER_BIT); + fl_overlay = 1; + draw_overlay(); + fl_overlay = 0; + valid(save_valid); + wglSwapLayerBuffers(Fl_X::i(this)->private_dc, WGL_SWAP_OVERLAY1); + // if only the overlay was damaged we are done, leave main layer alone: + if (damage() == FL_DAMAGE_OVERLAY) { + if (fixcursor) SetCursor(Fl_X::i(this)->cursor); + return; + } + } +#endif + + make_current(); + + if (mode_ & FL_DOUBLE) { + + glDrawBuffer(GL_BACK); + + if (!SWAP_TYPE) { +#ifdef __APPLE_QD__ + SWAP_TYPE = COPY; +#elif defined __APPLE_QUARTZ__ + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + SWAP_TYPE = COPY; +#else + SWAP_TYPE = UNDEFINED; +#endif + const char* c = getenv("GL_SWAP_TYPE"); + if (c) { + if (!strcmp(c,"COPY")) SWAP_TYPE = COPY; + else if (!strcmp(c, "NODAMAGE")) SWAP_TYPE = NODAMAGE; + else if (!strcmp(c, "SWAP")) SWAP_TYPE = SWAP; + } + } + + if (SWAP_TYPE == NODAMAGE) { + + // don't draw if only overlay damage or expose events: + if ((damage()&~(FL_DAMAGE_OVERLAY|FL_DAMAGE_EXPOSE)) || !save_valid) + draw(); + swap_buffers(); + + } else if (SWAP_TYPE == COPY) { + + // don't draw if only the overlay is damaged: + if (damage() != FL_DAMAGE_OVERLAY || !save_valid) draw(); + swap_buffers(); + + } else { // SWAP_TYPE == UNDEFINED + + // If we are faking the overlay, use CopyPixels to act like + // SWAP_TYPE == COPY. Otherwise overlay redraw is way too slow. + if (overlay == this) { + // don't draw if only the overlay is damaged: + if (damage1_ || damage() != FL_DAMAGE_OVERLAY || !save_valid) draw(); + // we use a seperate context for the copy because rasterpos must be 0 + // and depth test needs to be off: + static GLContext ortho_context = 0; + static Fl_Gl_Window* ortho_window = 0; + int orthoinit = !ortho_context; + if (orthoinit) ortho_context = fl_create_gl_context(this, g); + fl_set_gl_context(this, ortho_context); + if (orthoinit || !save_valid || ortho_window != this) { + glDisable(GL_DEPTH_TEST); + glReadBuffer(GL_BACK); + glDrawBuffer(GL_FRONT); + glLoadIdentity(); + glViewport(0, 0, w(), h()); + glOrtho(0, w(), 0, h(), -1, 1); + glRasterPos2i(0,0); + ortho_window = this; + } + glCopyPixels(0,0,w(),h(),GL_COLOR); + make_current(); // set current context back to draw overlay + damage1_ = 0; + + } else { + damage1_ = damage(); + clear_damage(0xff); draw(); + swap_buffers(); + } + + } + + if (overlay==this) { // fake overlay in front buffer + glDrawBuffer(GL_FRONT); + draw_overlay(); + glDrawBuffer(GL_BACK); + glFlush(); + } + + } else { // single-buffered context is simpler: + + draw(); + if (overlay == this) draw_overlay(); + glFlush(); + + } + +#if HAVE_GL_OVERLAY && defined(WIN32) + if (fixcursor) SetCursor(Fl_X::i(this)->cursor); +#endif + valid(1); +} + +void Fl_Gl_Window::resize(int X,int Y,int W,int H) { +// printf("Fl_Gl_Window::resize(X=%d, Y=%d, W=%d, H=%d)\n", X, Y, W, H); +// printf("current: x()=%d, y()=%d, w()=%d, h()=%d\n", x(), y(), w(), h()); + + if (W != w() || H != h()) valid(0); + +#ifdef __APPLE__ + if (X != x() || Y != y() || W != w() || H != h()) aglUpdateContext(context_); +#elif !defined(WIN32) + if ((W != w() || H != h()) && !resizable() && overlay && overlay != this) { + ((Fl_Gl_Window*)overlay)->resize(0,0,W,H); + } +#endif + + Fl_Window::resize(X,Y,W,H); +} + +void Fl_Gl_Window::context(void* v, int destroy_flag) { + if (context_ && !(mode_&NON_LOCAL_CONTEXT)) fl_delete_gl_context(context_); + context_ = (GLContext)v; + if (destroy_flag) mode_ &= ~NON_LOCAL_CONTEXT; + else mode_ |= NON_LOCAL_CONTEXT; +} + +void Fl_Gl_Window::hide() { + context(0); +#if HAVE_GL_OVERLAY && defined(WIN32) + if (overlay && overlay != this) { + fl_delete_gl_context((GLContext)overlay); + overlay = 0; + } +#endif + Fl_Window::hide(); +} + +Fl_Gl_Window::~Fl_Gl_Window() { + hide(); +// delete overlay; this is done by ~Fl_Group +} + +void Fl_Gl_Window::init() { + end(); // we probably don't want any children + box(FL_NO_BOX); + + mode_ = FL_RGB | FL_DEPTH | FL_DOUBLE; + alist = 0; + context_ = 0; + g = 0; + overlay = 0; + valid_ = 0; + damage1_ = 0; + +#if 0 // This breaks resizing on Linux/X11 + int H = h(); + h(1); // Make sure we actually do something in resize()... + resize(x(), y(), w(), H); +#endif // 0 +} + +void Fl_Gl_Window::draw_overlay() {} + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Group.cxx b/Utilities/FLTK/src/Fl_Group.cxx new file mode 100644 index 0000000000..a9aecf0976 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Group.cxx @@ -0,0 +1,612 @@ +// +// "$Id$" +// +// Group widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// The Fl_Group is the only defined container type in FLTK. + +// Fl_Window itself is a subclass of this, and most of the event +// handling is designed so windows themselves work correctly. + +#include <stdio.h> +#include <FL/Fl.H> +#include <FL/Fl_Group.H> +#include <FL/Fl_Window.H> +#include <FL/fl_draw.H> +#include <stdlib.h> + +Fl_Group* Fl_Group::current_; + +// Hack: A single child is stored in the pointer to the array, while +// multiple children are stored in an allocated array: +Fl_Widget*const* Fl_Group::array() const { + return children_ <= 1 ? (Fl_Widget**)(&array_) : array_; +} + +int Fl_Group::find(const Fl_Widget* o) const { + Fl_Widget*const* a = array(); + int i; for (i=0; i < children_; i++) if (*a++ == o) break; + return i; +} + +// Metrowerks CodeWarrior and others can't export the static +// class member: current_, so these methods can't be inlined... +void Fl_Group::begin() {current_ = this;} +void Fl_Group::end() {current_ = (Fl_Group*)parent();} +Fl_Group *Fl_Group::current() {return current_;} +void Fl_Group::current(Fl_Group *g) {current_ = g;} + +extern Fl_Widget* fl_oldfocus; // set by Fl::focus + +// For back-compatability, we must adjust all events sent to child +// windows so they are relative to that window. + +static int send(Fl_Widget* o, int event) { + if (o->type() < FL_WINDOW) return o->handle(event); + switch ( event ) + { + case FL_DND_ENTER: + case FL_DND_DRAG: + // figure out correct type of event: + event = (o->contains(Fl::belowmouse())) ? FL_DND_DRAG : FL_DND_ENTER; + } + int save_x = Fl::e_x; Fl::e_x -= o->x(); + int save_y = Fl::e_y; Fl::e_y -= o->y(); + int ret = o->handle(event); + Fl::e_y = save_y; + Fl::e_x = save_x; + switch ( event ) + { + case FL_ENTER: + case FL_DND_ENTER: + // Successful completion of FL_ENTER means the widget is now the + // belowmouse widget, but only call Fl::belowmouse if the child + // widget did not do so: + if (!o->contains(Fl::belowmouse())) Fl::belowmouse(o); + break; + } + return ret; +} + +// translate the current keystroke into up/down/left/right for navigation: +#define ctrl(x) (x^0x40) +static int navkey() { + switch (Fl::event_key()) { + case 0: // not an FL_KEYBOARD/FL_SHORTCUT event + break; + case FL_Tab: + if (!Fl::event_state(FL_SHIFT)) return FL_Right; + case 0xfe20: // XK_ISO_Left_Tab + return FL_Left; + case FL_Right: + return FL_Right; + case FL_Left: + return FL_Left; + case FL_Up: + return FL_Up; + case FL_Down: + return FL_Down; + } + return 0; +} + +int Fl_Group::handle(int event) { + + Fl_Widget*const* a = array(); + int i; + Fl_Widget* o; + + switch (event) { + + case FL_FOCUS: + switch (navkey()) { + default: + if (savedfocus_ && savedfocus_->take_focus()) return 1; + case FL_Right: + case FL_Down: + for (i = children(); i--;) if ((*a++)->take_focus()) return 1; + break; + case FL_Left: + case FL_Up: + for (i = children(); i--;) if (a[i]->take_focus()) return 1; + break; + } + return 0; + + case FL_UNFOCUS: + savedfocus_ = fl_oldfocus; + return 0; + + case FL_KEYBOARD: + return navigation(navkey()); + + case FL_SHORTCUT: + for (i = children(); i--;) { + o = a[i]; + if (o->takesevents() && Fl::event_inside(o) && send(o,FL_SHORTCUT)) + return 1; + } + for (i = children(); i--;) { + o = a[i]; + if (o->takesevents() && !Fl::event_inside(o) && send(o,FL_SHORTCUT)) + return 1; + } + if ((Fl::event_key() == FL_Enter || Fl::event_key() == FL_KP_Enter)) return navigation(FL_Down); + return 0; + + case FL_ENTER: + case FL_MOVE: + for (i = children(); i--;) { + o = a[i]; + if (o->visible() && Fl::event_inside(o)) { + if (o->contains(Fl::belowmouse())) { + return send(o,FL_MOVE); + } else { + Fl::belowmouse(o); + if (send(o,FL_ENTER)) return 1; + } + } + } + Fl::belowmouse(this); + return 1; + + case FL_DND_ENTER: + case FL_DND_DRAG: + for (i = children(); i--;) { + o = a[i]; + if (o->takesevents() && Fl::event_inside(o)) { + if (o->contains(Fl::belowmouse())) { + return send(o,FL_DND_DRAG); + } else if (send(o,FL_DND_ENTER)) { + if (!o->contains(Fl::belowmouse())) Fl::belowmouse(o); + return 1; + } + } + } + Fl::belowmouse(this); + return 0; + + case FL_PUSH: + for (i = children(); i--;) { + o = a[i]; + if (o->takesevents() && Fl::event_inside(o)) { + if (send(o,FL_PUSH)) { + if (Fl::pushed() && !o->contains(Fl::pushed())) Fl::pushed(o); + return 1; + } + } + } + return 0; + + case FL_RELEASE: + case FL_DRAG: + o = Fl::pushed(); + if (o == this) return 0; + else if (o) send(o,event); + else { + for (i = children(); i--;) { + o = a[i]; + if (o->takesevents() && Fl::event_inside(o)) { + if (send(o,event)) return 1; + } + } + } + return 0; + + case FL_MOUSEWHEEL: + for (i = children(); i--;) { + o = a[i]; + if (o->takesevents() && Fl::event_inside(o) && send(o,FL_MOUSEWHEEL)) + return 1; + } + for (i = children(); i--;) { + o = a[i]; + if (o->takesevents() && !Fl::event_inside(o) && send(o,FL_MOUSEWHEEL)) + return 1; + } + return 0; + + case FL_DEACTIVATE: + case FL_ACTIVATE: + for (i = children(); i--;) { + o = *a++; + if (o->active()) o->handle(event); + } + return 1; + + case FL_SHOW: + case FL_HIDE: + for (i = children(); i--;) { + o = *a++; + if (event == FL_HIDE && o == Fl::focus()) { + // Give up input focus... + int old_event = Fl::e_number; + o->handle(Fl::e_number = FL_UNFOCUS); + Fl::e_number = old_event; + Fl::focus(0); + } + if (o->visible()) o->handle(event); + } + return 1; + + default: + // For all other events, try to give to each child, starting at focus: + for (i = 0; i < children(); i ++) + if (Fl::focus_ == a[i]) break; + + if (i >= children()) i = 0; + + if (children()) { + for (int j = i;;) { + if (a[j]->takesevents() || event != FL_MOUSEWHEEL) { + if (send(a[j], event)) return 1; + } + j++; + if (j >= children()) j = 0; + if (j == i) break; + } + } + + return 0; + } +} + +//void Fl_Group::focus(Fl_Widget *o) {Fl::focus(o); o->handle(FL_FOCUS);} + +#if 0 +const char *nameof(Fl_Widget *o) { + if (!o) return "NULL"; + if (!o->label()) return "<no label>"; + return o->label(); +} +#endif + +// try to move the focus in response to a keystroke: +int Fl_Group::navigation(int key) { + if (children() <= 1) return 0; + int i; + for (i = 0; ; i++) { + if (i >= children_) return 0; + if (array_[i]->contains(Fl::focus())) break; + } + Fl_Widget *previous = array_[i]; + + for (;;) { + switch (key) { + case FL_Right: + case FL_Down: + i++; + if (i >= children_) { + if (parent()) return 0; + i = 0; + } + break; + case FL_Left: + case FL_Up: + if (i) i--; + else { + if (parent()) return 0; + i = children_-1; + } + break; + default: + return 0; + } + Fl_Widget* o = array_[i]; + if (o == previous) return 0; + switch (key) { + case FL_Down: + case FL_Up: + // for up/down, the widgets have to overlap horizontally: + if (o->x() >= previous->x()+previous->w() || + o->x()+o->w() <= previous->x()) continue; + } + if (o->take_focus()) return 1; + } +} + +//////////////////////////////////////////////////////////////// + +Fl_Group::Fl_Group(int X,int Y,int W,int H,const char *l) +: Fl_Widget(X,Y,W,H,l) { + align(FL_ALIGN_TOP); + children_ = 0; + array_ = 0; + savedfocus_ = 0; + resizable_ = this; + sizes_ = 0; // this is allocated when first resize() is done + // Subclasses may want to construct child objects as part of their + // constructor, so make sure they are add()'d to this object. + // But you must end() the object! + begin(); +} + +void Fl_Group::clear() { + Fl_Widget*const* old_array = array(); + int old_children = children(); + // clear everything now, in case fl_fix_focus recursively calls us: + children_ = 0; + //array_ = 0; //dont do this, it will clobber old_array if only one child + savedfocus_ = 0; + resizable_ = this; + init_sizes(); + // okay, now it is safe to destroy the children: + Fl_Widget*const* a = old_array; + for (int i=old_children; i--;) { + Fl_Widget* o = *a++; + if (o->parent() == this) delete o; + } + if (old_children > 1) free((void*)old_array); +} + +Fl_Group::~Fl_Group() { + clear(); +} + +void Fl_Group::insert(Fl_Widget &o, int index) { + if (o.parent()) { + Fl_Group* g = (Fl_Group*)(o.parent()); + int n = g->find(o); + if (g == this) { + if (index > n) index--; + if (index == n) return; + } + g->remove(o); + } + o.parent_ = this; + if (children_ == 0) { // use array pointer to point at single child + array_ = (Fl_Widget**)&o; + } else if (children_ == 1) { // go from 1 to 2 children + Fl_Widget* t = (Fl_Widget*)array_; + array_ = (Fl_Widget**)malloc(2*sizeof(Fl_Widget*)); + if (index) {array_[0] = t; array_[1] = &o;} + else {array_[0] = &o; array_[1] = t;} + } else { + if (!(children_ & (children_-1))) // double number of children + array_ = (Fl_Widget**)realloc((void*)array_, + 2*children_*sizeof(Fl_Widget*)); + int j; for (j = children_; j > index; j--) array_[j] = array_[j-1]; + array_[j] = &o; + } + children_++; + init_sizes(); +} + +void Fl_Group::add(Fl_Widget &o) {insert(o, children_);} + +void Fl_Group::remove(Fl_Widget &o) { + if (!children_) return; + int i = find(o); + if (i >= children_) return; + if (&o == savedfocus_) savedfocus_ = 0; + o.parent_ = 0; + children_--; + if (children_ == 1) { // go from 2 to 1 child + Fl_Widget *t = array_[!i]; + free((void*)array_); + array_ = (Fl_Widget**)t; + } else if (children_ > 1) { // delete from array + for (; i < children_; i++) array_[i] = array_[i+1]; + } + init_sizes(); +} + +//////////////////////////////////////////////////////////////// + +// Rather lame kludge here, I need to detect windows and ignore the +// changes to X,Y, since all children are relative to X,Y. That +// is why I check type(): + +// sizes array stores the initial positions of widgets as +// left,right,top,bottom quads. The first quad is the group, the +// second is the resizable (clipped to the group), and the +// rest are the children. This is a convienent order for the +// algorithim. If you change this be sure to fix Fl_Tile which +// also uses this array! + +void Fl_Group::init_sizes() { + delete[] sizes_; sizes_ = 0; +} + +short* Fl_Group::sizes() { + if (!sizes_) { + short* p = sizes_ = new short[4*(children_+2)]; + // first thing in sizes array is the group's size: + if (type() < FL_WINDOW) {p[0] = x(); p[2] = y();} else {p[0] = p[2] = 0;} + p[1] = p[0]+w(); p[3] = p[2]+h(); + // next is the resizable's size: + p[4] = p[0]; // init to the group's size + p[5] = p[1]; + p[6] = p[2]; + p[7] = p[3]; + Fl_Widget* r = resizable(); + if (r && r != this) { // then clip the resizable to it + int t; + t = r->x(); if (t > p[0]) p[4] = t; + t +=r->w(); if (t < p[1]) p[5] = t; + t = r->y(); if (t > p[2]) p[6] = t; + t +=r->h(); if (t < p[3]) p[7] = t; + } + // next is all the children's sizes: + p += 8; + Fl_Widget*const* a = array(); + for (int i=children_; i--;) { + Fl_Widget* o = *a++; + *p++ = o->x(); + *p++ = o->x()+o->w(); + *p++ = o->y(); + *p++ = o->y()+o->h(); + } + } + return sizes_; +} + +void Fl_Group::resize(int X, int Y, int W, int H) { + + if (!resizable() || W==w() && H==h() ) { + + if (type() < FL_WINDOW) { + int dx = X-x(); + int dy = Y-y(); + Fl_Widget*const* a = array(); + for (int i=children_; i--;) { + Fl_Widget* o = *a++; + o->resize(o->x()+dx, o->y()+dy, o->w(), o->h()); + } + } + + } else if (children_) { + + short* p = sizes(); + + // get changes in size/position from the initial size: + int dx = X - p[0]; + int dw = W - (p[1]-p[0]); + int dy = Y - p[2]; + int dh = H - (p[3]-p[2]); + if (type() >= FL_WINDOW) dx = dy = 0; + p += 4; + + // get initial size of resizable(): + int IX = *p++; + int IR = *p++; + int IY = *p++; + int IB = *p++; + + Fl_Widget*const* a = array(); + for (int i=children_; i--;) { + Fl_Widget* o = *a++; +#if 1 + int XX = *p++; + if (XX >= IR) XX += dw; + else if (XX > IX) XX = IX+((XX-IX)*(IR+dw-IX)+(IR-IX)/2)/(IR-IX); + int R = *p++; + if (R >= IR) R += dw; + else if (R > IX) R = IX+((R-IX)*(IR+dw-IX)+(IR-IX)/2)/(IR-IX); + + int YY = *p++; + if (YY >= IB) YY += dh; + else if (YY > IY) YY = IY+((YY-IY)*(IB+dh-IY)+(IB-IY)/2)/(IB-IY); + int B = *p++; + if (B >= IB) B += dh; + else if (B > IY) B = IY+((B-IY)*(IB+dh-IY)+(IB-IY)/2)/(IB-IY); +#else // much simpler code from Francois Ostiguy: + int XX = *p++; + if (XX >= IR) XX += dw; + else if (XX > IX) XX += dw * (XX-IX)/(IR-IX); + int R = *p++; + if (R >= IR) R += dw; + else if (R > IX) R = R + dw * (R-IX)/(IR-IX); + + int YY = *p++; + if (YY >= IB) YY += dh; + else if (YY > IY) YY = YY + dh*(YY-IY)/(IB-IY); + int B = *p++; + if (B >= IB) B += dh; + else if (B > IY) B = B + dh*(B-IY)/(IB-IY); +#endif + o->resize(XX+dx, YY+dy, R-XX, B-YY); + } + } + + Fl_Widget::resize(X,Y,W,H); +} + +void Fl_Group::draw_children() { + Fl_Widget*const* a = array(); + if (damage() & ~FL_DAMAGE_CHILD) { // redraw the entire thing: + for (int i=children_; i--;) { + Fl_Widget& o = **a++; + draw_child(o); + draw_outside_label(o); + } + } else { // only redraw the children that need it: + for (int i=children_; i--;) update_child(**a++); + } +} + +void Fl_Group::draw() { + if (damage() & ~FL_DAMAGE_CHILD) { // redraw the entire thing: + draw_box(); + draw_label(); + } + draw_children(); +} + +// Draw a child only if it needs it: +void Fl_Group::update_child(Fl_Widget& widget) const { + if (widget.damage() && widget.visible() && widget.type() < FL_WINDOW && + fl_not_clipped(widget.x(), widget.y(), widget.w(), widget.h())) { + widget.draw(); + widget.clear_damage(); + } +} + +// Force a child to redraw: +void Fl_Group::draw_child(Fl_Widget& widget) const { + if (widget.visible() && widget.type() < FL_WINDOW && + fl_not_clipped(widget.x(), widget.y(), widget.w(), widget.h())) { + widget.clear_damage(FL_DAMAGE_ALL); + widget.draw(); + widget.clear_damage(); + } +} + +extern char fl_draw_shortcut; + +// Parents normally call this to draw outside labels: +void Fl_Group::draw_outside_label(const Fl_Widget& widget) const { + if (!widget.visible()) return; + // skip any labels that are inside the widget: + if (!(widget.align()&15) || (widget.align() & FL_ALIGN_INSIDE)) return; + // invent a box that is outside the widget: + int a = widget.align(); + int X = widget.x(); + int Y = widget.y(); + int W = widget.w(); + int H = widget.h(); + if (a & FL_ALIGN_TOP) { + a ^= (FL_ALIGN_BOTTOM|FL_ALIGN_TOP); + Y = y(); + H = widget.y()-Y; + } else if (a & FL_ALIGN_BOTTOM) { + a ^= (FL_ALIGN_BOTTOM|FL_ALIGN_TOP); + Y = Y+H; + H = y()+h()-Y; + } else if (a & FL_ALIGN_LEFT) { + a ^= (FL_ALIGN_LEFT|FL_ALIGN_RIGHT); + X = x(); + W = widget.x()-X-3; + } else if (a & FL_ALIGN_RIGHT) { + a ^= (FL_ALIGN_LEFT|FL_ALIGN_RIGHT); + X = X+W+3; + W = x()+this->w()-X; + } + widget.draw_label(X,Y,W,H,(Fl_Align)a); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Help_Dialog.cxx b/Utilities/FLTK/src/Fl_Help_Dialog.cxx new file mode 100644 index 0000000000..c38e7c8c09 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Help_Dialog.cxx @@ -0,0 +1,321 @@ +// +// "$Id$" +// +// Fl_Help_Dialog dialog for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// generated by Fast Light User Interface Designer (fluid) version 1.0107 + +#include "../FL/Fl_Help_Dialog.H" +#include "flstring.h" +#include <FL/fl_ask.H> + +void Fl_Help_Dialog::cb_view__i(Fl_Help_View*, void*) { + if (view_->filename()) +{ + if (view_->changed()) + { + index_ ++; + + if (index_ >= 100) + { + memmove(line_, line_ + 10, sizeof(line_[0]) * 90); + memmove(file_, file_ + 10, sizeof(file_[0]) * 90); + index_ -= 10; + } + + max_ = index_; + + strlcpy(file_[index_], view_->filename(),sizeof(file_[0])); + line_[index_] = view_->topline(); + + if (index_ > 0) + back_->activate(); + else + back_->deactivate(); + + forward_->deactivate(); + window_->label(view_->title()); + } + else // if ! view_->changed() + { + strlcpy(file_[index_], view_->filename(), sizeof(file_[0])); + line_[index_] = view_->topline(); + } +} else { // if ! view_->filename() + index_ = 0; // hitting an internal page will disable the back/fwd buffer + file_[index_][0] = 0; // unnamed internal page + line_[index_] = view_->topline(); + back_->deactivate(); + forward_->deactivate(); +}; +} +void Fl_Help_Dialog::cb_view_(Fl_Help_View* o, void* v) { + ((Fl_Help_Dialog*)(o->parent()->user_data()))->cb_view__i(o,v); +} + +void Fl_Help_Dialog::cb_Close_i(Fl_Button*, void*) { + window_->hide(); +} +void Fl_Help_Dialog::cb_Close(Fl_Button* o, void* v) { + ((Fl_Help_Dialog*)(o->parent()->parent()->user_data()))->cb_Close_i(o,v); +} + +void Fl_Help_Dialog::cb_back__i(Fl_Button*, void*) { + if (index_ > 0) + index_ --; + +if (index_ == 0) + back_->deactivate(); + +forward_->activate(); + +int l = line_[index_]; + +if (strcmp(view_->filename(), file_[index_]) != 0) + view_->load(file_[index_]); + +view_->topline(l); +} +void Fl_Help_Dialog::cb_back_(Fl_Button* o, void* v) { + ((Fl_Help_Dialog*)(o->parent()->parent()->user_data()))->cb_back__i(o,v); +} + +void Fl_Help_Dialog::cb_forward__i(Fl_Button*, void*) { + if (index_ < max_) + index_ ++; + +if (index_ >= max_) + forward_->deactivate(); + +back_->activate(); + +int l = view_->topline(); + +if (strcmp(view_->filename(), file_[index_]) != 0) + view_->load(file_[index_]); + +view_->topline(l); +} +void Fl_Help_Dialog::cb_forward_(Fl_Button* o, void* v) { + ((Fl_Help_Dialog*)(o->parent()->parent()->user_data()))->cb_forward__i(o,v); +} + +void Fl_Help_Dialog::cb_smaller__i(Fl_Button*, void*) { + if (view_->textsize() > 8) + view_->textsize(view_->textsize() - 2); + +if (view_->textsize() <= 8) + smaller_->deactivate(); +larger_->activate(); +} +void Fl_Help_Dialog::cb_smaller_(Fl_Button* o, void* v) { + ((Fl_Help_Dialog*)(o->parent()->parent()->user_data()))->cb_smaller__i(o,v); +} + +void Fl_Help_Dialog::cb_larger__i(Fl_Button*, void*) { + if (view_->textsize() < 18) + view_->textsize(view_->textsize() + 2); + +if (view_->textsize() >= 18) + larger_->deactivate(); +smaller_->activate(); +} +void Fl_Help_Dialog::cb_larger_(Fl_Button* o, void* v) { + ((Fl_Help_Dialog*)(o->parent()->parent()->user_data()))->cb_larger__i(o,v); +} + +void Fl_Help_Dialog::cb_find__i(Fl_Input*, void*) { + find_pos_ = view_->find(find_->value(), find_pos_); +} +void Fl_Help_Dialog::cb_find_(Fl_Input* o, void* v) { + ((Fl_Help_Dialog*)(o->parent()->parent()->parent()->user_data()))->cb_find__i(o,v); +} + +Fl_Help_Dialog::Fl_Help_Dialog() { + Fl_Double_Window* w; + { Fl_Double_Window* o = window_ = new Fl_Double_Window(530, 385, "Help Dialog"); + w = o; + o->user_data((void*)(this)); + { Fl_Help_View* o = view_ = new Fl_Help_View(10, 10, 510, 330); + o->box(FL_DOWN_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_SELECTION_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); + o->callback((Fl_Callback*)cb_view_); + o->align(FL_ALIGN_TOP); + o->when(FL_WHEN_RELEASE); + o->end(); + Fl_Group::current()->resizable(o); + } + { Fl_Group* o = new Fl_Group(10, 348, 510, 27); + { Fl_Button* o = new Fl_Button(456, 350, 64, 25, "Close"); + o->callback((Fl_Callback*)cb_Close); + o->label(fl_close); + } + { Fl_Button* o = back_ = new Fl_Button(386, 350, 25, 25, "@<-"); + o->tooltip("Show the previous help page."); + o->shortcut(0xff51); + o->labelcolor((Fl_Color)2); + o->callback((Fl_Callback*)cb_back_); + } + { Fl_Button* o = forward_ = new Fl_Button(421, 350, 25, 25, "@->"); + o->tooltip("Show the next help page."); + o->shortcut(0xff53); + o->labelcolor((Fl_Color)2); + o->callback((Fl_Callback*)cb_forward_); + } + { Fl_Button* o = smaller_ = new Fl_Button(316, 350, 25, 25, "F"); + o->tooltip("Make the help text smaller."); + o->labelfont(1); + o->labelsize(10); + o->callback((Fl_Callback*)cb_smaller_); + } + { Fl_Button* o = larger_ = new Fl_Button(351, 350, 25, 25, "F"); + o->tooltip("Make the help text larger."); + o->labelfont(1); + o->labelsize(16); + o->callback((Fl_Callback*)cb_larger_); + } + { Fl_Group* o = new Fl_Group(10, 350, 296, 25); + o->box(FL_DOWN_BOX); + o->color(FL_BACKGROUND2_COLOR); + { Fl_Input* o = find_ = new Fl_Input(35, 352, 268, 21, "@search"); + o->tooltip("find text in document"); + o->box(FL_FLAT_BOX); + o->labelsize(13); + o->callback((Fl_Callback*)cb_find_); + o->when(FL_WHEN_ENTER_KEY_ALWAYS); + Fl_Group::current()->resizable(o); + } + o->end(); + Fl_Group::current()->resizable(o); + } + o->end(); + } + o->size_range(260, 150); + o->end(); + } + back_->deactivate(); +forward_->deactivate(); + +index_ = -1; +max_ = 0; +find_pos_ = 0; + +fl_register_images(); +} + +Fl_Help_Dialog::~Fl_Help_Dialog() { + delete window_; +} + +int Fl_Help_Dialog::h() { + return (window_->h()); +} + +void Fl_Help_Dialog::hide() { + window_->hide(); +} + +void Fl_Help_Dialog::load(const char *f) { + view_->set_changed(); +view_->load(f); +window_->label(view_->title()); +} + +void Fl_Help_Dialog::position(int xx, int yy) { + window_->position(xx, yy); +} + +void Fl_Help_Dialog::resize(int xx, int yy, int ww, int hh) { + window_->resize(xx, yy, ww, hh); +} + +void Fl_Help_Dialog::show() { + window_->show(); +} + +void Fl_Help_Dialog::show(int argc, char **argv) { + window_->show(argc, argv); +} + +void Fl_Help_Dialog::textsize(uchar s) { + view_->textsize(s); + +if (s <= 8) + smaller_->deactivate(); +else + smaller_->activate(); + +if (s >= 18) + larger_->deactivate(); +else + larger_->activate(); +} + +uchar Fl_Help_Dialog::textsize() { + return (view_->textsize()); +} + +void Fl_Help_Dialog::topline(const char *n) { + view_->topline(n); +} + +void Fl_Help_Dialog::topline(int n) { + view_->topline(n); +} + +void Fl_Help_Dialog::value(const char *f) { + view_->set_changed(); +view_->value(f); +window_->label(view_->title()); +} + +const char * Fl_Help_Dialog::value() const { + return view_->value(); +} + +int Fl_Help_Dialog::visible() { + return (window_->visible()); +} + +int Fl_Help_Dialog::w() { + return (window_->w()); +} + +int Fl_Help_Dialog::x() { + return (window_->x()); +} + +int Fl_Help_Dialog::y() { + return (window_->y()); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Help_Dialog.fl b/Utilities/FLTK/src/Fl_Help_Dialog.fl new file mode 100644 index 0000000000..e06c555000 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Help_Dialog.fl @@ -0,0 +1,269 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {../FL/Fl_Help_Dialog.H} +code_name {.cxx} +comment {// +// "$Id: Fl_Help_Dialog.fl 4721 2005-12-19 16:52:11Z matt $" +// +// Fl_Help_Dialog dialog for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +} {in_source in_header +} + +decl {\#include "flstring.h"} {} + +decl {\#include <FL/fl_ask.H>} {} + +class FL_EXPORT Fl_Help_Dialog {open +} { + decl {int index_;} {} + decl {int max_;} {} + decl {int line_[100];} {} + decl {char file_[100][256];} {} + decl {int find_pos_;} {} + Function {Fl_Help_Dialog()} {} { + Fl_Window window_ { + label {Help Dialog} open + private xywh {398 65 530 385} type Double resizable size_range {260 150 0 0} visible + } { + Fl_Group view_ { + callback {if (view_->filename()) +{ + if (view_->changed()) + { + index_ ++; + + if (index_ >= 100) + { + memmove(line_, line_ + 10, sizeof(line_[0]) * 90); + memmove(file_, file_ + 10, sizeof(file_[0]) * 90); + index_ -= 10; + } + + max_ = index_; + + strlcpy(file_[index_], view_->filename(),sizeof(file_[0])); + line_[index_] = view_->topline(); + + if (index_ > 0) + back_->activate(); + else + back_->deactivate(); + + forward_->deactivate(); + window_->label(view_->title()); + } + else // if ! view_->changed() + { + strlcpy(file_[index_], view_->filename(), sizeof(file_[0])); + line_[index_] = view_->topline(); + } +} else { // if ! view_->filename() + index_ = 0; // hitting an internal page will disable the back/fwd buffer + file_[index_][0] = 0; // unnamed internal page + line_[index_] = view_->topline(); + back_->deactivate(); + forward_->deactivate(); +}} open + private xywh {10 10 510 330} box DOWN_BOX selection_color 15 resizable + code0 {\#include <FL/Fl_Help_View.H>} + class Fl_Help_View + } {} + Fl_Group {} {open + xywh {10 348 510 27} + } { + Fl_Button {} { + label Close + callback {window_->hide();} + private xywh {456 350 64 25} + code0 {o->label(fl_close);} + } + Fl_Button back_ { + label {@<-} + callback {if (index_ > 0) + index_ --; + +if (index_ == 0) + back_->deactivate(); + +forward_->activate(); + +int l = line_[index_]; + +if (strcmp(view_->filename(), file_[index_]) != 0) + view_->load(file_[index_]); + +view_->topline(l);} + private tooltip {Show the previous help page.} xywh {386 350 25 25} shortcut 0xff51 labelcolor 2 + } + Fl_Button forward_ { + label {@->} + callback {if (index_ < max_) + index_ ++; + +if (index_ >= max_) + forward_->deactivate(); + +back_->activate(); + +int l = view_->topline(); + +if (strcmp(view_->filename(), file_[index_]) != 0) + view_->load(file_[index_]); + +view_->topline(l);} + private tooltip {Show the next help page.} xywh {421 350 25 25} shortcut 0xff53 labelcolor 2 + } + Fl_Button smaller_ { + label F + callback {if (view_->textsize() > 8) + view_->textsize(view_->textsize() - 2); + +if (view_->textsize() <= 8) + smaller_->deactivate(); +larger_->activate();} + private tooltip {Make the help text smaller.} xywh {316 350 25 25} labelfont 1 labelsize 10 + } + Fl_Button larger_ { + label F + callback {if (view_->textsize() < 18) + view_->textsize(view_->textsize() + 2); + +if (view_->textsize() >= 18) + larger_->deactivate(); +smaller_->activate();} + private tooltip {Make the help text larger.} xywh {351 350 25 25} labelfont 1 labelsize 16 + } + Fl_Group {} {open + xywh {10 350 296 25} box DOWN_BOX color 7 resizable + } { + Fl_Input find_ { + label {@search} + callback {find_pos_ = view_->find(find_->value(), find_pos_);} selected + private tooltip {find text in document} xywh {35 352 268 21} box FLAT_BOX labelsize 13 when 10 resizable + } + } + } + } + code {back_->deactivate(); +forward_->deactivate(); + +index_ = -1; +max_ = 0; +find_pos_ = 0; + +fl_register_images();} {} + } + Function {~Fl_Help_Dialog()} {} { + code {delete window_;} {} + } + Function {h()} {return_type int + } { + code {return (window_->h());} {} + } + Function {hide()} {return_type void + } { + code {window_->hide();} {} + } + Function {load(const char *f)} {return_type void + } { + code {view_->set_changed(); +view_->load(f); +window_->label(view_->title());} {} + } + Function {position(int xx, int yy)} {return_type void + } { + code {window_->position(xx, yy);} {} + } + Function {resize(int xx, int yy, int ww, int hh)} {return_type void + } { + code {window_->resize(xx, yy, ww, hh);} {} + } + Function {show()} {return_type void + } { + code {window_->show();} {} + } + Function {show(int argc, char **argv)} {return_type void + } { + code {window_->show(argc, argv);} {} + } + Function {textsize(uchar s)} {return_type void + } { + code {view_->textsize(s); + +if (s <= 8) + smaller_->deactivate(); +else + smaller_->activate(); + +if (s >= 18) + larger_->deactivate(); +else + larger_->activate();} {} + } + Function {textsize()} {return_type uchar + } { + code {return (view_->textsize());} {} + } + Function {topline(const char *n)} {return_type void + } { + code {view_->topline(n);} {} + } + Function {topline(int n)} {return_type void + } { + code {view_->topline(n);} {} + } + Function {value(const char *f)} {return_type void + } { + code {view_->set_changed(); +view_->value(f); +window_->label(view_->title());} {} + } + Function {value() const} {return_type {const char *} + } { + code {return view_->value();} {} + } + Function {visible()} {return_type int + } { + code {return (window_->visible());} {} + } + Function {w()} {return_type int + } { + code {return (window_->w());} {} + } + Function {x()} {return_type int + } { + code {return (window_->x());} {} + } + Function {y()} {return_type int + } { + code {return (window_->y());} {} + } +} + +comment { +// +// End of "$Id: Fl_Help_Dialog.fl 4721 2005-12-19 16:52:11Z matt $". +//} {in_source in_header +} diff --git a/Utilities/FLTK/src/Fl_Help_View.cxx b/Utilities/FLTK/src/Fl_Help_View.cxx new file mode 100644 index 0000000000..83c97bcf80 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Help_View.cxx @@ -0,0 +1,2924 @@ +// +// "$Id$" +// +// Fl_Help_View widget routines. +// +// Copyright 1997-2005 by Easy Software Products. +// Image support donated by Matthias Melcher, Copyright 2000. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +// Contents: +// +// Fl_Help_View::add_block() - Add a text block to the list. +// Fl_Help_View::add_link() - Add a new link to the list. +// Fl_Help_View::add_target() - Add a new target to the list. +// Fl_Help_View::compare_targets() - Compare two targets. +// Fl_Help_View::do_align() - Compute the alignment for a line in +// a block. +// Fl_Help_View::draw() - Draw the Fl_Help_View widget. +// Fl_Help_View::format() - Format the help text. +// Fl_Help_View::format_table() - Format a table... +// Fl_Help_View::get_align() - Get an alignment attribute. +// Fl_Help_View::get_attr() - Get an attribute value from the string. +// Fl_Help_View::get_color() - Get an alignment attribute. +// Fl_Help_View::handle() - Handle events in the widget. +// Fl_Help_View::Fl_Help_View() - Build a Fl_Help_View widget. +// Fl_Help_View::~Fl_Help_View() - Destroy a Fl_Help_View widget. +// Fl_Help_View::load() - Load the specified file. +// Fl_Help_View::resize() - Resize the help widget. +// Fl_Help_View::topline() - Set the top line to the named target. +// Fl_Help_View::topline() - Set the top line by number. +// Fl_Help_View::value() - Set the help text directly. +// scrollbar_callback() - A callback for the scrollbar. +// + +// +// Include necessary header files... +// + +#include <FL/Fl_Help_View.H> +#include <FL/Fl_Pixmap.H> +#include <stdio.h> +#include <stdlib.h> +#include "flstring.h" +#include <ctype.h> +#include <errno.h> +#include <math.h> + +#if defined(WIN32) && ! defined(__CYGWIN__) +# include <io.h> +# include <direct.h> +// Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs +// on Windows, which is supposed to be POSIX compliant... +# define getcwd _getcwd +#else +# include <unistd.h> +#endif // WIN32 + +#define MAX_COLUMNS 200 + + +// +// Typedef the C API sort function type the only way I know how... +// + +extern "C" +{ + typedef int (*compare_func_t)(const void *, const void *); +} + + +// +// Local functions... +// + +static int quote_char(const char *); +static void scrollbar_callback(Fl_Widget *s, void *); +static void hscrollbar_callback(Fl_Widget *s, void *); + + +// +// Broken image... +// + +static const char *broken_xpm[] = + { + "16 24 4 1", + "@ c #000000", + " c #ffffff", + "+ c none", + "x c #ff0000", + // pixels + "@@@@@@@+++++++++", + "@ @++++++++++", + "@ @+++++++++++", + "@ @++@++++++++", + "@ @@+++++++++", + "@ @+++@+++++", + "@ @++@@++++@", + "@ xxx @@ @++@@", + "@ xxx xx@@ @", + "@ xxx xxx @", + "@ xxxxxx @", + "@ xxxx @", + "@ xxxxxx @", + "@ xxx xxx @", + "@ xxx xxx @", + "@ xxx xxx @", + "@ @", + "@ @", + "@ @", + "@ @", + "@ @", + "@ @", + "@ @", + "@@@@@@@@@@@@@@@@", + NULL + }; + +static Fl_Pixmap broken_image(broken_xpm); + + +// +// 'Fl_Help_View::add_block()' - Add a text block to the list. +// + +Fl_Help_Block * // O - Pointer to new block +Fl_Help_View::add_block(const char *s, // I - Pointer to start of block text + int xx, // I - X position of block + int yy, // I - Y position of block + int ww, // I - Right margin of block + int hh, // I - Height of block + unsigned char border) // I - Draw border? +{ + Fl_Help_Block *temp; // New block + + +// printf("add_block(s = %p, xx = %d, yy = %d, ww = %d, hh = %d, border = %d)\n", +// s, xx, yy, ww, hh, border); + + if (nblocks_ >= ablocks_) + { + ablocks_ += 16; + + if (ablocks_ == 16) + blocks_ = (Fl_Help_Block *)malloc(sizeof(Fl_Help_Block) * ablocks_); + else + blocks_ = (Fl_Help_Block *)realloc(blocks_, sizeof(Fl_Help_Block) * ablocks_); + } + + temp = blocks_ + nblocks_; + memset(temp, 0, sizeof(Fl_Help_Block)); + temp->start = s; + temp->end = s; + temp->x = xx; + temp->y = yy; + temp->w = ww; + temp->h = hh; + temp->border = border; + temp->bgcolor = bgcolor_; + nblocks_ ++; + + return (temp); +} + + +// +// 'Fl_Help_View::add_link()' - Add a new link to the list. +// + +void +Fl_Help_View::add_link(const char *n, // I - Name of link + int xx, // I - X position of link + int yy, // I - Y position of link + int ww, // I - Width of link text + int hh) // I - Height of link text +{ + Fl_Help_Link *temp; // New link + char *target; // Pointer to target name + + + if (nlinks_ >= alinks_) + { + alinks_ += 16; + + if (alinks_ == 16) + links_ = (Fl_Help_Link *)malloc(sizeof(Fl_Help_Link) * alinks_); + else + links_ = (Fl_Help_Link *)realloc(links_, sizeof(Fl_Help_Link) * alinks_); + } + + temp = links_ + nlinks_; + + temp->x = xx; + temp->y = yy; + temp->w = xx + ww; + temp->h = yy + hh; + + strlcpy(temp->filename, n, sizeof(temp->filename)); + + if ((target = strrchr(temp->filename, '#')) != NULL) + { + *target++ = '\0'; + strlcpy(temp->name, target, sizeof(temp->name)); + } + else + temp->name[0] = '\0'; + + nlinks_ ++; +} + + +// +// 'Fl_Help_View::add_target()' - Add a new target to the list. +// + +void +Fl_Help_View::add_target(const char *n, // I - Name of target + int yy) // I - Y position of target +{ + Fl_Help_Target *temp; // New target + + + if (ntargets_ >= atargets_) + { + atargets_ += 16; + + if (atargets_ == 16) + targets_ = (Fl_Help_Target *)malloc(sizeof(Fl_Help_Target) * atargets_); + else + targets_ = (Fl_Help_Target *)realloc(targets_, sizeof(Fl_Help_Target) * atargets_); + } + + temp = targets_ + ntargets_; + + temp->y = yy; + strlcpy(temp->name, n, sizeof(temp->name)); + + ntargets_ ++; +} + + +// +// 'Fl_Help_View::compare_targets()' - Compare two targets. +// + +int // O - Result of comparison +Fl_Help_View::compare_targets(const Fl_Help_Target *t0, // I - First target + const Fl_Help_Target *t1) // I - Second target +{ + return (strcasecmp(t0->name, t1->name)); +} + + +// +// 'Fl_Help_View::do_align()' - Compute the alignment for a line in a block. +// + +int // O - New line +Fl_Help_View::do_align(Fl_Help_Block *block, // I - Block to add to + int line, // I - Current line + int xx, // I - Current X position + int a, // I - Current alignment + int &l) // IO - Starting link +{ + int offset; // Alignment offset + + + switch (a) + { + case RIGHT : // Right align + offset = block->w - xx; + break; + case CENTER : // Center + offset = (block->w - xx) / 2; + break; + default : // Left align + offset = 0; + break; + } + + block->line[line] = block->x + offset; + + if (line < 31) + line ++; + + while (l < nlinks_) + { + links_[l].x += offset; + links_[l].w += offset; + l ++; + } + + return (line); +} + + +// +// 'Fl_Help_View::draw()' - Draw the Fl_Help_View widget. +// + +void +Fl_Help_View::draw() +{ + int i; // Looping var + const Fl_Help_Block *block; // Pointer to current block + const char *ptr, // Pointer to text in block + *attrs; // Pointer to start of element attributes + char *s, // Pointer into buffer + buf[1024], // Text buffer + attr[1024]; // Attribute buffer + int xx, yy, ww, hh; // Current positions and sizes + int line; // Current line + unsigned char font, fsize; // Current font and size + int head, pre, // Flags for text + needspace; // Do we need whitespace? + Fl_Boxtype b = box() ? box() : FL_DOWN_BOX; + // Box to draw... + int underline, // Underline text? + xtra_ww; // Extra width for underlined space between words + + + // Draw the scrollbar(s) and box first... + ww = w() ; + hh = h(); + i = 0; + + draw_box(b, x(), y(), ww, hh, bgcolor_); + + if (hscrollbar_.visible()) { + draw_child(hscrollbar_); + hh -= 17; + i ++; + } + if (scrollbar_.visible()) { + draw_child(scrollbar_); + ww -= 17; + i ++; + } + if (i == 2) { + fl_color(FL_GRAY); + fl_rectf(x() + ww - Fl::box_dw(b) + Fl::box_dx(b), + y() + hh - Fl::box_dh(b) + Fl::box_dy(b), 17, 17); + } + + if (!value_) + return; + + // Clip the drawing to the inside of the box... + fl_push_clip(x() + Fl::box_dx(b), y() + Fl::box_dy(b), + ww - Fl::box_dw(b), hh - Fl::box_dh(b)); + fl_color(textcolor_); + + // Draw all visible blocks... + for (i = 0, block = blocks_; i < nblocks_; i ++, block ++) + if ((block->y + block->h) >= topline_ && block->y < (topline_ + h())) + { + line = 0; + xx = block->line[line]; + yy = block->y - topline_; + hh = 0; + pre = 0; + head = 0; + needspace = 0; + underline = 0; + + initfont(font, fsize); + + for (ptr = block->start, s = buf; ptr < block->end;) + { + if ((*ptr == '<' || isspace(*ptr)) && s > buf) + { + if (!head && !pre) + { + // Check width... + *s = '\0'; + s = buf; + ww = (int)fl_width(buf); + + if (needspace && xx > block->x) + xx += (int)fl_width(' '); + + if ((xx + ww) > block->w) + { + if (line < 31) + line ++; + xx = block->line[line]; + yy += hh; + hh = 0; + } + + fl_draw(buf, xx + x() - leftline_, yy + y()); + if (underline) { + xtra_ww = isspace(*ptr)?(int)fl_width(' '):0; + fl_xyline(xx + x() - leftline_, yy + y() + 1, + xx + x() - leftline_ + ww + xtra_ww); + } + + xx += ww; + if ((fsize + 2) > hh) + hh = fsize + 2; + + needspace = 0; + } + else if (pre) + { + while (isspace(*ptr)) + { + if (*ptr == '\n') + { + *s = '\0'; + s = buf; + + fl_draw(buf, xx + x() - leftline_, yy + y()); + if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1, + xx + x() - leftline_ + + (int)fl_width(buf)); + + if (line < 31) + line ++; + xx = block->line[line]; + yy += hh; + hh = fsize + 2; + } + else if (*ptr == '\t') + { + // Do tabs every 8 columns... + while (((s - buf) & 7)) + *s++ = ' '; + } + else + *s++ = ' '; + + if ((fsize + 2) > hh) + hh = fsize + 2; + + ptr ++; + } + + if (s > buf) + { + *s = '\0'; + s = buf; + + fl_draw(buf, xx + x() - leftline_, yy + y()); + ww = (int)fl_width(buf); + if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1, + xx + x() - leftline_ + ww); + xx += ww; + } + + needspace = 0; + } + else + { + s = buf; + + while (isspace(*ptr)) + ptr ++; + } + } + + if (*ptr == '<') + { + ptr ++; + + if (strncmp(ptr, "!--", 3) == 0) + { + // Comment... + ptr += 3; + if ((ptr = strstr(ptr, "-->")) != NULL) + { + ptr += 3; + continue; + } + else + break; + } + + while (*ptr && *ptr != '>' && !isspace(*ptr)) + if (s < (buf + sizeof(buf) - 1)) + *s++ = *ptr++; + else + ptr ++; + + *s = '\0'; + s = buf; + + attrs = ptr; + while (*ptr && *ptr != '>') + ptr ++; + + if (*ptr == '>') + ptr ++; + + if (strcasecmp(buf, "HEAD") == 0) + head = 1; + else if (strcasecmp(buf, "BR") == 0) + { + if (line < 31) + line ++; + xx = block->line[line]; + yy += hh; + hh = 0; + } + else if (strcasecmp(buf, "HR") == 0) + { + fl_line(block->x + x(), yy + y(), block->w + x(), + yy + y()); + + if (line < 31) + line ++; + xx = block->line[line]; + yy += 2 * hh; + hh = 0; + } + else if (strcasecmp(buf, "CENTER") == 0 || + strcasecmp(buf, "P") == 0 || + strcasecmp(buf, "H1") == 0 || + strcasecmp(buf, "H2") == 0 || + strcasecmp(buf, "H3") == 0 || + strcasecmp(buf, "H4") == 0 || + strcasecmp(buf, "H5") == 0 || + strcasecmp(buf, "H6") == 0 || + strcasecmp(buf, "UL") == 0 || + strcasecmp(buf, "OL") == 0 || + strcasecmp(buf, "DL") == 0 || + strcasecmp(buf, "LI") == 0 || + strcasecmp(buf, "DD") == 0 || + strcasecmp(buf, "DT") == 0 || + strcasecmp(buf, "PRE") == 0) + { + if (tolower(buf[0]) == 'h') + { + font = FL_HELVETICA_BOLD; + fsize = (uchar)(textsize_ + '7' - buf[1]); + } + else if (strcasecmp(buf, "DT") == 0) + { + font = (uchar)(textfont_ | FL_ITALIC); + fsize = textsize_; + } + else if (strcasecmp(buf, "PRE") == 0) + { + font = FL_COURIER; + fsize = textsize_; + pre = 1; + } + + if (strcasecmp(buf, "LI") == 0) + { +#ifdef __APPLE_QUARTZ__ + fl_font(FL_SYMBOL, fsize); + fl_draw("\245", xx - fsize + x() - leftline_, yy + y()); +#else + fl_font(FL_SYMBOL, fsize); + fl_draw("\267", xx - fsize + x() - leftline_, yy + y()); +#endif + } + + pushfont(font, fsize); + } + else if (strcasecmp(buf, "A") == 0 && + get_attr(attrs, "HREF", attr, sizeof(attr)) != NULL) + { + fl_color(linkcolor_); + underline = 1; + } + else if (strcasecmp(buf, "/A") == 0) + { + fl_color(textcolor_); + underline = 0; + } + else if (strcasecmp(buf, "FONT") == 0) + { + if (get_attr(attrs, "COLOR", attr, sizeof(attr)) != NULL) { + fl_color(get_color(attr, textcolor_)); + } + + if (get_attr(attrs, "FACE", attr, sizeof(attr)) != NULL) { + if (!strncasecmp(attr, "helvetica", 9) || + !strncasecmp(attr, "arial", 5) || + !strncasecmp(attr, "sans", 4)) font = FL_HELVETICA; + else if (!strncasecmp(attr, "times", 5) || + !strncasecmp(attr, "serif", 5)) font = FL_TIMES; + else if (!strncasecmp(attr, "symbol", 6)) font = FL_SYMBOL; + else font = FL_COURIER; + } + + if (get_attr(attrs, "SIZE", attr, sizeof(attr)) != NULL) { + if (isdigit(attr[0] & 255)) { + // Absolute size + fsize = (int)(textsize_ * pow(1.2, atof(attr) - 3.0)); + } else { + // Relative size + fsize = (int)(fsize * pow(1.2, atof(attr) - 3.0)); + } + } + + pushfont(font, fsize); + } + else if (strcasecmp(buf, "/FONT") == 0) + { + fl_color(textcolor_); + popfont(font, fsize); + } + else if (strcasecmp(buf, "U") == 0) + underline = 1; + else if (strcasecmp(buf, "/U") == 0) + underline = 0; + else if (strcasecmp(buf, "B") == 0 || + strcasecmp(buf, "STRONG") == 0) + pushfont(font |= FL_BOLD, fsize); + else if (strcasecmp(buf, "TD") == 0 || + strcasecmp(buf, "TH") == 0) + { + int tx, ty, tw, th; + + if (tolower(buf[1]) == 'h') + pushfont(font |= FL_BOLD, fsize); + else + pushfont(font = textfont_, fsize); + + tx = block->x - 4 - leftline_; + ty = block->y - topline_ - fsize - 3; + tw = block->w - block->x + 7; + th = block->h + fsize - 5; + + if (tx < 0) + { + tw += tx; + tx = 0; + } + + if (ty < 0) + { + th += ty; + ty = 0; + } + + tx += x(); + ty += y(); + + if (block->bgcolor != bgcolor_) + { + fl_color(block->bgcolor); + fl_rectf(tx, ty, tw, th); + fl_color(textcolor_); + } + + if (block->border) + fl_rect(tx, ty, tw, th); + } + else if (strcasecmp(buf, "I") == 0 || + strcasecmp(buf, "EM") == 0) + pushfont(font |= FL_ITALIC, fsize); + else if (strcasecmp(buf, "CODE") == 0 || + strcasecmp(buf, "TT") == 0) + pushfont(font = FL_COURIER, fsize); + else if (strcasecmp(buf, "KBD") == 0) + pushfont(font = FL_COURIER_BOLD, fsize); + else if (strcasecmp(buf, "VAR") == 0) + pushfont(font = FL_COURIER_ITALIC, fsize); + else if (strcasecmp(buf, "/HEAD") == 0) + head = 0; + else if (strcasecmp(buf, "/H1") == 0 || + strcasecmp(buf, "/H2") == 0 || + strcasecmp(buf, "/H3") == 0 || + strcasecmp(buf, "/H4") == 0 || + strcasecmp(buf, "/H5") == 0 || + strcasecmp(buf, "/H6") == 0 || + strcasecmp(buf, "/B") == 0 || + strcasecmp(buf, "/STRONG") == 0 || + strcasecmp(buf, "/I") == 0 || + strcasecmp(buf, "/EM") == 0 || + strcasecmp(buf, "/CODE") == 0 || + strcasecmp(buf, "/TT") == 0 || + strcasecmp(buf, "/KBD") == 0 || + strcasecmp(buf, "/VAR") == 0) + popfont(font, fsize); + else if (strcasecmp(buf, "/PRE") == 0) + { + popfont(font, fsize); + pre = 0; + } + else if (strcasecmp(buf, "IMG") == 0) + { + Fl_Shared_Image *img = 0; + int width, height; + char wattr[8], hattr[8]; + + + get_attr(attrs, "WIDTH", wattr, sizeof(wattr)); + get_attr(attrs, "HEIGHT", hattr, sizeof(hattr)); + width = get_length(wattr); + height = get_length(hattr); + + if (get_attr(attrs, "SRC", attr, sizeof(attr))) { + img = get_image(attr, width, height); + if (!width) width = img->w(); + if (!height) height = img->h(); + } + + if (!width || !height) { + if (get_attr(attrs, "ALT", attr, sizeof(attr)) == NULL) { + strcpy(attr, "IMG"); + } + } + + ww = width; + + if (needspace && xx > block->x) + xx += (int)fl_width(' '); + + if ((xx + ww) > block->w) + { + if (line < 31) + line ++; + + xx = block->line[line]; + yy += hh; + hh = 0; + } + + if (img) + img->draw(xx + x() - leftline_, + yy + y() - fl_height() + fl_descent() + 2); + + xx += ww; + if ((height + 2) > hh) + hh = height + 2; + + needspace = 0; + } + } + else if (*ptr == '\n' && pre) + { + *s = '\0'; + s = buf; + + fl_draw(buf, xx + x() - leftline_, yy + y()); + + if (line < 31) + line ++; + xx = block->line[line]; + yy += hh; + hh = fsize + 2; + needspace = 0; + + ptr ++; + } + else if (isspace(*ptr)) + { + if (pre) + { + if (*ptr == ' ') + *s++ = ' '; + else + { + // Do tabs every 8 columns... + while (((s - buf) & 7)) + *s++ = ' '; + } + } + + ptr ++; + needspace = 1; + } + else if (*ptr == '&') + { + ptr ++; + + int qch = quote_char(ptr); + + if (qch < 0) + *s++ = '&'; + else { + *s++ = qch; + ptr = strchr(ptr, ';') + 1; + } + + if ((fsize + 2) > hh) + hh = fsize + 2; + } + else + { + *s++ = *ptr++; + + if ((fsize + 2) > hh) + hh = fsize + 2; + } + } + + *s = '\0'; + + if (s > buf && !pre && !head) + { + ww = (int)fl_width(buf); + + if (needspace && xx > block->x) + xx += (int)fl_width(' '); + + if ((xx + ww) > block->w) + { + if (line < 31) + line ++; + xx = block->line[line]; + yy += hh; + hh = 0; + } + } + + if (s > buf && !head) + { + fl_draw(buf, xx + x() - leftline_, yy + y()); + if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1, + xx + x() - leftline_ + ww); + } + } + + fl_pop_clip(); +} + + +// +// 'Fl_Help_View::find()' - Find the specified string... +// + +int // O - Matching position or -1 if not found +Fl_Help_View::find(const char *s, // I - String to find + int p) // I - Starting position +{ + int i, // Looping var + c; // Current character + Fl_Help_Block *b; // Current block + const char *bp, // Block matching pointer + *bs, // Start of current comparison + *sp; // Search string pointer + + + // Range check input and value... + if (!s || !value_) return -1; + + if (p < 0 || p >= (int)strlen(value_)) p = 0; + else if (p > 0) p ++; + + // Look for the string... + for (i = nblocks_, b = blocks_; i > 0; i --, b ++) { + if (b->end < (value_ + p)) + continue; + + if (b->start < (value_ + p)) bp = value_ + p; + else bp = b->start; + + for (sp = s, bs = bp; *sp && *bp && bp < b->end; bp ++) { + if (*bp == '<') { + // skip to end of element... + while (*bp && bp < b->end && *bp != '>') bp ++; + continue; + } else if (*bp == '&') { + // decode HTML entity... + if ((c = quote_char(bp + 1)) < 0) c = '&'; + else bp = strchr(bp + 1, ';') + 1; + } else c = *bp; + + if (tolower(*sp) == tolower(c)) sp ++; + else { + // No match, so reset to start of search... + sp = s; + bs ++; + bp = bs; + } + } + + if (!*sp) { + // Found a match! + topline(b->y - b->h); + return (b->end - value_); + } + } + + // No match! + return (-1); +} + + +// +// 'Fl_Help_View::format()' - Format the help text. +// + +void +Fl_Help_View::format() +{ + int i; // Looping var + int done; // Are we done yet? + Fl_Help_Block *block, // Current block + *cell; // Current table cell + int cells[MAX_COLUMNS], + // Cells in the current row... + row; // Current table row (block number) + const char *ptr, // Pointer into block + *start, // Pointer to start of element + *attrs; // Pointer to start of element attributes + char *s, // Pointer into buffer + buf[1024], // Text buffer + attr[1024], // Attribute buffer + wattr[1024], // Width attribute buffer + hattr[1024], // Height attribute buffer + linkdest[1024]; // Link destination + int xx, yy, ww, hh; // Size of current text fragment + int line; // Current line in block + int links; // Links for current line + unsigned char font, fsize; // Current font and size + unsigned char border; // Draw border? + int talign, // Current alignment + newalign, // New alignment + head, // In the <HEAD> section? + pre, // <PRE> text? + needspace; // Do we need whitespace? + int table_width, // Width of table + table_offset; // Offset of table + int column, // Current table column number + columns[MAX_COLUMNS]; + // Column widths + Fl_Color tc, rc; // Table/row background color + Fl_Boxtype b = box() ? box() : FL_DOWN_BOX; + // Box to draw... + + + // Reset document width... + hsize_ = w() - 24; + + done = 0; + while (!done) + { + // Reset state variables... + done = 1; + nblocks_ = 0; + nlinks_ = 0; + ntargets_ = 0; + size_ = 0; + bgcolor_ = color(); + textcolor_ = textcolor(); + linkcolor_ = selection_color(); + + tc = rc = bgcolor_; + + strcpy(title_, "Untitled"); + + if (!value_) + return; + + // Setup for formatting... + initfont(font, fsize); + + line = 0; + links = 0; + xx = 4; + yy = fsize + 2; + ww = 0; + column = 0; + border = 0; + hh = 0; + block = add_block(value_, xx, yy, hsize_, 0); + row = 0; + head = 0; + pre = 0; + talign = LEFT; + newalign = LEFT; + needspace = 0; + linkdest[0] = '\0'; + table_offset = 0; + + for (ptr = value_, s = buf; *ptr;) + { + if ((*ptr == '<' || isspace(*ptr)) && s > buf) + { + // Get width... + *s = '\0'; + ww = (int)fl_width(buf); + + if (!head && !pre) + { + // Check width... + if (ww > hsize_) { + hsize_ = ww; + done = 0; + break; + } + + if (needspace && xx > block->x) + ww += (int)fl_width(' '); + + // printf("line = %d, xx = %d, ww = %d, block->x = %d, block->w = %d\n", + // line, xx, ww, block->x, block->w); + + if ((xx + ww) > block->w) + { + line = do_align(block, line, xx, newalign, links); + xx = block->x; + yy += hh; + block->h += hh; + hh = 0; + } + + if (linkdest[0]) + add_link(linkdest, xx, yy - fsize, ww, fsize); + + xx += ww; + if ((fsize + 2) > hh) + hh = fsize + 2; + + needspace = 0; + } + else if (pre) + { + // Add a link as needed... + if (linkdest[0]) + add_link(linkdest, xx, yy - hh, ww, hh); + + xx += ww; + if ((fsize + 2) > hh) + hh = fsize + 2; + + // Handle preformatted text... + while (isspace(*ptr)) + { + if (*ptr == '\n') + { + if (xx > hsize_) break; + + line = do_align(block, line, xx, newalign, links); + xx = block->x; + yy += hh; + block->h += hh; + hh = fsize + 2; + } + else + xx += (int)fl_width(' '); + + if ((fsize + 2) > hh) + hh = fsize + 2; + + ptr ++; + } + + if (xx > hsize_) { + hsize_ = xx; + done = 0; + break; + } + + needspace = 0; + } + else + { + // Handle normal text or stuff in the <HEAD> section... + while (isspace(*ptr)) + ptr ++; + } + + s = buf; + } + + if (*ptr == '<') + { + start = ptr; + ptr ++; + + if (strncmp(ptr, "!--", 3) == 0) + { + // Comment... + ptr += 3; + if ((ptr = strstr(ptr, "-->")) != NULL) + { + ptr += 3; + continue; + } + else + break; + } + + while (*ptr && *ptr != '>' && !isspace(*ptr)) + if (s < (buf + sizeof(buf) - 1)) + *s++ = *ptr++; + else + ptr ++; + + *s = '\0'; + s = buf; + +// puts(buf); + + attrs = ptr; + while (*ptr && *ptr != '>') + ptr ++; + + if (*ptr == '>') + ptr ++; + + if (strcasecmp(buf, "HEAD") == 0) + head = 1; + else if (strcasecmp(buf, "/HEAD") == 0) + head = 0; + else if (strcasecmp(buf, "TITLE") == 0) + { + // Copy the title in the document... + for (s = title_; + *ptr != '<' && *ptr && s < (title_ + sizeof(title_) - 1); + *s++ = *ptr++); + + *s = '\0'; + s = buf; + } + else if (strcasecmp(buf, "A") == 0) + { + if (get_attr(attrs, "NAME", attr, sizeof(attr)) != NULL) + add_target(attr, yy - fsize - 2); + + if (get_attr(attrs, "HREF", attr, sizeof(attr)) != NULL) + strlcpy(linkdest, attr, sizeof(linkdest)); + } + else if (strcasecmp(buf, "/A") == 0) + linkdest[0] = '\0'; + else if (strcasecmp(buf, "BODY") == 0) + { + bgcolor_ = get_color(get_attr(attrs, "BGCOLOR", attr, sizeof(attr)), + color()); + textcolor_ = get_color(get_attr(attrs, "TEXT", attr, sizeof(attr)), + textcolor()); + linkcolor_ = get_color(get_attr(attrs, "LINK", attr, sizeof(attr)), + selection_color()); + } + else if (strcasecmp(buf, "BR") == 0) + { + line = do_align(block, line, xx, newalign, links); + xx = block->x; + block->h += hh; + yy += hh; + hh = 0; + } + else if (strcasecmp(buf, "CENTER") == 0 || + strcasecmp(buf, "P") == 0 || + strcasecmp(buf, "H1") == 0 || + strcasecmp(buf, "H2") == 0 || + strcasecmp(buf, "H3") == 0 || + strcasecmp(buf, "H4") == 0 || + strcasecmp(buf, "H5") == 0 || + strcasecmp(buf, "H6") == 0 || + strcasecmp(buf, "UL") == 0 || + strcasecmp(buf, "OL") == 0 || + strcasecmp(buf, "DL") == 0 || + strcasecmp(buf, "LI") == 0 || + strcasecmp(buf, "DD") == 0 || + strcasecmp(buf, "DT") == 0 || + strcasecmp(buf, "HR") == 0 || + strcasecmp(buf, "PRE") == 0 || + strcasecmp(buf, "TABLE") == 0) + { + block->end = start; + line = do_align(block, line, xx, newalign, links); + xx = block->x; + block->h += hh; + + if (strcasecmp(buf, "UL") == 0 || + strcasecmp(buf, "OL") == 0 || + strcasecmp(buf, "DL") == 0) + { + block->h += fsize + 2; + xx += 4 * fsize; + } + else if (strcasecmp(buf, "TABLE") == 0) + { + if (get_attr(attrs, "BORDER", attr, sizeof(attr))) + border = (uchar)atoi(attr); + else + border = 0; + + tc = rc = get_color(get_attr(attrs, "BGCOLOR", attr, sizeof(attr)), bgcolor_); + + block->h += fsize + 2; + + format_table(&table_width, columns, start); + + if ((xx + table_width) > hsize_) { +#ifdef DEBUG + printf("xx=%d, table_width=%d, hsize_=%d\n", xx, table_width, + hsize_); +#endif // DEBUG + hsize_ = xx + table_width; + done = 0; + break; + } + + switch (get_align(attrs, talign)) + { + default : + table_offset = 0; + break; + + case CENTER : + table_offset = (hsize_ - table_width) / 2 - textsize_; + break; + + case RIGHT : + table_offset = hsize_ - table_width - textsize_; + break; + } + + column = 0; + } + + if (tolower(buf[0]) == 'h' && isdigit(buf[1])) + { + font = FL_HELVETICA_BOLD; + fsize = (uchar)(textsize_ + '7' - buf[1]); + } + else if (strcasecmp(buf, "DT") == 0) + { + font = (uchar)(textfont_ | FL_ITALIC); + fsize = textsize_; + } + else if (strcasecmp(buf, "PRE") == 0) + { + font = FL_COURIER; + fsize = textsize_; + pre = 1; + } + else + { + font = textfont_; + fsize = textsize_; + } + + pushfont(font, fsize); + + yy = block->y + block->h; + hh = 0; + + if ((tolower(buf[0]) == 'h' && isdigit(buf[1])) || + strcasecmp(buf, "DD") == 0 || + strcasecmp(buf, "DT") == 0 || + strcasecmp(buf, "P") == 0) + yy += fsize + 2; + else if (strcasecmp(buf, "HR") == 0) + { + hh += 2 * fsize; + yy += fsize; + } + + if (row) + block = add_block(start, xx, yy, block->w, 0); + else + block = add_block(start, xx, yy, hsize_, 0); + + needspace = 0; + line = 0; + + if (strcasecmp(buf, "CENTER") == 0) + newalign = talign = CENTER; + else + newalign = get_align(attrs, talign); + } + else if (strcasecmp(buf, "/CENTER") == 0 || + strcasecmp(buf, "/P") == 0 || + strcasecmp(buf, "/H1") == 0 || + strcasecmp(buf, "/H2") == 0 || + strcasecmp(buf, "/H3") == 0 || + strcasecmp(buf, "/H4") == 0 || + strcasecmp(buf, "/H5") == 0 || + strcasecmp(buf, "/H6") == 0 || + strcasecmp(buf, "/PRE") == 0 || + strcasecmp(buf, "/UL") == 0 || + strcasecmp(buf, "/OL") == 0 || + strcasecmp(buf, "/DL") == 0 || + strcasecmp(buf, "/TABLE") == 0) + { + line = do_align(block, line, xx, newalign, links); + xx = block->x; + block->end = ptr; + + if (strcasecmp(buf, "/UL") == 0 || + strcasecmp(buf, "/OL") == 0 || + strcasecmp(buf, "/DL") == 0) + { + xx -= 4 * fsize; + block->h += fsize + 2; + } + else if (strcasecmp(buf, "/TABLE") == 0) + { + block->h += fsize + 2; + // the current block is *not* the table block, so the current xx is + // meaningless. Set it back to page x, so the next block will be aligned + // reasonably. This fails fro table-in-table html! + xx = 4; + } + else if (strcasecmp(buf, "/PRE") == 0) + { + pre = 0; + hh = 0; + } + else if (strcasecmp(buf, "/CENTER") == 0) + talign = LEFT; + + popfont(font, fsize); + + while (isspace(*ptr)) + ptr ++; + + block->h += hh; + yy += hh; + + if (tolower(buf[2]) == 'l') + yy += fsize + 2; + + if (row) + block = add_block(ptr, xx, yy, block->w, 0); + else + block = add_block(ptr, xx, yy, hsize_, 0); + + needspace = 0; + hh = 0; + line = 0; + newalign = talign; + } + else if (strcasecmp(buf, "TR") == 0) + { + block->end = start; + line = do_align(block, line, xx, newalign, links); + xx = block->x; + block->h += hh; + + if (row) + { + yy = blocks_[row].y + blocks_[row].h; + + for (cell = blocks_ + row + 1; cell <= block; cell ++) + if ((cell->y + cell->h) > yy) + yy = cell->y + cell->h; + + block = blocks_ + row; + + block->h = yy - block->y + 2; + + for (i = 0; i < column; i ++) + if (cells[i]) + { + cell = blocks_ + cells[i]; + cell->h = block->h; + } + } + + memset(cells, 0, sizeof(cells)); + + yy = block->y + block->h - 4; + hh = 0; + block = add_block(start, xx, yy, hsize_, 0); + row = block - blocks_; + needspace = 0; + column = 0; + line = 0; + + rc = get_color(get_attr(attrs, "BGCOLOR", attr, sizeof(attr)), tc); + } + else if (strcasecmp(buf, "/TR") == 0 && row) + { + line = do_align(block, line, xx, newalign, links); + block->end = start; + block->h += hh; + + xx = blocks_[row].x; + + yy = blocks_[row].y + blocks_[row].h; + + for (cell = blocks_ + row + 1; cell <= block; cell ++) + if ((cell->y + cell->h) > yy) + yy = cell->y + cell->h; + + block = blocks_ + row; + + block->h = yy - block->y + 2; + + for (i = 0; i < column; i ++) + if (cells[i]) + { + cell = blocks_ + cells[i]; + cell->h = block->h; + } + + yy = block->y + block->h - 4; + block = add_block(start, xx, yy, hsize_, 0); + needspace = 0; + row = 0; + line = 0; + } + else if ((strcasecmp(buf, "TD") == 0 || + strcasecmp(buf, "TH") == 0) && row) + { + int colspan; // COLSPAN attribute + + + line = do_align(block, line, xx, newalign, links); + block->end = start; + block->h += hh; + + if (strcasecmp(buf, "TH") == 0) + font = (uchar)(textfont_ | FL_BOLD); + else + font = textfont_; + + fsize = textsize_; + + xx = blocks_[row].x + fsize + 3 + table_offset; + for (i = 0; i < column; i ++) + xx += columns[i] + 6; + + if (get_attr(attrs, "COLSPAN", attr, sizeof(attr)) != NULL) + colspan = atoi(attr); + else + colspan = 1; + + for (i = 0, ww = -6; i < colspan; i ++) + ww += columns[column + i] + 6; + + if (block->end == block->start && nblocks_ > 1) + { + nblocks_ --; + block --; + } + + pushfont(font, fsize); + + yy = blocks_[row].y; + hh = 0; + block = add_block(start, xx, yy, xx + ww, 0, border); + needspace = 0; + line = 0; + newalign = get_align(attrs, tolower(buf[1]) == 'h' ? CENTER : LEFT); + talign = newalign; + + cells[column] = block - blocks_; + + column += colspan; + + block->bgcolor = get_color(get_attr(attrs, "BGCOLOR", attr, + sizeof(attr)), rc); + } + else if ((strcasecmp(buf, "/TD") == 0 || + strcasecmp(buf, "/TH") == 0) && row) + { + popfont(font, fsize); + } + else if (strcasecmp(buf, "FONT") == 0) + { + if (get_attr(attrs, "FACE", attr, sizeof(attr)) != NULL) { + if (!strncasecmp(attr, "helvetica", 9) || + !strncasecmp(attr, "arial", 5) || + !strncasecmp(attr, "sans", 4)) font = FL_HELVETICA; + else if (!strncasecmp(attr, "times", 5) || + !strncasecmp(attr, "serif", 5)) font = FL_TIMES; + else if (!strncasecmp(attr, "symbol", 6)) font = FL_SYMBOL; + else font = FL_COURIER; + } + + if (get_attr(attrs, "SIZE", attr, sizeof(attr)) != NULL) { + if (isdigit(attr[0] & 255)) { + // Absolute size + fsize = (int)(textsize_ * pow(1.2, atoi(attr) - 3.0)); + } else { + // Relative size + fsize = (int)(fsize * pow(1.2, atoi(attr))); + } + } + + pushfont(font, fsize); + } + else if (strcasecmp(buf, "/FONT") == 0) + popfont(font, fsize); + else if (strcasecmp(buf, "B") == 0 || + strcasecmp(buf, "STRONG") == 0) + pushfont(font |= FL_BOLD, fsize); + else if (strcasecmp(buf, "I") == 0 || + strcasecmp(buf, "EM") == 0) + pushfont(font |= FL_ITALIC, fsize); + else if (strcasecmp(buf, "CODE") == 0 || + strcasecmp(buf, "TT") == 0) + pushfont(font = FL_COURIER, fsize); + else if (strcasecmp(buf, "KBD") == 0) + pushfont(font = FL_COURIER_BOLD, fsize); + else if (strcasecmp(buf, "VAR") == 0) + pushfont(font = FL_COURIER_ITALIC, fsize); + else if (strcasecmp(buf, "/B") == 0 || + strcasecmp(buf, "/STRONG") == 0 || + strcasecmp(buf, "/I") == 0 || + strcasecmp(buf, "/EM") == 0 || + strcasecmp(buf, "/CODE") == 0 || + strcasecmp(buf, "/TT") == 0 || + strcasecmp(buf, "/KBD") == 0 || + strcasecmp(buf, "/VAR") == 0) + popfont(font, fsize); + else if (strcasecmp(buf, "IMG") == 0) + { + Fl_Shared_Image *img = 0; + int width; + int height; + + + get_attr(attrs, "WIDTH", wattr, sizeof(wattr)); + get_attr(attrs, "HEIGHT", hattr, sizeof(hattr)); + width = get_length(wattr); + height = get_length(hattr); + + if (get_attr(attrs, "SRC", attr, sizeof(attr))) { + img = get_image(attr, width, height); + width = img->w(); + height = img->h(); + } + + ww = width; + + if (ww > hsize_) { + hsize_ = ww; + done = 0; + break; + } + + if (needspace && xx > block->x) + ww += (int)fl_width(' '); + + if ((xx + ww) > block->w) + { + line = do_align(block, line, xx, newalign, links); + xx = block->x; + yy += hh; + block->h += hh; + hh = 0; + } + + if (linkdest[0]) + add_link(linkdest, xx, yy - height, ww, height); + + xx += ww; + if ((height + 2) > hh) + hh = height + 2; + + needspace = 0; + } + } + else if (*ptr == '\n' && pre) + { + if (linkdest[0]) + add_link(linkdest, xx, yy - hh, ww, hh); + + if (xx > hsize_) { + hsize_ = xx; + done = 0; + break; + } + + line = do_align(block, line, xx, newalign, links); + xx = block->x; + yy += hh; + block->h += hh; + needspace = 0; + ptr ++; + } + else if (isspace(*ptr)) + { + needspace = 1; + + ptr ++; + } + else if (*ptr == '&' && s < (buf + sizeof(buf) - 1)) + { + ptr ++; + + int qch = quote_char(ptr); + + if (qch < 0) + *s++ = '&'; + else { + *s++ = qch; + ptr = strchr(ptr, ';') + 1; + } + + if ((fsize + 2) > hh) + hh = fsize + 2; + } + else + { + if (s < (buf + sizeof(buf) - 1)) + *s++ = *ptr++; + else + ptr ++; + + if ((fsize + 2) > hh) + hh = fsize + 2; + } + } + + if (s > buf && !head) + { + *s = '\0'; + ww = (int)fl_width(buf); + + // printf("line = %d, xx = %d, ww = %d, block->x = %d, block->w = %d\n", + // line, xx, ww, block->x, block->w); + + if (ww > hsize_) { + hsize_ = ww; + done = 0; + break; + } + + if (needspace && xx > block->x) + ww += (int)fl_width(' '); + + if ((xx + ww) > block->w) + { + line = do_align(block, line, xx, newalign, links); + xx = block->x; + yy += hh; + block->h += hh; + hh = 0; + } + + if (linkdest[0]) + add_link(linkdest, xx, yy - fsize, ww, fsize); + + xx += ww; + } + + do_align(block, line, xx, newalign, links); + + block->end = ptr; + size_ = yy + hh; + } + + + if (ntargets_ > 1) + qsort(targets_, ntargets_, sizeof(Fl_Help_Target), + (compare_func_t)compare_targets); + + int dx = Fl::box_dw(b) - Fl::box_dx(b); + int dy = Fl::box_dh(b) - Fl::box_dy(b); + + if (hsize_ > (w() - 24)) { + hscrollbar_.show(); + + if (size_ < (h() - 24)) { + scrollbar_.hide(); + hscrollbar_.resize(x() + Fl::box_dx(b), y() + h() - 17 - dy, w() - Fl::box_dw(b), 17); + } else { + scrollbar_.show(); + scrollbar_.resize(x() + w() - 17 - dx, y() + Fl::box_dy(b), 17, h() - 17 - Fl::box_dh(b)); + hscrollbar_.resize(x() + Fl::box_dx(b), y() + h() - 17 - dy, w() - 17 - Fl::box_dw(b), 17); + } + } else { + hscrollbar_.hide(); + + if (size_ < (h() - 8)) scrollbar_.hide(); + else { + scrollbar_.resize(x() + w() - 17 - dx, y() + Fl::box_dy(b), 17, h() - Fl::box_dh(b)); + scrollbar_.show(); + } + } + + // Reset scrolling if it needs to be... + if (scrollbar_.visible()) { + int temph = h() - 8; + if (hscrollbar_.visible()) temph -= 16; + if ((topline_ + temph) > size_) topline(size_ - temph); + else topline(topline_); + } else topline(0); + + if (hscrollbar_.visible()) { + int tempw = w() - 24; + if ((leftline_ + tempw) > hsize_) leftline(hsize_ - tempw); + else leftline(leftline_); + } else leftline(0); +} + + +// +// 'Fl_Help_View::format_table()' - Format a table... +// + +void +Fl_Help_View::format_table(int *table_width, // O - Total table width + int *columns, // O - Column widths + const char *table) // I - Pointer to start of table +{ + int column, // Current column + num_columns, // Number of columns + colspan, // COLSPAN attribute + width, // Current width + temp_width, // Temporary width + max_width, // Maximum width + incell, // In a table cell? + pre, // <PRE> text? + needspace; // Need whitespace? + char *s, // Pointer into buffer + buf[1024], // Text buffer + attr[1024], // Other attribute + wattr[1024], // WIDTH attribute + hattr[1024]; // HEIGHT attribute + const char *ptr, // Pointer into table + *attrs, // Pointer to attributes + *start; // Start of element + int minwidths[MAX_COLUMNS]; // Minimum widths for each column + unsigned char font, fsize; // Current font and size + + + // Clear widths... + *table_width = 0; + for (column = 0; column < MAX_COLUMNS; column ++) + { + columns[column] = 0; + minwidths[column] = 0; + } + + num_columns = 0; + colspan = 0; + max_width = 0; + pre = 0; + needspace = 0; + font = fonts_[nfonts_][0]; + fsize = fonts_[nfonts_][1]; + + // Scan the table... + for (ptr = table, column = -1, width = 0, s = buf, incell = 0; *ptr;) + { + if ((*ptr == '<' || isspace(*ptr)) && s > buf && incell) + { + // Check width... + if (needspace) + { + *s++ = ' '; + needspace = 0; + } + + *s = '\0'; + temp_width = (int)fl_width(buf); + s = buf; + + if (temp_width > minwidths[column]) + minwidths[column] = temp_width; + + width += temp_width; + + if (width > max_width) + max_width = width; + } + + if (*ptr == '<') + { + start = ptr; + + for (s = buf, ptr ++; *ptr && *ptr != '>' && !isspace(*ptr);) + if (s < (buf + sizeof(buf) - 1)) + *s++ = *ptr++; + else + ptr ++; + + *s = '\0'; + s = buf; + + attrs = ptr; + while (*ptr && *ptr != '>') + ptr ++; + + if (*ptr == '>') + ptr ++; + + if (strcasecmp(buf, "BR") == 0 || + strcasecmp(buf, "HR") == 0) + { + width = 0; + needspace = 0; + } + else if (strcasecmp(buf, "TABLE") == 0 && start > table) + break; + else if (strcasecmp(buf, "CENTER") == 0 || + strcasecmp(buf, "P") == 0 || + strcasecmp(buf, "H1") == 0 || + strcasecmp(buf, "H2") == 0 || + strcasecmp(buf, "H3") == 0 || + strcasecmp(buf, "H4") == 0 || + strcasecmp(buf, "H5") == 0 || + strcasecmp(buf, "H6") == 0 || + strcasecmp(buf, "UL") == 0 || + strcasecmp(buf, "OL") == 0 || + strcasecmp(buf, "DL") == 0 || + strcasecmp(buf, "LI") == 0 || + strcasecmp(buf, "DD") == 0 || + strcasecmp(buf, "DT") == 0 || + strcasecmp(buf, "PRE") == 0) + { + width = 0; + needspace = 0; + + if (tolower(buf[0]) == 'h' && isdigit(buf[1])) + { + font = FL_HELVETICA_BOLD; + fsize = (uchar)(textsize_ + '7' - buf[1]); + } + else if (strcasecmp(buf, "DT") == 0) + { + font = (uchar)(textfont_ | FL_ITALIC); + fsize = textsize_; + } + else if (strcasecmp(buf, "PRE") == 0) + { + font = FL_COURIER; + fsize = textsize_; + pre = 1; + } + else if (strcasecmp(buf, "LI") == 0) + { + width += 4 * fsize; + font = textfont_; + fsize = textsize_; + } + else + { + font = textfont_; + fsize = textsize_; + } + + pushfont(font, fsize); + } + else if (strcasecmp(buf, "/CENTER") == 0 || + strcasecmp(buf, "/P") == 0 || + strcasecmp(buf, "/H1") == 0 || + strcasecmp(buf, "/H2") == 0 || + strcasecmp(buf, "/H3") == 0 || + strcasecmp(buf, "/H4") == 0 || + strcasecmp(buf, "/H5") == 0 || + strcasecmp(buf, "/H6") == 0 || + strcasecmp(buf, "/PRE") == 0 || + strcasecmp(buf, "/UL") == 0 || + strcasecmp(buf, "/OL") == 0 || + strcasecmp(buf, "/DL") == 0) + { + width = 0; + needspace = 0; + + popfont(font, fsize); + } + else if (strcasecmp(buf, "TR") == 0 || strcasecmp(buf, "/TR") == 0 || + strcasecmp(buf, "/TABLE") == 0) + { +// printf("%s column = %d, colspan = %d, num_columns = %d\n", +// buf, column, colspan, num_columns); + + if (column >= 0) + { + // This is a hack to support COLSPAN... + max_width /= colspan; + + while (colspan > 0) + { + if (max_width > columns[column]) + columns[column] = max_width; + + column ++; + colspan --; + } + } + + if (strcasecmp(buf, "/TABLE") == 0) + break; + + needspace = 0; + column = -1; + width = 0; + max_width = 0; + incell = 0; + } + else if (strcasecmp(buf, "TD") == 0 || + strcasecmp(buf, "TH") == 0) + { +// printf("BEFORE column = %d, colspan = %d, num_columns = %d\n", +// column, colspan, num_columns); + + if (column >= 0) + { + // This is a hack to support COLSPAN... + max_width /= colspan; + + while (colspan > 0) + { + if (max_width > columns[column]) + columns[column] = max_width; + + column ++; + colspan --; + } + } + else + column ++; + + if (get_attr(attrs, "COLSPAN", attr, sizeof(attr)) != NULL) + colspan = atoi(attr); + else + colspan = 1; + +// printf("AFTER column = %d, colspan = %d, num_columns = %d\n", +// column, colspan, num_columns); + + if ((column + colspan) >= num_columns) + num_columns = column + colspan; + + needspace = 0; + width = 0; + incell = 1; + + if (strcasecmp(buf, "TH") == 0) + font = (uchar)(textfont_ | FL_BOLD); + else + font = textfont_; + + fsize = textsize_; + + pushfont(font, fsize); + + if (get_attr(attrs, "WIDTH", attr, sizeof(attr)) != NULL) + max_width = get_length(attr); + else + max_width = 0; + +// printf("max_width = %d\n", max_width); + } + else if (strcasecmp(buf, "/TD") == 0 || + strcasecmp(buf, "/TH") == 0) + { + incell = 0; + popfont(font, fsize); + } + else if (strcasecmp(buf, "B") == 0 || + strcasecmp(buf, "STRONG") == 0) + pushfont(font |= FL_BOLD, fsize); + else if (strcasecmp(buf, "I") == 0 || + strcasecmp(buf, "EM") == 0) + pushfont(font |= FL_ITALIC, fsize); + else if (strcasecmp(buf, "CODE") == 0 || + strcasecmp(buf, "TT") == 0) + pushfont(font = FL_COURIER, fsize); + else if (strcasecmp(buf, "KBD") == 0) + pushfont(font = FL_COURIER_BOLD, fsize); + else if (strcasecmp(buf, "VAR") == 0) + pushfont(font = FL_COURIER_ITALIC, fsize); + else if (strcasecmp(buf, "/B") == 0 || + strcasecmp(buf, "/STRONG") == 0 || + strcasecmp(buf, "/I") == 0 || + strcasecmp(buf, "/EM") == 0 || + strcasecmp(buf, "/CODE") == 0 || + strcasecmp(buf, "/TT") == 0 || + strcasecmp(buf, "/KBD") == 0 || + strcasecmp(buf, "/VAR") == 0) + popfont(font, fsize); + else if (strcasecmp(buf, "IMG") == 0 && incell) + { + Fl_Shared_Image *img = 0; + int iwidth, iheight; + + + get_attr(attrs, "WIDTH", wattr, sizeof(wattr)); + get_attr(attrs, "HEIGHT", hattr, sizeof(hattr)); + iwidth = get_length(wattr); + iheight = get_length(hattr); + + if (get_attr(attrs, "SRC", attr, sizeof(attr))) { + img = get_image(attr, iwidth, iheight); + iwidth = img->w(); + iheight = img->h(); + } + + if (iwidth > minwidths[column]) + minwidths[column] = iwidth; + + width += iwidth; + if (needspace) + width += (int)fl_width(' '); + + if (width > max_width) + max_width = width; + + needspace = 0; + } + } + else if (*ptr == '\n' && pre) + { + width = 0; + needspace = 0; + ptr ++; + } + else if (isspace(*ptr)) + { + needspace = 1; + + ptr ++; + } + else if (*ptr == '&' && s < (buf + sizeof(buf) - 1)) + { + ptr ++; + + int qch = quote_char(ptr); + + if (qch < 0) + *s++ = '&'; + else { + *s++ = qch; + ptr = strchr(ptr, ';') + 1; + } + } + else + { + if (s < (buf + sizeof(buf) - 1)) + *s++ = *ptr++; + else + ptr ++; + } + } + + // Now that we have scanned the entire table, adjust the table and + // cell widths to fit on the screen... + if (get_attr(table + 6, "WIDTH", attr, sizeof(attr))) + *table_width = get_length(attr); + else + *table_width = 0; + +#ifdef DEBUG + printf("num_columns = %d, table_width = %d\n", num_columns, *table_width); +#endif // DEBUG + + if (num_columns == 0) + return; + + // Add up the widths... + for (column = 0, width = 0; column < num_columns; column ++) + width += columns[column]; + +#ifdef DEBUG + printf("width = %d, w() = %d\n", width, w()); + for (column = 0; column < num_columns; column ++) + printf(" columns[%d] = %d, minwidths[%d] = %d\n", column, columns[column], + column, minwidths[column]); +#endif // DEBUG + + // Adjust the width if needed... + int scale_width = *table_width; + + if (scale_width == 0) { + if (width > (hsize_ - 24)) scale_width = hsize_ - 24; + else scale_width = width; + } + + if (width < scale_width) { +#ifdef DEBUG + printf("Scaling table up to %d from %d...\n", scale_width, width); +#endif // DEBUG + + *table_width = 0; + + scale_width = (scale_width - width) / num_columns; + +#ifdef DEBUG + printf("adjusted scale_width = %d\n", scale_width); +#endif // DEBUG + + for (column = 0; column < num_columns; column ++) { + columns[column] += scale_width; + + (*table_width) += columns[column]; + } + } + else if (width > scale_width) { +#ifdef DEBUG + printf("Scaling table down to %d from %d...\n", scale_width, width); +#endif // DEBUG + + for (column = 0; column < num_columns; column ++) { + width -= minwidths[column]; + scale_width -= minwidths[column]; + } + +#ifdef DEBUG + printf("adjusted width = %d, scale_width = %d\n", width, scale_width); +#endif // DEBUG + + if (width > 0) { + for (column = 0; column < num_columns; column ++) { + columns[column] -= minwidths[column]; + columns[column] = scale_width * columns[column] / width; + columns[column] += minwidths[column]; + } + } + + *table_width = 0; + for (column = 0; column < num_columns; column ++) { + (*table_width) += columns[column]; + } + } + else if (*table_width == 0) + *table_width = width; + +#ifdef DEBUG + printf("FINAL table_width = %d\n", *table_width); + for (column = 0; column < num_columns; column ++) + printf(" columns[%d] = %d\n", column, columns[column]); +#endif // DEBUG +} + + +// +// 'Fl_Help_View::get_align()' - Get an alignment attribute. +// + +int // O - Alignment +Fl_Help_View::get_align(const char *p, // I - Pointer to start of attrs + int a) // I - Default alignment +{ + char buf[255]; // Alignment value + + + if (get_attr(p, "ALIGN", buf, sizeof(buf)) == NULL) + return (a); + + if (strcasecmp(buf, "CENTER") == 0) + return (CENTER); + else if (strcasecmp(buf, "RIGHT") == 0) + return (RIGHT); + else + return (LEFT); +} + + +// +// 'Fl_Help_View::get_attr()' - Get an attribute value from the string. +// + +const char * // O - Pointer to buf or NULL +Fl_Help_View::get_attr(const char *p, // I - Pointer to start of attributes + const char *n, // I - Name of attribute + char *buf, // O - Buffer for attribute value + int bufsize) // I - Size of buffer +{ + char name[255], // Name from string + *ptr, // Pointer into name or value + quote; // Quote + + + buf[0] = '\0'; + + while (*p && *p != '>') + { + while (isspace(*p)) + p ++; + + if (*p == '>' || !*p) + return (NULL); + + for (ptr = name; *p && !isspace(*p) && *p != '=' && *p != '>';) + if (ptr < (name + sizeof(name) - 1)) + *ptr++ = *p++; + else + p ++; + + *ptr = '\0'; + + if (isspace(*p) || !*p || *p == '>') + buf[0] = '\0'; + else + { + if (*p == '=') + p ++; + + for (ptr = buf; *p && !isspace(*p) && *p != '>';) + if (*p == '\'' || *p == '\"') + { + quote = *p++; + + while (*p && *p != quote) + if ((ptr - buf + 1) < bufsize) + *ptr++ = *p++; + else + p ++; + + if (*p == quote) + p ++; + } + else if ((ptr - buf + 1) < bufsize) + *ptr++ = *p++; + else + p ++; + + *ptr = '\0'; + } + + if (strcasecmp(n, name) == 0) + return (buf); + else + buf[0] = '\0'; + + if (*p == '>') + return (NULL); + } + + return (NULL); +} + + +// +// 'Fl_Help_View::get_color()' - Get an alignment attribute. +// + +Fl_Color // O - Color value +Fl_Help_View::get_color(const char *n, // I - Color name + Fl_Color c) // I - Default color value +{ + int i; // Looping var + int rgb, r, g, b; // RGB values + static const struct { // Color name table + const char *name; + int r, g, b; + } colors[] = { + { "black", 0x00, 0x00, 0x00 }, + { "red", 0xff, 0x00, 0x00 }, + { "green", 0x00, 0x80, 0x00 }, + { "yellow", 0xff, 0xff, 0x00 }, + { "blue", 0x00, 0x00, 0xff }, + { "magenta", 0xff, 0x00, 0xff }, + { "fuchsia", 0xff, 0x00, 0xff }, + { "cyan", 0x00, 0xff, 0xff }, + { "aqua", 0x00, 0xff, 0xff }, + { "white", 0xff, 0xff, 0xff }, + { "gray", 0x80, 0x80, 0x80 }, + { "grey", 0x80, 0x80, 0x80 }, + { "lime", 0x00, 0xff, 0x00 }, + { "maroon", 0x80, 0x00, 0x00 }, + { "navy", 0x00, 0x00, 0x80 }, + { "olive", 0x80, 0x80, 0x00 }, + { "purple", 0x80, 0x00, 0x80 }, + { "silver", 0xc0, 0xc0, 0xc0 }, + { "teal", 0x00, 0x80, 0x80 } + }; + + + if (!n || !n[0]) return c; + + if (n[0] == '#') { + // Do hex color lookup + rgb = strtol(n + 1, NULL, 16); + + if (strlen(n) > 4) { + r = rgb >> 16; + g = (rgb >> 8) & 255; + b = rgb & 255; + } else { + r = (rgb >> 8) * 17; + g = ((rgb >> 4) & 15) * 17; + b = (rgb & 15) * 17; + } + return (fl_rgb_color((uchar)r, (uchar)g, (uchar)b)); + } else { + for (i = 0; i < (int)(sizeof(colors) / sizeof(colors[0])); i ++) + if (!strcasecmp(n, colors[i].name)) { + return fl_rgb_color(colors[i].r, colors[i].g, colors[i].b); + } + return c; + } +} + + +// +// 'Fl_Help_View::get_image()' - Get an inline image. +// + +Fl_Shared_Image * +Fl_Help_View::get_image(const char *name, int W, int H) { + const char *localname; // Local filename + char dir[1024]; // Current directory + char temp[1024], // Temporary filename + *tempptr; // Pointer into temporary name + Fl_Shared_Image *ip; // Image pointer... + + // See if the image can be found... + if (strchr(directory_, ':') != NULL && strchr(name, ':') == NULL) { + if (name[0] == '/') { + strlcpy(temp, directory_, sizeof(temp)); + + if ((tempptr = strrchr(strchr(directory_, ':') + 3, '/')) != NULL) { + strlcpy(tempptr, name, sizeof(temp) - (tempptr - temp)); + } else { + strlcat(temp, name, sizeof(temp)); + } + } else { + snprintf(temp, sizeof(temp), "%s/%s", directory_, name); + } + + if (link_) localname = (*link_)(this, temp); + else localname = temp; + } else if (name[0] != '/' && strchr(name, ':') == NULL) { + if (directory_[0]) snprintf(temp, sizeof(temp), "%s/%s", directory_, name); + else { + getcwd(dir, sizeof(dir)); + snprintf(temp, sizeof(temp), "file:%s/%s", dir, name); + } + + if (link_) localname = (*link_)(this, temp); + else localname = temp; + } else if (link_) localname = (*link_)(this, name); + else localname = name; + + if (!localname) return 0; + + if (strncmp(localname, "file:", 5) == 0) localname += 5; + + if ((ip = Fl_Shared_Image::get(localname, W, H)) == NULL) + ip = (Fl_Shared_Image *)&broken_image; + + return ip; +} + + +// +// 'Fl_Help_View::get_length()' - Get a length value, either absolute or %. +// + +int +Fl_Help_View::get_length(const char *l) { // I - Value + int val; // Integer value + + if (!l[0]) return 0; + + val = atoi(l); + if (l[strlen(l) - 1] == '%') { + if (val > 100) val = 100; + else if (val < 0) val = 0; + + val = val * (hsize_ - 24) / 100; + } + + return val; +} + + +// +// 'Fl_Help_View::handle()' - Handle events in the widget. +// + +int // O - 1 if we handled it, 0 otherwise +Fl_Help_View::handle(int event) // I - Event to handle +{ + int i; // Looping var + int xx, yy; // Adjusted mouse position + Fl_Help_Link *linkp; // Current link + char target[32]; // Current target + + + switch (event) + { + case FL_PUSH : + if (Fl_Group::handle(event)) + return (1); + + case FL_MOVE : + xx = Fl::event_x() - x() + leftline_; + yy = Fl::event_y() - y() + topline_; + break; + + case FL_LEAVE : + fl_cursor(FL_CURSOR_DEFAULT); + + default : + return (Fl_Group::handle(event)); + } + + // Handle mouse clicks on links... + for (i = nlinks_, linkp = links_; i > 0; i --, linkp ++) + if (xx >= linkp->x && xx < linkp->w && + yy >= linkp->y && yy < linkp->h) + break; + + if (!i) + { + fl_cursor(FL_CURSOR_DEFAULT); + return (1); + } + + // Change the cursor for FL_MOTION events, and go to the link for + // clicks... + if (event == FL_MOVE) + fl_cursor(FL_CURSOR_HAND); + else + { + fl_cursor(FL_CURSOR_DEFAULT); + + strlcpy(target, linkp->name, sizeof(target)); + + set_changed(); + + if (strcmp(linkp->filename, filename_) != 0 && linkp->filename[0]) + { + char dir[1024]; // Current directory + char temp[1024], // Temporary filename + *tempptr; // Pointer into temporary filename + + + if (strchr(directory_, ':') != NULL && + strchr(linkp->filename, ':') == NULL) + { + if (linkp->filename[0] == '/') + { + strlcpy(temp, directory_, sizeof(temp)); + if ((tempptr = strrchr(strchr(directory_, ':') + 3, '/')) != NULL) + strlcpy(tempptr, linkp->filename, sizeof(temp)); + else + strlcat(temp, linkp->filename, sizeof(temp)); + } + else + snprintf(temp, sizeof(temp), "%s/%s", directory_, linkp->filename); + } + else if (linkp->filename[0] != '/' && strchr(linkp->filename, ':') == NULL) + { + if (directory_[0]) + snprintf(temp, sizeof(temp), "%s/%s", directory_, linkp->filename); + else + { + getcwd(dir, sizeof(dir)); + snprintf(temp, sizeof(temp), "file:%s/%s", dir, linkp->filename); + } + } + else + strlcpy(temp, linkp->filename, sizeof(temp)); + + if (linkp->name[0]) + snprintf(temp + strlen(temp), sizeof(temp) - strlen(temp), "#%s", + linkp->name); + + load(temp); + } + else if (target[0]) + topline(target); + else + topline(0); + + leftline(0); + } + + return (1); +} + + +// +// 'Fl_Help_View::Fl_Help_View()' - Build a Fl_Help_View widget. +// + +Fl_Help_View::Fl_Help_View(int xx, // I - Left position + int yy, // I - Top position + int ww, // I - Width in pixels + int hh, // I - Height in pixels + const char *l) + : Fl_Group(xx, yy, ww, hh, l), + scrollbar_(xx + ww - 17, yy, 17, hh - 17), + hscrollbar_(xx, yy + hh - 17, ww - 17, 17) +{ + color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR); + + title_[0] = '\0'; + defcolor_ = FL_FOREGROUND_COLOR; + bgcolor_ = FL_BACKGROUND_COLOR; + textcolor_ = FL_FOREGROUND_COLOR; + linkcolor_ = FL_SELECTION_COLOR; + textfont_ = FL_TIMES; + textsize_ = 12; + value_ = NULL; + + ablocks_ = 0; + nblocks_ = 0; + blocks_ = (Fl_Help_Block *)0; + + nfonts_ = 0; + + link_ = (Fl_Help_Func *)0; + + alinks_ = 0; + nlinks_ = 0; + links_ = (Fl_Help_Link *)0; + + atargets_ = 0; + ntargets_ = 0; + targets_ = (Fl_Help_Target *)0; + + directory_[0] = '\0'; + filename_[0] = '\0'; + + topline_ = 0; + leftline_ = 0; + size_ = 0; + hsize_ = 0; + + scrollbar_.value(0, hh, 0, 1); + scrollbar_.step(8.0); + scrollbar_.show(); + scrollbar_.callback(scrollbar_callback); + + hscrollbar_.value(0, ww, 0, 1); + hscrollbar_.step(8.0); + hscrollbar_.show(); + hscrollbar_.callback(hscrollbar_callback); + hscrollbar_.type(FL_HORIZONTAL); + end(); + + resize(xx, yy, ww, hh); +} + + +// +// 'Fl_Help_View::~Fl_Help_View()' - Destroy a Fl_Help_View widget. +// + +Fl_Help_View::~Fl_Help_View() +{ + if (nblocks_) + free(blocks_); + if (nlinks_) + free(links_); + if (ntargets_) + free(targets_); + if (value_) + free((void *)value_); +} + + +// +// 'Fl_Help_View::load()' - Load the specified file. +// + +int // O - 0 on success, -1 on error +Fl_Help_View::load(const char *f)// I - Filename to load (may also have target) +{ + FILE *fp; // File to read from + long len; // Length of file + char *target; // Target in file + char *slash; // Directory separator + const char *localname; // Local filename + char error[1024]; // Error buffer + char newname[1024]; // New filename buffer + + + strlcpy(newname, f, sizeof(newname)); + if ((target = strrchr(newname, '#')) != NULL) + *target++ = '\0'; + + if (link_) + localname = (*link_)(this, newname); + else + localname = filename_; + + if (!localname) + return (0); + + strlcpy(filename_, newname, sizeof(filename_)); + strlcpy(directory_, newname, sizeof(directory_)); + + // Note: We do not support Windows backslashes, since they are illegal + // in URLs... + if ((slash = strrchr(directory_, '/')) == NULL) + directory_[0] = '\0'; + else if (slash > directory_ && slash[-1] != '/') + *slash = '\0'; + + if (value_ != NULL) + { + free((void *)value_); + value_ = NULL; + } + + if (strncmp(localname, "ftp:", 4) == 0 || + strncmp(localname, "http:", 5) == 0 || + strncmp(localname, "https:", 6) == 0 || + strncmp(localname, "ipp:", 4) == 0 || + strncmp(localname, "mailto:", 7) == 0 || + strncmp(localname, "news:", 5) == 0) + { + // Remote link wasn't resolved... + snprintf(error, sizeof(error), + "<HTML><HEAD><TITLE>Error</TITLE></HEAD>" + "<BODY><H1>Error</H1>" + "<P>Unable to follow the link \"%s\" - " + "no handler exists for this URI scheme.</P></BODY>", + localname); + value_ = strdup(error); + } + else + { + if (strncmp(localname, "file:", 5) == 0) + localname += 5; // Adjust for local filename... + + if ((fp = fopen(localname, "rb")) != NULL) + { + fseek(fp, 0, SEEK_END); + len = ftell(fp); + rewind(fp); + + value_ = (const char *)calloc(len + 1, 1); + fread((void *)value_, 1, len, fp); + fclose(fp); + } + else + { + snprintf(error, sizeof(error), + "<HTML><HEAD><TITLE>Error</TITLE></HEAD>" + "<BODY><H1>Error</H1>" + "<P>Unable to follow the link \"%s\" - " + "%s.</P></BODY>", + localname, strerror(errno)); + value_ = strdup(error); + } + } + + format(); + + if (target) + topline(target); + else + topline(0); + + return (0); +} + + +// +// 'Fl_Help_View::resize()' - Resize the help widget. +// + +void +Fl_Help_View::resize(int xx, // I - New left position + int yy, // I - New top position + int ww, // I - New width + int hh) // I - New height +{ + Fl_Boxtype b = box() ? box() : FL_DOWN_BOX; + // Box to draw... + + + Fl_Widget::resize(xx, yy, ww, hh); + + scrollbar_.resize(x() + w() - 17 - Fl::box_dw(b) + Fl::box_dx(b), y() + Fl::box_dy(b), + 17, h() - 17 - Fl::box_dh(b)); + hscrollbar_.resize(x() + Fl::box_dx(b), y() + h() - 17 - Fl::box_dh(b) + Fl::box_dy(b), + w() - 17 - Fl::box_dw(b), 17); + + format(); +} + + +// +// 'Fl_Help_View::topline()' - Set the top line to the named target. +// + +void +Fl_Help_View::topline(const char *n) // I - Target name +{ + Fl_Help_Target key, // Target name key + *target; // Pointer to matching target + + + if (ntargets_ == 0) + return; + + strlcpy(key.name, n, sizeof(key.name)); + + target = (Fl_Help_Target *)bsearch(&key, targets_, ntargets_, sizeof(Fl_Help_Target), + (compare_func_t)compare_targets); + + if (target != NULL) + topline(target->y); +} + + +// +// 'Fl_Help_View::topline()' - Set the top line by number. +// + +void +Fl_Help_View::topline(int t) // I - Top line number +{ + if (!value_) + return; + + if (size_ < (h() - 24) || t < 0) + t = 0; + else if (t > size_) + t = size_; + + topline_ = t; + + scrollbar_.value(topline_, h() - 24, 0, size_); + + do_callback(); + + redraw(); +} + + +// +// 'Fl_Help_View::leftline()' - Set the left position. +// + +void +Fl_Help_View::leftline(int l) // I - Left position +{ + if (!value_) + return; + + if (hsize_ < (w() - 24) || l < 0) + l = 0; + else if (l > hsize_) + l = hsize_; + + leftline_ = l; + + hscrollbar_.value(leftline_, w() - 24, 0, hsize_); + + redraw(); +} + + +// +// 'Fl_Help_View::value()' - Set the help text directly. +// + +void +Fl_Help_View::value(const char *v) // I - Text to view +{ + if (!v) + return; + + if (value_ != NULL) + free((void *)value_); + + value_ = strdup(v); + + format(); + + set_changed(); + topline(0); + leftline(0); +} + + +// +// 'quote_char()' - Return the character code associated with a quoted char. +// + +static int // O - Code or -1 on error +quote_char(const char *p) { // I - Quoted string + int i; // Looping var + static struct { + const char *name; + int namelen; + int code; + } *nameptr, // Pointer into name array + names[] = { // Quoting names + { "Aacute;", 7, 193 }, + { "aacute;", 7, 225 }, + { "Acirc;", 6, 194 }, + { "acirc;", 6, 226 }, + { "acute;", 6, 180 }, + { "AElig;", 6, 198 }, + { "aelig;", 6, 230 }, + { "Agrave;", 7, 192 }, + { "agrave;", 7, 224 }, + { "amp;", 4, '&' }, + { "Aring;", 6, 197 }, + { "aring;", 6, 229 }, + { "Atilde;", 7, 195 }, + { "atilde;", 7, 227 }, + { "Auml;", 5, 196 }, + { "auml;", 5, 228 }, + { "brvbar;", 7, 166 }, + { "Ccedil;", 7, 199 }, + { "ccedil;", 7, 231 }, + { "cedil;", 6, 184 }, + { "cent;", 5, 162 }, + { "copy;", 5, 169 }, + { "curren;", 7, 164 }, + { "deg;", 4, 176 }, + { "divide;", 7, 247 }, + { "Eacute;", 7, 201 }, + { "eacute;", 7, 233 }, + { "Ecirc;", 6, 202 }, + { "ecirc;", 6, 234 }, + { "Egrave;", 7, 200 }, + { "egrave;", 7, 232 }, + { "ETH;", 4, 208 }, + { "eth;", 4, 240 }, + { "Euml;", 5, 203 }, + { "euml;", 5, 235 }, + { "frac12;", 7, 189 }, + { "frac14;", 7, 188 }, + { "frac34;", 7, 190 }, + { "gt;", 3, '>' }, + { "Iacute;", 7, 205 }, + { "iacute;", 7, 237 }, + { "Icirc;", 6, 206 }, + { "icirc;", 6, 238 }, + { "iexcl;", 6, 161 }, + { "Igrave;", 7, 204 }, + { "igrave;", 7, 236 }, + { "iquest;", 7, 191 }, + { "Iuml;", 5, 207 }, + { "iuml;", 5, 239 }, + { "laquo;", 6, 171 }, + { "lt;", 3, '<' }, + { "macr;", 5, 175 }, + { "micro;", 6, 181 }, + { "middot;", 7, 183 }, + { "nbsp;", 5, ' ' }, + { "not;", 4, 172 }, + { "Ntilde;", 7, 209 }, + { "ntilde;", 7, 241 }, + { "Oacute;", 7, 211 }, + { "oacute;", 7, 243 }, + { "Ocirc;", 6, 212 }, + { "ocirc;", 6, 244 }, + { "Ograve;", 7, 210 }, + { "ograve;", 7, 242 }, + { "ordf;", 5, 170 }, + { "ordm;", 5, 186 }, + { "Oslash;", 7, 216 }, + { "oslash;", 7, 248 }, + { "Otilde;", 7, 213 }, + { "otilde;", 7, 245 }, + { "Ouml;", 5, 214 }, + { "ouml;", 5, 246 }, + { "para;", 5, 182 }, + { "plusmn;", 7, 177 }, + { "pound;", 6, 163 }, + { "quot;", 5, '\"' }, + { "raquo;", 6, 187 }, + { "reg;", 4, 174 }, + { "sect;", 5, 167 }, + { "shy;", 4, 173 }, + { "sup1;", 5, 185 }, + { "sup2;", 5, 178 }, + { "sup3;", 5, 179 }, + { "szlig;", 6, 223 }, + { "THORN;", 6, 222 }, + { "thorn;", 6, 254 }, + { "times;", 6, 215 }, + { "Uacute;", 7, 218 }, + { "uacute;", 7, 250 }, + { "Ucirc;", 6, 219 }, + { "ucirc;", 6, 251 }, + { "Ugrave;", 7, 217 }, + { "ugrave;", 7, 249 }, + { "uml;", 4, 168 }, + { "Uuml;", 5, 220 }, + { "uuml;", 5, 252 }, + { "Yacute;", 7, 221 }, + { "yacute;", 7, 253 }, + { "yen;", 4, 165 }, + { "yuml;", 5, 255 } + }; + + if (!strchr(p, ';')) return -1; + if (*p == '#') { + if (*(p+1) == 'x' || *(p+1) == 'X') return strtol(p+2, NULL, 16); + else return atoi(p+1); + } + for (i = (int)(sizeof(names) / sizeof(names[0])), nameptr = names; i > 0; i --, nameptr ++) + if (strncmp(p, nameptr->name, nameptr->namelen) == 0) + return nameptr->code; + + return -1; +} + + +// +// 'scrollbar_callback()' - A callback for the scrollbar. +// + +static void +scrollbar_callback(Fl_Widget *s, void *) +{ + ((Fl_Help_View *)(s->parent()))->topline(int(((Fl_Scrollbar*)s)->value())); +} + + +// +// 'hscrollbar_callback()' - A callback for the horizontal scrollbar. +// + +static void +hscrollbar_callback(Fl_Widget *s, void *) +{ + ((Fl_Help_View *)(s->parent()))->leftline(int(((Fl_Scrollbar*)s)->value())); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Image.cxx b/Utilities/FLTK/src/Fl_Image.cxx new file mode 100644 index 0000000000..329a71288a --- /dev/null +++ b/Utilities/FLTK/src/Fl_Image.cxx @@ -0,0 +1,439 @@ +// +// "$Id$" +// +// Image drawing code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/fl_draw.H> +#include <FL/x.H> +#include <FL/Fl_Widget.H> +#include <FL/Fl_Menu_Item.H> +#include <FL/Fl_Image.H> +#include "flstring.h" + +#ifdef WIN32 +void fl_release_dc(HWND, HDC); // from Fl_win32.cxx +#endif + +void fl_restore_clip(); // from fl_rect.cxx + +// +// Base image class... +// + +Fl_Image::~Fl_Image() { +} + +void Fl_Image::uncache() { +} + +void Fl_Image::draw(int XP, int YP, int, int, int, int) { + draw_empty(XP, YP); +} + +void Fl_Image::draw_empty(int X, int Y) { + if (w() > 0 && h() > 0) { + fl_color(FL_FOREGROUND_COLOR); + fl_rect(X, Y, w(), h()); + fl_line(X, Y, X + w() - 1, Y + h() - 1); + fl_line(X, Y + h() - 1, X + w() - 1, Y); + } +} + +Fl_Image *Fl_Image::copy(int W, int H) { + return new Fl_Image(W, H, d()); +} + +void Fl_Image::color_average(Fl_Color, float) { +} + +void Fl_Image::desaturate() { +} + +void Fl_Image::label(Fl_Widget* widget) { + widget->image(this); +} + +void Fl_Image::label(Fl_Menu_Item* m) { + Fl::set_labeltype(_FL_IMAGE_LABEL, labeltype, measure); + m->label(_FL_IMAGE_LABEL, (const char*)this); +} + +void +Fl_Image::labeltype(const Fl_Label *lo, // I - Label + int lx, // I - X position + int ly, // I - Y position + int lw, // I - Width of label + int lh, // I - Height of label + Fl_Align la) { // I - Alignment + Fl_Image *img; // Image pointer + int cx, cy; // Image position + + img = (Fl_Image *)(lo->value); + + if (la & FL_ALIGN_LEFT) cx = 0; + else if (la & FL_ALIGN_RIGHT) cx = img->w() - lw; + else cx = (img->w() - lw) / 2; + + if (la & FL_ALIGN_TOP) cy = 0; + else if (la & FL_ALIGN_BOTTOM) cy = img->h() - lh; + else cy = (img->h() - lh) / 2; + + fl_color((Fl_Color)lo->color); + + img->draw(lx, ly, lw, lh, cx, cy); +} + +void +Fl_Image::measure(const Fl_Label *lo, // I - Label + int &lw, // O - Width of image + int &lh) { // O - Height of image + Fl_Image *img; // Image pointer + + img = (Fl_Image *)(lo->value); + + lw = img->w(); + lh = img->h(); +} + + +// +// RGB image class... +// + +Fl_RGB_Image::~Fl_RGB_Image() { + uncache(); + if (alloc_array) delete[] (uchar *)array; +} + +void Fl_RGB_Image::uncache() { +#ifdef __APPLE_QUARTZ__ + if (id) + CGImageRelease((CGImageRef)id); +#else + if (id) { + fl_delete_offscreen((Fl_Offscreen)id); + id = 0; + } + + if (mask) { + fl_delete_bitmask((Fl_Bitmask)mask); + mask = 0; + } +#endif +} + +Fl_Image *Fl_RGB_Image::copy(int W, int H) { + Fl_RGB_Image *new_image; // New RGB image + uchar *new_array; // New array for image data + + // Optimize the simple copy where the width and height are the same, + // or when we are copying an empty image... + if ((W == w() && H == h()) || + !w() || !h() || !d() || !array) { + if (array) { + // Make a copy of the image data and return a new Fl_RGB_Image... + new_array = new uchar[w() * h() * d()]; + memcpy(new_array, array, w() * h() * d()); + + new_image = new Fl_RGB_Image(new_array, w(), h(), d(), ld()); + new_image->alloc_array = 1; + + return new_image; + } else return new Fl_RGB_Image(array, w(), h(), d(), ld()); + } + if (W <= 0 || H <= 0) return 0; + + // OK, need to resize the image data; allocate memory and + uchar *new_ptr; // Pointer into new array + const uchar *old_ptr; // Pointer into old array + int c, // Channel number + sy, // Source coordinate + dx, dy, // Destination coordinates + xerr, yerr, // X & Y errors + xmod, ymod, // X & Y moduli + xstep, ystep; // X & Y step increments + + + // Figure out Bresenheim step/modulus values... + xmod = w() % W; + xstep = (w() / W) * d(); + ymod = h() % H; + ystep = h() / H; + + // Allocate memory for the new image... + new_array = new uchar [W * H * d()]; + new_image = new Fl_RGB_Image(new_array, W, H, d()); + new_image->alloc_array = 1; + + // Scale the image using a nearest-neighbor algorithm... + for (dy = H, sy = 0, yerr = H, new_ptr = new_array; dy > 0; dy --) { + for (dx = W, xerr = W, old_ptr = array + sy * (w() * d() + ld()); + dx > 0; + dx --) { + for (c = 0; c < d(); c ++) *new_ptr++ = old_ptr[c]; + + old_ptr += xstep; + xerr -= xmod; + + if (xerr <= 0) { + xerr += W; + old_ptr += d(); + } + } + + sy += ystep; + yerr -= ymod; + if (yerr <= 0) { + yerr += H; + sy ++; + } + } + + return new_image; +} + +void Fl_RGB_Image::color_average(Fl_Color c, float i) { + // Don't average an empty image... + if (!w() || !h() || !d() || !array) return; + + // Delete any existing pixmap/mask objects... + uncache(); + + // Allocate memory as needed... + uchar *new_array, + *new_ptr; + + if (!alloc_array) new_array = new uchar[h() * w() * d()]; + else new_array = (uchar *)array; + + // Get the color to blend with... + uchar r, g, b; + unsigned ia, ir, ig, ib; + + Fl::get_color(c, r, g, b); + if (i < 0.0f) i = 0.0f; + else if (i > 1.0f) i = 1.0f; + + ia = (unsigned)(256 * i); + ir = r * (256 - ia); + ig = g * (256 - ia); + ib = b * (256 - ia); + + // Update the image data to do the blend... + const uchar *old_ptr; + int x, y; + + if (d() < 3) { + ig = (r * 31 + g * 61 + b * 8) / 100 * (256 - ia); + + for (new_ptr = new_array, old_ptr = array, y = 0; y < h(); y ++, old_ptr += ld()) + for (x = 0; x < w(); x ++) { + *new_ptr++ = (*old_ptr++ * ia + ig) >> 8; + if (d() > 1) *new_ptr++ = *old_ptr++; + } + } else { + for (new_ptr = new_array, old_ptr = array, y = 0; y < h(); y ++, old_ptr += ld()) + for (x = 0; x < w(); x ++) { + *new_ptr++ = (*old_ptr++ * ia + ir) >> 8; + *new_ptr++ = (*old_ptr++ * ia + ig) >> 8; + *new_ptr++ = (*old_ptr++ * ia + ib) >> 8; + if (d() > 3) *new_ptr++ = *old_ptr++; + } + } + + // Set the new pointers/values as needed... + if (!alloc_array) { + array = new_array; + alloc_array = 1; + + ld(0); + } +} + +void Fl_RGB_Image::desaturate() { + // Don't desaturate an empty image... + if (!w() || !h() || !d() || !array) return; + + // Can only desaturate color images... + if (d() < 3) return; + + // Delete any existing pixmap/mask objects... + uncache(); + + // Allocate memory for a grayscale image... + uchar *new_array, + *new_ptr; + int new_d; + + new_d = d() - 2; + new_array = new uchar[h() * w() * new_d]; + + // Copy the image data, converting to grayscale... + const uchar *old_ptr; + int x, y; + + for (new_ptr = new_array, old_ptr = array, y = 0; y < h(); y ++, old_ptr += ld()) + for (x = 0; x < w(); x ++, old_ptr += d()) { + *new_ptr++ = (uchar)((31 * old_ptr[0] + 61 * old_ptr[1] + 8 * old_ptr[2]) / 100); + if (d() > 3) *new_ptr++ = old_ptr[3]; + } + + // Free the old array as needed, and then set the new pointers/values... + if (alloc_array) delete[] (uchar *)array; + + array = new_array; + alloc_array = 1; + + ld(0); + d(new_d); +} + +void Fl_RGB_Image::draw(int XP, int YP, int WP, int HP, int cx, int cy) { + // Don't draw an empty image... + if (!d() || !array) { + draw_empty(XP, YP); + return; + } + + // account for current clip region (faster on Irix): + int X,Y,W,H; fl_clip_box(XP,YP,WP,HP,X,Y,W,H); + cx += X-XP; cy += Y-YP; + // clip the box down to the size of image, quit if empty: + if (cx < 0) {W += cx; X -= cx; cx = 0;} + if (cx+W > w()) W = w()-cx; + if (W <= 0) return; + if (cy < 0) {H += cy; Y -= cy; cy = 0;} + if (cy+H > h()) H = h()-cy; + if (H <= 0) return; + if (!id) { +#ifdef __APPLE_QUARTZ__ + CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); + CGDataProviderRef src = CGDataProviderCreateWithData( 0L, array, w()*h()*d(), 0L); + id = CGImageCreate( w(), h(), 8, d()*8, ld()?ld():w()*d(), + lut, (d()&1)?kCGImageAlphaNone:kCGImageAlphaLast, + src, 0L, false, kCGRenderingIntentDefault); + CGColorSpaceRelease(lut); + CGDataProviderRelease(src); +#else + id = fl_create_offscreen(w(), h()); + fl_begin_offscreen((Fl_Offscreen)id); + fl_draw_image(array, 0, 0, w(), h(), d(), ld()); + fl_end_offscreen(); + if (d() == 2 || d() == 4) { + mask = fl_create_alphamask(w(), h(), d(), ld(), array); + } +#endif + } +#ifdef WIN32 + if (mask) { + HDC new_gc = CreateCompatibleDC(fl_gc); + int save = SaveDC(new_gc); + SelectObject(new_gc, (void*)mask); + BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCAND); + SelectObject(new_gc, (void*)id); + BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCPAINT); + RestoreDC(new_gc,save); + DeleteDC(new_gc); + } else { + fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id, cx, cy); + } +#elif defined(__APPLE_QD__) + if (mask) { + Rect src, dst; + // MRS: STR #114 says we should be using cx, cy, W, and H... +// src.left = 0; src.right = w(); +// src.top = 0; src.bottom = h(); +// dst.left = X; dst.right = X+w(); +// dst.top = Y; dst.bottom = Y+h(); + src.left = cx; src.right = cx+W; + src.top = cy; src.bottom = cy+H; + dst.left = X; dst.right = X+W; + dst.top = Y; dst.bottom = Y+H; + RGBColor rgb; + rgb.red = 0xffff; rgb.green = 0xffff; rgb.blue = 0xffff; + RGBBackColor(&rgb); + rgb.red = 0x0000; rgb.green = 0x0000; rgb.blue = 0x0000; + RGBForeColor(&rgb); + +# if 0 + // MRS: This *should* work, but doesn't on my system (iBook); change to + // "#if 1" and restore the corresponding code in Fl_Bitmap.cxx + // to test the real alpha channel support. + CopyDeepMask(GetPortBitMapForCopyBits((GrafPtr)id), + GetPortBitMapForCopyBits((GrafPtr)mask), + GetPortBitMapForCopyBits(GetWindowPort(fl_window)), + &src, &src, &dst, blend, NULL); +# else // Fallback to screen-door transparency... + CopyMask(GetPortBitMapForCopyBits((GrafPtr)id), + GetPortBitMapForCopyBits((GrafPtr)mask), + GetPortBitMapForCopyBits(GetWindowPort(fl_window)), + &src, &src, &dst); +# endif // 0 + } else { + fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id, cx, cy); + } +#elif defined(__APPLE_QUARTZ__) + if (id && fl_gc) { + CGRect rect = { X, Y, W, H }; + Fl_X::q_begin_image(rect, cx, cy, w(), h()); + CGContextDrawImage(fl_gc, rect, (CGImageRef)id); + Fl_X::q_end_image(); + } +#else + if (mask) { + // I can't figure out how to combine a mask with existing region, + // so cut the image down to a clipped rectangle: + int nx, ny; fl_clip_box(X,Y,W,H,nx,ny,W,H); + cx += nx-X; X = nx; + cy += ny-Y; Y = ny; + // make X use the bitmap as a mask: + XSetClipMask(fl_display, fl_gc, mask); + int ox = X-cx; if (ox < 0) ox += w(); + int oy = Y-cy; if (oy < 0) oy += h(); + XSetClipOrigin(fl_display, fl_gc, X-cx, Y-cy); + } + fl_copy_offscreen(X, Y, W, H, id, cx, cy); + if (mask) { + // put the old clip region back + XSetClipOrigin(fl_display, fl_gc, 0, 0); + fl_restore_clip(); + } +#endif +} + +void Fl_RGB_Image::label(Fl_Widget* widget) { + widget->image(this); +} + +void Fl_RGB_Image::label(Fl_Menu_Item* m) { + Fl::set_labeltype(_FL_IMAGE_LABEL, labeltype, measure); + m->label(_FL_IMAGE_LABEL, (const char*)this); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Input.cxx b/Utilities/FLTK/src/Fl_Input.cxx new file mode 100644 index 0000000000..ef12c7487f --- /dev/null +++ b/Utilities/FLTK/src/Fl_Input.cxx @@ -0,0 +1,467 @@ +// +// "$Id$" +// +// Input widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// This is the "user interface", it decodes user actions into what to +// do to the text. See also Fl_Input_.cxx, where the text is actually +// manipulated (and some ui, in particular the mouse, is done...). +// In theory you can replace this code with another subclass to change +// the keybindings. + +#include <stdio.h> +#include <stdlib.h> +#include <FL/Fl.H> +#include <FL/Fl_Input.H> +#include <FL/fl_draw.H> +#include <FL/fl_ask.H> +#include "flstring.h" + +#ifdef HAVE_LOCALE_H +# include <locale.h> +#endif + + +void Fl_Input::draw() { + if (input_type() == FL_HIDDEN_INPUT) return; + Fl_Boxtype b = box(); + if (damage() & FL_DAMAGE_ALL) draw_box(b, color()); + Fl_Input_::drawtext(x()+Fl::box_dx(b), y()+Fl::box_dy(b), + w()-Fl::box_dw(b), h()-Fl::box_dh(b)); +} + +// kludge so shift causes selection to extend: +int Fl_Input::shift_position(int p) { + return position(p, Fl::event_state(FL_SHIFT) ? mark() : p); +} +int Fl_Input::shift_up_down_position(int p) { + return up_down_position(p, Fl::event_state(FL_SHIFT)); +} + +// If you define this symbol as zero you will get the peculiar fltk +// behavior where moving off the end of an input field will move the +// cursor into the next field: +// define it as 1 to prevent cursor movement from going to next field: +#define NORMAL_INPUT_MOVE 0 + +#define ctrl(x) ((x)^0x40) + +// List of characters that are legal in a floating point input field. +// This text string is created at run-time to take the current locale +// into account (for example, continental Europe uses a comma instead +// of a decimal point). For back compatibility reasons, we always +// allow the decimal point. +#ifdef HAVE_LOCALECONV +static const char *standard_fp_chars = ".eE+-"; +static const char *legal_fp_chars = 0L; +#else +static const char *legal_fp_chars = ".eE+-"; +#endif + +int Fl_Input::handle_key() { + + char ascii = Fl::event_text()[0]; + + int repeat_num=1; + + int del; + if (Fl::compose(del)) { + + // Insert characters into numeric fields after checking for legality: + if (input_type() == FL_FLOAT_INPUT || input_type() == FL_INT_INPUT) { + Fl::compose_reset(); // ignore any foreign letters... + + // initialize the list of legal characters inside a floating point number +#ifdef HAVE_LOCALECONV + if (!legal_fp_chars) { + int len = strlen(standard_fp_chars); + struct lconv *lc = localeconv(); + if (lc) { + if (lc->decimal_point) len += strlen(lc->decimal_point); + if (lc->mon_decimal_point) len += strlen(lc->mon_decimal_point); + if (lc->positive_sign) len += strlen(lc->positive_sign); + if (lc->negative_sign) len += strlen(lc->negative_sign); + } + // the following line is not a true memory leak because the array is only + // allocated once if required, and automatically freed when the program quits + char *chars = (char*)malloc(len+1); + legal_fp_chars = chars; + strcpy(chars, standard_fp_chars); + if (lc) { + if (lc->decimal_point) strcat(chars, lc->decimal_point); + if (lc->mon_decimal_point) strcat(chars, lc->mon_decimal_point); + if (lc->positive_sign) strcat(chars, lc->positive_sign); + if (lc->negative_sign) strcat(chars, lc->negative_sign); + } + } +#endif // HAVE_LOCALECONV + + // This is complex to allow "0xff12" hex to be typed: + if (!position() && (ascii == '+' || ascii == '-') || + (ascii >= '0' && ascii <= '9') || + (position()==1 && index(0)=='0' && (ascii=='x' || ascii == 'X')) || + (position()>1 && index(0)=='0' && (index(1)=='x'||index(1)=='X') + && (ascii>='A'&& ascii<='F' || ascii>='a'&& ascii<='f')) || + input_type()==FL_FLOAT_INPUT && ascii && strchr(legal_fp_chars, ascii)) { + if (readonly()) fl_beep(); + else replace(position(), mark(), &ascii, 1); + } + return 1; + } + + if (del || Fl::event_length()) { + if (readonly()) fl_beep(); + else replace(position(), del ? position()-del : mark(), + Fl::event_text(), Fl::event_length()); + } + return 1; + } + + switch (Fl::event_key()) { + case FL_Insert: + if (Fl::event_state() & FL_CTRL) ascii = ctrl('C'); + else if (Fl::event_state() & FL_SHIFT) ascii = ctrl('V'); + break; + case FL_Delete: + if (Fl::event_state() & FL_SHIFT) ascii = ctrl('X'); + else ascii = ctrl('D'); + break; + case FL_Left: + ascii = ctrl('B'); break; + case FL_Right: + ascii = ctrl('F'); break; + case FL_Page_Up: + fl_font(textfont(),textsize()); //ensure current font is set to ours + repeat_num=h()/fl_height(); // number of lines to scroll + if (!repeat_num) repeat_num=1; + case FL_Up: + ascii = ctrl('P'); break; + case FL_Page_Down: + fl_font(textfont(),textsize()); + repeat_num=h()/fl_height(); + if (!repeat_num) repeat_num=1; + case FL_Down: + ascii = ctrl('N'); break; + case FL_Home: + if (Fl::event_state() & FL_CTRL) { + shift_position(0); + return 1; + } + ascii = ctrl('A'); + break; + case FL_End: + if (Fl::event_state() & FL_CTRL) { + shift_position(size()); + return 1; + } + ascii = ctrl('E'); break; + + case FL_BackSpace: + ascii = ctrl('H'); break; + case FL_Enter: + case FL_KP_Enter: + if (when() & FL_WHEN_ENTER_KEY) { + position(size(), 0); + maybe_do_callback(); + return 1; + } else if (input_type() == FL_MULTILINE_INPUT && !readonly()) + return replace(position(), mark(), "\n", 1); + else + return 0; // reserved for shortcuts + case FL_Tab: + if (Fl::event_state(FL_CTRL|FL_SHIFT) || input_type()!=FL_MULTILINE_INPUT || readonly()) return 0; + return replace(position(), mark(), &ascii, 1); +#ifdef __APPLE__ + case 'c' : + case 'v' : + case 'x' : + case 'z' : +// printf("'%c' (0x%02x) pressed with%s%s%s%s\n", ascii, ascii, +// Fl::event_state(FL_SHIFT) ? " FL_SHIFT" : "", +// Fl::event_state(FL_CTRL) ? " FL_CTRL" : "", +// Fl::event_state(FL_ALT) ? " FL_ALT" : "", +// Fl::event_state(FL_META) ? " FL_META" : ""); + if (Fl::event_state(FL_META)) ascii -= 0x60; +// printf("using '%c' (0x%02x)...\n", ascii, ascii); + break; +#endif // __APPLE__ + } + + int i; + switch (ascii) { + case ctrl('A'): + return shift_position(line_start(position())) + NORMAL_INPUT_MOVE; + case ctrl('B'): + return shift_position(position()-1) + NORMAL_INPUT_MOVE; + case ctrl('C'): // copy + return copy(1); + case ctrl('D'): + case ctrl('?'): + if (readonly()) { + fl_beep(); + return 1; + } + if (mark() != position()) return cut(); + else return cut(1); + case ctrl('E'): + return shift_position(line_end(position())) + NORMAL_INPUT_MOVE; + case ctrl('F'): + return shift_position(position()+1) + NORMAL_INPUT_MOVE; + case ctrl('H'): + if (readonly()) { + fl_beep(); + return 1; + } + if (mark() != position()) cut(); + else cut(-1); + return 1; + case ctrl('K'): + if (readonly()) { + fl_beep(); + return 1; + } + if (position()>=size()) return 0; + i = line_end(position()); + if (i == position() && i < size()) i++; + cut(position(), i); + return copy_cuts(); + case ctrl('N'): + i = position(); + if (line_end(i) >= size()) return NORMAL_INPUT_MOVE; + while (repeat_num--) { + i = line_end(i); + if (i >= size()) break; + i++; + } + shift_up_down_position(i); + return 1; + case ctrl('P'): + i = position(); + if (!line_start(i)) return NORMAL_INPUT_MOVE; + while(repeat_num--) { + i = line_start(i); + if (!i) break; + i--; + } + shift_up_down_position(line_start(i)); + return 1; + case ctrl('U'): + if (readonly()) { + fl_beep(); + return 1; + } + return cut(0, size()); + case ctrl('V'): + case ctrl('Y'): + if (readonly()) { + fl_beep(); + return 1; + } + Fl::paste(*this, 1); + return 1; + case ctrl('X'): + case ctrl('W'): + if (readonly()) { + fl_beep(); + return 1; + } + copy(1); + return cut(); + case ctrl('Z'): + case ctrl('_'): + if (readonly()) { + fl_beep(); + return 1; + } + return undo(); + case ctrl('I'): + case ctrl('J'): + case ctrl('L'): + case ctrl('M'): + if (readonly()) { + fl_beep(); + return 1; + } + // insert a few selected control characters literally: + if (input_type() != FL_FLOAT_INPUT && input_type() != FL_INT_INPUT) + return replace(position(), mark(), &ascii, 1); + } + + return 0; +} + +int Fl_Input::handle(int event) { + static int dnd_save_position, dnd_save_mark, drag_start = -1, newpos; + static Fl_Widget *dnd_save_focus; + switch (event) { + case FL_FOCUS: + switch (Fl::event_key()) { + case FL_Right: + position(0); + break; + case FL_Left: + position(size()); + break; + case FL_Down: + up_down_position(0); + break; + case FL_Up: + up_down_position(line_start(size())); + break; + case FL_Tab: + case 0xfe20: // XK_ISO_Left_Tab + position(size(),0); + break; + default: + position(position(),mark());// turns off the saved up/down arrow position + break; + } + break; + + case FL_KEYBOARD: + if (Fl::event_key() == FL_Tab && mark() != position()) { + // Set the current cursor position to the end of the selection... + if (mark() > position()) + position(mark()); + else + position(position()); + return (1); + } else return handle_key(); + + case FL_PUSH: + if (Fl::dnd_text_ops()) { + int oldpos = position(), oldmark = mark(); + Fl_Boxtype b = box(); + Fl_Input_::handle_mouse( + x()+Fl::box_dx(b), y()+Fl::box_dy(b), + w()-Fl::box_dw(b), h()-Fl::box_dh(b), 0); + newpos = position(); + position( oldpos, oldmark ); + if (Fl::focus()==this && !Fl::event_state(FL_SHIFT) && input_type()!=FL_SECRET_INPUT && + (newpos >= mark() && newpos < position() || + newpos >= position() && newpos < mark())) { + // user clicked in the selection, may be trying to drag + drag_start = newpos; + return 1; + } + drag_start = -1; + } + + if (Fl::focus() != this) { + Fl::focus(this); + handle(FL_FOCUS); + } + break; + + case FL_DRAG: + if (Fl::dnd_text_ops()) { + if (drag_start >= 0) { + if (Fl::event_is_click()) return 1; // debounce the mouse + // save the position because sometimes we don't get DND_ENTER: + dnd_save_position = position(); + dnd_save_mark = mark(); + // drag the data: + copy(0); Fl::dnd(); + return 1; + } + } + break; + + case FL_RELEASE: + if (Fl::event_button() == 2) { + Fl::event_is_click(0); // stop double click from picking a word + Fl::paste(*this, 0); + } else if (!Fl::event_is_click()) { + // copy drag-selected text to the clipboard. + copy(0); + } else if (Fl::event_is_click() && drag_start >= 0) { + // user clicked in the field and wants to reset the cursor position... + position(drag_start, drag_start); + drag_start = -1; + } else if (Fl::event_clicks()) { + // user double or triple clicked to select word or whole text + copy(0); + } + // For output widgets, do the callback so the app knows the user + // did something with the mouse... + if (readonly()) do_callback(); + return 1; + + case FL_DND_ENTER: + Fl::belowmouse(this); // send the leave events first + dnd_save_position = position(); + dnd_save_mark = mark(); + dnd_save_focus = Fl::focus(); + if (dnd_save_focus != this) { + Fl::focus(this); + handle(FL_FOCUS); + } + // fall through: + case FL_DND_DRAG: + //int p = mouse_position(X, Y, W, H); +#if DND_OUT_XXXX + if (Fl::focus()==this && (p>=dnd_save_position && p<=dnd_save_mark || + p>=dnd_save_mark && p<=dnd_save_position)) { + position(dnd_save_position, dnd_save_mark); + return 0; + } +#endif + { + Fl_Boxtype b = box(); + Fl_Input_::handle_mouse( + x()+Fl::box_dx(b), y()+Fl::box_dy(b), + w()-Fl::box_dw(b), h()-Fl::box_dh(b), 0); + } + return 1; + + case FL_DND_LEAVE: + position(dnd_save_position, dnd_save_mark); +#if DND_OUT_XXXX + if (!focused()) +#endif + if (dnd_save_focus != this) { + Fl::focus(dnd_save_focus); + handle(FL_UNFOCUS); + } + return 1; + + case FL_DND_RELEASE: + take_focus(); + return 1; + + } + Fl_Boxtype b = box(); + return Fl_Input_::handletext(event, + x()+Fl::box_dx(b), y()+Fl::box_dy(b), + w()-Fl::box_dw(b), h()-Fl::box_dh(b)); +} + +Fl_Input::Fl_Input(int X, int Y, int W, int H, const char *l) +: Fl_Input_(X, Y, W, H, l) { +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Input_.cxx b/Utilities/FLTK/src/Fl_Input_.cxx new file mode 100644 index 0000000000..142870bec7 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Input_.cxx @@ -0,0 +1,882 @@ +// +// "$Id$" +// +// Common input widget routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// This is the base class for Fl_Input. You can use it directly +// if you are one of those people who like to define their own +// set of editing keys. It may also be useful for adding scrollbars +// to the input field. + +#include <FL/Fl.H> +#include <FL/Fl_Input_.H> +#include <FL/Fl_Window.H> +#include <FL/fl_draw.H> +#include <FL/fl_ask.H> +#include <math.h> +#include "flstring.h" +#include <stdlib.h> +#include <ctype.h> + +#define MAXBUF 1024 + +extern void fl_draw(const char*, int, float, float); + +//////////////////////////////////////////////////////////////// + +// Copy string p..e to the buffer, replacing characters with ^X and \nnn +// as necessary. Truncate if necessary so the resulting string and +// null terminator fits in a buffer of size n. Return new end pointer. +const char* Fl_Input_::expand(const char* p, char* buf) const { + char* o = buf; + char* e = buf+(MAXBUF-4); + const char* lastspace = p; + char* lastspace_out = o; + int width_to_lastspace = 0; + int word_count = 0; + int word_wrap; + + if (input_type()==FL_SECRET_INPUT) { + while (o<e && p < value_+size_) {*o++ = '*'; p++;} + } else while (o<e) { + if (wrap() && (p >= value_+size_ || isspace(*p & 255))) { + word_wrap = w() - Fl::box_dw(box()) - 2; + width_to_lastspace += (int)fl_width(lastspace_out, o-lastspace_out); + if (p > lastspace+1) { + if (word_count && width_to_lastspace > word_wrap) { + p = lastspace; o = lastspace_out; break; + } + word_count++; + } + lastspace = p; + lastspace_out = o; + } + + if (p >= value_+size_) break; + int c = *p++ & 255; + if (c < ' ' || c == 127) { + if (c=='\n' && input_type()==FL_MULTILINE_INPUT) {p--; break;} + if (c == '\t' && input_type()==FL_MULTILINE_INPUT) { + for (c = (o-buf)%8; c<8 && o<e; c++) *o++ = ' '; + } else { + *o++ = '^'; + *o++ = c ^ 0x40; + } + } else if (c == 0xA0) { // nbsp + *o++ = ' '; + } else { + *o++ = c; + } + } + *o = 0; + return p; +} + +// After filling in such a buffer, find the width to e +double Fl_Input_::expandpos( + const char* p, // real string + const char* e, // pointer into real string + const char* buf, // conversion of real string by expand() + int* returnn // return offset into buf here +) const { + int n = 0; + if (input_type()==FL_SECRET_INPUT) n = e-p; + else while (p<e) { + int c = *p++ & 255; + if (c < ' ' || c == 127) { + if (c == '\t' && input_type()==FL_MULTILINE_INPUT) n += 8-(n%8); + else n += 2; + } else if (c >= 128 && c < 0xA0) { + n += 4; + } else { + n++; + } + } + if (returnn) *returnn = n; + return fl_width(buf, n); +} + +//////////////////////////////////////////////////////////////// + +// minimal update: +// Characters from mu_p to end of widget are redrawn. +// If erase_cursor_only, small part at mu_p is redrawn. +// Right now minimal update just keeps unchanged characters from +// being erased, so they don't blink. + +void Fl_Input_::minimal_update(int p) { + if (damage() & FL_DAMAGE_ALL) return; // don't waste time if it won't be done + if (damage() & FL_DAMAGE_EXPOSE) { + if (p < mu_p) mu_p = p; + } else { + mu_p = p; + } + + damage(FL_DAMAGE_EXPOSE); + erase_cursor_only = 0; +} + +void Fl_Input_::minimal_update(int p, int q) { + if (q < p) p = q; + minimal_update(p); +} + +//////////////////////////////////////////////////////////////// + +static double up_down_pos; +static int was_up_down; + +void Fl_Input_::setfont() const { + fl_font(textfont(), textsize()); +} + +void Fl_Input_::drawtext(int X, int Y, int W, int H) { + int do_mu = !(damage()&FL_DAMAGE_ALL); + + if (Fl::focus()!=this && !size()) { + if (do_mu) { // we have to erase it if cursor was there + draw_box(box(), X-Fl::box_dx(box()), Y-Fl::box_dy(box()), + W+Fl::box_dw(box()), H+Fl::box_dh(box()), color()); + } + return; + } + + int selstart, selend; + if (Fl::focus()!=this && /*Fl::selection_owner()!=this &&*/ Fl::pushed()!=this) + selstart = selend = 0; + else if (position() <= mark()) { + selstart = position(); selend = mark(); + } else { + selend = position(); selstart = mark(); + } + + setfont(); + const char *p, *e; + char buf[MAXBUF]; + + // count how many lines and put the last one into the buffer: + // And figure out where the cursor is: + int height = fl_height(); + int lines; + int curx, cury; + for (p=value(), curx=cury=lines=0; ;) { + e = expand(p, buf); + if (position() >= p-value() && position() <= e-value()) { + curx = int(expandpos(p, value()+position(), buf, 0)+.5); + if (Fl::focus()==this && !was_up_down) up_down_pos = curx; + cury = lines*height; + int newscroll = xscroll_; + if (curx > newscroll+W-20) { + // figure out scrolling so there is space after the cursor: + newscroll = curx+20-W; + // figure out the furthest left we ever want to scroll: + int ex = int(expandpos(p, e, buf, 0))+2-W; + // use minimum of both amounts: + if (ex < newscroll) newscroll = ex; + } else if (curx < newscroll+20) { + newscroll = curx-20; + } + if (newscroll < 0) newscroll = 0; + if (newscroll != xscroll_) { + xscroll_ = newscroll; + mu_p = 0; erase_cursor_only = 0; + } + } + lines++; + if (e >= value_+size_) break; + p = e+1; + } + + // adjust the scrolling: + if (input_type()==FL_MULTILINE_INPUT) { + int newy = yscroll_; + if (cury < newy) newy = cury; + if (cury > newy+H-height) newy = cury-H+height; + if (newy < -1) newy = -1; + if (newy != yscroll_) {yscroll_ = newy; mu_p = 0; erase_cursor_only = 0;} + } else { + yscroll_ = -(H-height)/2; + } + + fl_clip(X, Y, W, H); + Fl_Color tc = active_r() ? textcolor() : fl_inactive(textcolor()); + + p = value(); + // visit each line and draw it: + int desc = height-fl_descent(); + float xpos = X - xscroll_ + 1; + int ypos = -yscroll_; + for (; ypos < H;) { + + // re-expand line unless it is the last one calculated above: + if (lines>1) e = expand(p, buf); + + if (ypos <= -height) goto CONTINUE; // clipped off top + + if (do_mu) { // for minimal update: + const char* pp = value()+mu_p; // pointer to where minimal update starts + if (e < pp) goto CONTINUE2; // this line is before the changes + if (readonly()) erase_cursor_only = 0; // this isn't the most efficient way + if (erase_cursor_only && p > pp) goto CONTINUE2; // this line is after + // calculate area to erase: + float r = X+W; + float xx; + if (p >= pp) { + xx = X; + if (erase_cursor_only) r = xpos+2; + else if (readonly()) xx -= 3; + } else { + xx = xpos+expandpos(p, pp, buf, 0); + if (erase_cursor_only) r = xx+2; + else if (readonly()) xx -= 3; + } + // clip to and erase it: + fl_push_clip((int)xx-1-height/8, Y+ypos, (int)(r-xx+2+height/4), height); + draw_box(box(), X-Fl::box_dx(box()), Y-Fl::box_dy(box()), + W+Fl::box_dw(box()), H+Fl::box_dh(box()), color()); + // it now draws entire line over it + // this should not draw letters to left of erased area, but + // that is nyi. + } + + // Draw selection area if required: + if (selstart < selend && selstart <= e-value() && selend > p-value()) { + const char* pp = value()+selstart; + float x1 = xpos; + int offset1 = 0; + if (pp > p) { + fl_color(tc); + x1 += expandpos(p, pp, buf, &offset1); + fl_draw(buf, offset1, xpos, (float)(Y+ypos+desc)); + } + pp = value()+selend; + float x2 = X+W; + int offset2; + if (pp <= e) x2 = xpos+expandpos(p, pp, buf, &offset2); + else offset2 = strlen(buf); + fl_color(selection_color()); + fl_rectf((int)(x1+0.5), Y+ypos, (int)(x2-x1+0.5), height); + fl_color(fl_contrast(textcolor(), selection_color())); + fl_draw(buf+offset1, offset2-offset1, x1, (float)(Y+ypos+desc)); + if (pp < e) { + fl_color(tc); + fl_draw(buf+offset2, strlen(buf+offset2), x2, (float)(Y+ypos+desc)); + } + } else { + // draw unselected text + fl_color(tc); + fl_draw(buf, strlen(buf), xpos, (float)(Y+ypos+desc)); + } + + if (do_mu) fl_pop_clip(); + + CONTINUE2: + // draw the cursor: + if (Fl::focus() == this && selstart == selend && + position() >= p-value() && position() <= e-value()) { + fl_color(cursor_color()); + if (readonly()) { + fl_line((int)(xpos+curx-2.5f), Y+ypos+height-1, + (int)(xpos+curx+0.5f), Y+ypos+height-4, + (int)(xpos+curx+3.5f), Y+ypos+height-1); + } else { + fl_rectf((int)(xpos+curx+0.5), Y+ypos, 2, height); + } + } + + CONTINUE: + ypos += height; + if (e >= value_+size_) break; + if (*e == '\n' || *e == ' ') e++; + p = e; + } + + // for minimal update, erase all lines below last one if necessary: + if (input_type()==FL_MULTILINE_INPUT && do_mu && ypos<H + && (!erase_cursor_only || p <= value()+mu_p)) { + if (ypos < 0) ypos = 0; + fl_push_clip(X, Y+ypos, W, H-ypos); + draw_box(box(), X-Fl::box_dx(box()), Y-Fl::box_dy(box()), + W+Fl::box_dw(box()), H+Fl::box_dh(box()), color()); + fl_pop_clip(); + } + + fl_pop_clip(); +} + +static int isword(char c) { + return (c&128 || isalnum(c) || strchr("#%&-/@\\_~", c)); +} + +int Fl_Input_::word_end(int i) const { + if (input_type() == FL_SECRET_INPUT) return size(); + //while (i < size() && !isword(index(i))) i++; + while (i < size() && isword(index(i))) i++; + return i; +} + +int Fl_Input_::word_start(int i) const { + if (input_type() == FL_SECRET_INPUT) return 0; +// if (i >= size() || !isword(index(i))) +// while (i > 0 && !isword(index(i-1))) i--; + while (i > 0 && isword(index(i-1))) i--; + return i; +} + +int Fl_Input_::line_end(int i) const { + if (input_type() != FL_MULTILINE_INPUT) return size(); + + if (wrap()) { + // go to the start of the paragraph: + int j = i; + while (j > 0 && index(j-1) != '\n') j--; + // now measure lines until we get past i, end of that line is real eol: + setfont(); + for (const char* p=value()+j; ;) { + char buf[MAXBUF]; + p = expand(p, buf); + if (p-value() >= i) return p-value(); + p++; + } + } else { + while (i < size() && index(i) != '\n') i++; + return i; + } +} + +int Fl_Input_::line_start(int i) const { + if (input_type() != FL_MULTILINE_INPUT) return 0; + int j = i; + while (j > 0 && index(j-1) != '\n') j--; + if (wrap()) { + // now measure lines until we get past i, start of that line is real eol: + setfont(); + for (const char* p=value()+j; ;) { + char buf[MAXBUF]; + const char* e = expand(p, buf); + if (e-value() >= i) return p-value(); + p = e+1; + } + } else return j; +} + +void Fl_Input_::handle_mouse(int X, int Y, int /*W*/, int /*H*/, int drag) { + was_up_down = 0; + if (!size()) return; + setfont(); + + const char *p, *e; + char buf[MAXBUF]; + + int theline = (input_type()==FL_MULTILINE_INPUT) ? + (Fl::event_y()-Y+yscroll_)/fl_height() : 0; + + int newpos = 0; + for (p=value();; ) { + e = expand(p, buf); + theline--; if (theline < 0) break; + if (e >= value_+size_) break; + p = e+1; + } + const char *l, *r, *t; double f0 = Fl::event_x()-X+xscroll_; + for (l = p, r = e; l<r; ) { + double f; + t = l+(r-l+1)/2; + f = X-xscroll_+expandpos(p, t, buf, 0); + if (f <= Fl::event_x()) {l = t; f0 = Fl::event_x()-f;} + else r = t-1; + } + if (l < e) { // see if closer to character on right: + double f1 = X-xscroll_+expandpos(p, l+1, buf, 0)-Fl::event_x(); + if (f1 < f0) l = l+1; + } + newpos = l-value(); + + int newmark = drag ? mark() : newpos; + if (Fl::event_clicks()) { + if (newpos >= newmark) { + if (newpos == newmark) { + if (newpos < size()) newpos++; + else newmark--; + } + if (Fl::event_clicks() > 1) { + newpos = line_end(newpos); + newmark = line_start(newmark); + } else { + newpos = word_end(newpos); + newmark = word_start(newmark); + } + } else { + if (Fl::event_clicks() > 1) { + newpos = line_start(newpos); + newmark = line_end(newmark); + } else { + newpos = word_start(newpos); + newmark = word_end(newmark); + } + } + // if the multiple click does not increase the selection, revert + // to single-click behavior: + if (!drag && (mark() > position() ? + (newmark >= position() && newpos <= mark()) : + (newmark >= mark() && newpos <= position()))) { + Fl::event_clicks(0); + newmark = newpos = l-value(); + } + } + position(newpos, newmark); +} + +int Fl_Input_::position(int p, int m) { + was_up_down = 0; + if (p<0) p = 0; + if (p>size()) p = size(); + if (m<0) m = 0; + if (m>size()) m = size(); + if (p == position_ && m == mark_) return 0; + //if (Fl::selection_owner() == this) Fl::selection_owner(0); + if (p != m) { + if (p != position_) minimal_update(position_, p); + if (m != mark_) minimal_update(mark_, m); + } else { + // new position is a cursor + if (position_ == mark_) { + // old position was just a cursor + if (Fl::focus() == this && !(damage()&FL_DAMAGE_EXPOSE)) { + minimal_update(position_); erase_cursor_only = 1; + } + } else { // old position was a selection + minimal_update(position_, mark_); + } + } + position_ = p; + mark_ = m; + return 1; +} + +int Fl_Input_::up_down_position(int i, int keepmark) { + // unlike before, i must be at the start of the line already! + + setfont(); + char buf[MAXBUF]; + const char* p = value()+i; + const char* e = expand(p, buf); + const char *l, *r, *t; + for (l = p, r = e; l<r; ) { + t = l+(r-l+1)/2; + int f = (int)expandpos(p, t, buf, 0); + if (f <= up_down_pos) l = t; else r = t-1; + } + int j = l-value(); + j = position(j, keepmark ? mark_ : j); + was_up_down = 1; + return j; +} + +int Fl_Input_::copy(int clipboard) { + int b = position(); + int e = mark(); + if (b != e) { + if (b > e) {b = mark(); e = position();} + if (input_type() == FL_SECRET_INPUT) e = b; + Fl::copy(value()+b, e-b, clipboard); + return 1; + } + return 0; +} + +#define MAXFLOATSIZE 40 + +static char* undobuffer; +static int undobufferlength; +static Fl_Input_* undowidget; +static int undoat; // points after insertion +static int undocut; // number of characters deleted there +static int undoinsert; // number of characters inserted +static int yankcut; // length of valid contents of buffer, even if undocut=0 + +static void undobuffersize(int n) { + if (n > undobufferlength) { + if (undobuffer) { + do {undobufferlength *= 2;} while (undobufferlength < n); + undobuffer = (char*)realloc(undobuffer, undobufferlength); + } else { + undobufferlength = n+9; + undobuffer = (char*)malloc(undobufferlength); + } + } +} + +// all changes go through here, delete characters b-e and insert text: +int Fl_Input_::replace(int b, int e, const char* text, int ilen) { + + was_up_down = 0; + + if (b<0) b = 0; + if (e<0) e = 0; + if (b>size_) b = size_; + if (e>size_) e = size_; + if (e<b) {int t=b; b=e; e=t;} + if (text && !ilen) ilen = strlen(text); + if (e<=b && !ilen) return 0; // don't clobber undo for a null operation + if (size_+ilen-(e-b) > maximum_size_) { + ilen = maximum_size_-size_+(e-b); + if (ilen < 0) ilen = 0; + } + + put_in_buffer(size_+ilen); + + if (e>b) { + if (undowidget == this && b == undoat) { + undobuffersize(undocut+(e-b)); + memcpy(undobuffer+undocut, value_+b, e-b); + undocut += e-b; + } else if (undowidget == this && e == undoat && !undoinsert) { + undobuffersize(undocut+(e-b)); + memmove(undobuffer+(e-b), undobuffer, undocut); + memcpy(undobuffer, value_+b, e-b); + undocut += e-b; + } else if (undowidget == this && e == undoat && (e-b)<undoinsert) { + undoinsert -= e-b; + } else { + undobuffersize(e-b); + memcpy(undobuffer, value_+b, e-b); + undocut = e-b; + undoinsert = 0; + } + memmove(buffer+b, buffer+e, size_-e+1); + size_ -= e-b; + undowidget = this; + undoat = b; + if (input_type() == FL_SECRET_INPUT) yankcut = 0; else yankcut = undocut; + } + + if (ilen) { + if (undowidget == this && b == undoat) + undoinsert += ilen; + else { + undocut = 0; + undoinsert = ilen; + } + memmove(buffer+b+ilen, buffer+b, size_-b+1); + memcpy(buffer+b, text, ilen); + size_ += ilen; + } + undowidget = this; + undoat = b+ilen; + + // Insertions into the word at the end of the line will cause it to + // wrap to the next line, so we must indicate that the changes may start + // right after the whitespace before the current word. This will + // result in sub-optimal update when such wrapping does not happen + // but it is too hard to figure out for now... + if (wrap()) { + // if there is a space in the pasted text, the whole line may have rewrapped + int i; + for (i=0; i<ilen; i++) + if (text[i]==' ') break; + if (i==ilen) + while (b > 0 && !isspace(index(b) & 255) && index(b)!='\n') b--; + else + while (b > 0 && index(b)!='\n') b--; + } + + // make sure we redraw the old selection or cursor: + if (mark_ < b) b = mark_; + if (position_ < b) b = position_; + + minimal_update(b); + + mark_ = position_ = undoat; + + set_changed(); + if (when()&FL_WHEN_CHANGED) do_callback(); + return 1; +} + +int Fl_Input_::undo() { + was_up_down = 0; + if (undowidget != this || !undocut && !undoinsert) return 0; + + int ilen = undocut; + int xlen = undoinsert; + int b = undoat-xlen; + int b1 = b; + + put_in_buffer(size_+ilen); + + if (ilen) { + memmove(buffer+b+ilen, buffer+b, size_-b+1); + memcpy(buffer+b, undobuffer, ilen); + size_ += ilen; + b += ilen; + } + + if (xlen) { + undobuffersize(xlen); + memcpy(undobuffer, buffer+b, xlen); + memmove(buffer+b, buffer+b+xlen, size_-xlen-b+1); + size_ -= xlen; + } + + undocut = xlen; + if (xlen) yankcut = xlen; + undoinsert = ilen; + undoat = b; + mark_ = b /* -ilen */; + position_ = b; + + if (wrap()) + while (b1 > 0 && index(b1)!='\n') b1--; + minimal_update(b1); + set_changed(); + if (when()&FL_WHEN_CHANGED) do_callback(); + return 1; +} + +int Fl_Input_::copy_cuts() { + // put the yank buffer into the X clipboard + if (!yankcut || input_type()==FL_SECRET_INPUT) return 0; + Fl::copy(undobuffer, yankcut, 1); + return 1; +} + +void Fl_Input_::maybe_do_callback() { + if (changed() || (when()&FL_WHEN_NOT_CHANGED)) { + do_callback(); + } +} + +int Fl_Input_::handletext(int event, int X, int Y, int W, int H) { + switch (event) { + + case FL_ENTER: + if (active_r() && window()) window()->cursor(FL_CURSOR_INSERT); + return 1; + + case FL_LEAVE: + if (active_r() && window()) window()->cursor(FL_CURSOR_DEFAULT); + return 1; + + case FL_FOCUS: + if (mark_ == position_) { + minimal_update(size()+1); + } else //if (Fl::selection_owner() != this) + minimal_update(mark_, position_); + return 1; + + case FL_UNFOCUS: + if (mark_ == position_) { + if (!(damage()&FL_DAMAGE_EXPOSE)) {minimal_update(position_); erase_cursor_only = 1;} + } else //if (Fl::selection_owner() != this) + minimal_update(mark_, position_); + case FL_HIDE: + if (when() & FL_WHEN_RELEASE) maybe_do_callback(); + return 1; + + case FL_PUSH: + handle_mouse(X, Y, W, H, Fl::event_state(FL_SHIFT)); + + if (Fl::focus() != this) { + Fl::focus(this); + handle(FL_FOCUS); + } + return 1; + + case FL_DRAG: + handle_mouse(X, Y, W, H, 1); + return 1; + + case FL_RELEASE: + copy(0); + return 1; + + case FL_PASTE: { + // Don't allow pastes into readonly widgets... + if (readonly()) { + fl_beep(FL_BEEP_ERROR); + return 1; + } + + // See if we have anything to paste... + if (!Fl::event_text() || !Fl::event_length()) return 1; + + // strip trailing control characters and spaces before pasting: + const char* t = Fl::event_text(); + const char* e = t+Fl::event_length(); + if (input_type() != FL_MULTILINE_INPUT) while (e > t && isspace(*(e-1) & 255)) e--; + if (!t || e <= t) return 1; // Int/float stuff will crash without this test + if (input_type() == FL_INT_INPUT) { + while (isspace(*t & 255) && t < e) t ++; + const char *p = t; + if (*p == '+' || *p == '-') p ++; + if (strncmp(p, "0x", 2) == 0) { + p += 2; + while (isxdigit(*p & 255) && p < e) p ++; + } else { + while (isdigit(*p & 255) && p < e) p ++; + } + if (p < e) { + fl_beep(FL_BEEP_ERROR); + return 1; + } else return replace(0, size(), t, e - t); + } else if (input_type() == FL_FLOAT_INPUT) { + while (isspace(*t & 255) && t < e) t ++; + const char *p = t; + if (*p == '+' || *p == '-') p ++; + while (isdigit(*p & 255) && p < e) p ++; + if (*p == '.') { + p ++; + while (isdigit(*p & 255) && p < e) p ++; + if (*p == 'e' || *p == 'E') { + p ++; + if (*p == '+' || *p == '-') p ++; + while (isdigit(*p & 255) && p < e) p ++; + } + } + if (p < e) { + fl_beep(FL_BEEP_ERROR); + return 1; + } else return replace(0, size(), t, e - t); + } + return replace(position(), mark(), t, e-t);} + + default: + return 0; + } +} + +/*------------------------------*/ + +Fl_Input_::Fl_Input_(int X, int Y, int W, int H, const char* l) +: Fl_Widget(X, Y, W, H, l) { + box(FL_DOWN_BOX); + color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR); + align(FL_ALIGN_LEFT); + textsize_ = (uchar)FL_NORMAL_SIZE; + textfont_ = FL_HELVETICA; + textcolor_ = FL_FOREGROUND_COLOR; + cursor_color_ = FL_FOREGROUND_COLOR; // was FL_BLUE + mark_ = position_ = size_ = 0; + bufsize = 0; + buffer = 0; + value_ = ""; + xscroll_ = yscroll_ = 0; + maximum_size_ = 32767; +} + +void Fl_Input_::put_in_buffer(int len) { + if (value_ == buffer && bufsize > len) { + buffer[size_] = 0; + return; + } + if (!bufsize) { + if (len > size_) len += 9; // let a few characters insert before realloc + bufsize = len+1; + buffer = (char*)malloc(bufsize); + } else if (bufsize <= len) { + // we may need to move old value in case it points into buffer: + int moveit = (value_ >= buffer && value_ < buffer+bufsize); + // enlarge current buffer + if (len > size_) { + do {bufsize *= 2;} while (bufsize <= len); + } else { + bufsize = len+1; + } + // Note: the following code is equivalent to: + // + // if (moveit) value_ = value_ - buffer; + // char* nbuffer = (char*)realloc(buffer, bufsize); + // if (moveit) value_ = value_ + nbuffer; + // buffer = nbuffer; + // + // We just optimized the pointer arithmetic for value_... + // + char* nbuffer = (char*)realloc(buffer, bufsize); + if (moveit) value_ += (nbuffer-buffer); + buffer = nbuffer; + } + memmove(buffer, value_, size_); buffer[size_] = 0; + value_ = buffer; +} + +int Fl_Input_::static_value(const char* str, int len) { + clear_changed(); + if (undowidget == this) undowidget = 0; + if (str == value_ && len == size_) return 0; + if (len) { // non-empty new value: + if (xscroll_ || yscroll_) { + xscroll_ = yscroll_ = 0; + minimal_update(0); + } else { + int i = 0; + // find first different character: + if (value_) { + for (; i<size_ && i<len && str[i]==value_[i]; i++); + if (i==size_ && i==len) return 0; + } + minimal_update(i); + } + value_ = str; + size_ = len; + } else { // empty new value: + if (!size_) return 0; // both old and new are empty. + size_ = 0; + value_ = ""; + xscroll_ = yscroll_ = 0; + minimal_update(0); + } + position(0, readonly() ? 0 : size()); + return 1; +} + +int Fl_Input_::static_value(const char* str) { + return static_value(str, str ? strlen(str) : 0); +} + +int Fl_Input_::value(const char* str, int len) { + int r = static_value(str, len); + if (len) put_in_buffer(len); + return r; +} + +int Fl_Input_::value(const char* str) { + return value(str, str ? strlen(str) : 0); +} + +void Fl_Input_::resize(int X, int Y, int W, int H) { + if (W != w()) xscroll_ = 0; + if (H != h()) yscroll_ = 0; + Fl_Widget::resize(X, Y, W, H); +} + +Fl_Input_::~Fl_Input_() { + if (undowidget == this) undowidget = 0; + if (bufsize) free((void*)buffer); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_JPEG_Image.cxx b/Utilities/FLTK/src/Fl_JPEG_Image.cxx new file mode 100644 index 0000000000..8b0fb3c54a --- /dev/null +++ b/Utilities/FLTK/src/Fl_JPEG_Image.cxx @@ -0,0 +1,198 @@ +// +// "$Id$" +// +// Fl_JPEG_Image routines. +// +// Copyright 1997-2005 by Easy Software Products. +// Image support donated by Matthias Melcher, Copyright 2000. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +// Contents: +// +// Fl_JPEG_Image::Fl_JPEG_Image() - Load a JPEG image file. +// + +// +// Include necessary header files... +// + +#include <FL/Fl_JPEG_Image.H> +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <setjmp.h> + + +// Some releases of the Cygwin JPEG libraries don't have a correctly +// updated header file for the INT32 data type; the following define +// from Shane Hill seems to be a usable workaround... + +#if defined(WIN32) && defined(__CYGWIN__) +# define XMD_H +#endif // WIN32 && __CYGWIN__ + + +extern "C" +{ +#ifdef HAVE_LIBJPEG +# include <jpeglib.h> +#endif // HAVE_LIBJPEG +} + + +// +// Custom JPEG error handling structure... +// + +#ifdef HAVE_LIBJPEG +struct fl_jpeg_error_mgr { + jpeg_error_mgr pub_; // Destination manager... + jmp_buf errhand_; // Error handler +}; +#endif // HAVE_LIBJPEG + + +// +// Error handler for JPEG files... +// + +#ifdef HAVE_LIBJPEG +extern "C" { + static void + fl_jpeg_error_handler(j_common_ptr dinfo) { // I - Decompressor info + longjmp(((fl_jpeg_error_mgr *)(dinfo->err))->errhand_, 1); + return; + } + + static void + fl_jpeg_output_handler(j_common_ptr dinfo) { // I - Decompressor info + return; + } +} +#endif // HAVE_LIBJPEG + + +// +// 'Fl_JPEG_Image::Fl_JPEG_Image()' - Load a JPEG image file. +// + +Fl_JPEG_Image::Fl_JPEG_Image(const char *jpeg) // I - File to load + : Fl_RGB_Image(0,0,0) { +#ifdef HAVE_LIBJPEG + FILE *fp; // File pointer + jpeg_decompress_struct dinfo; // Decompressor info + fl_jpeg_error_mgr jerr; // Error handler info + JSAMPROW row; // Sample row pointer + + // the following variables are pointers allocating some private space that + // is not reset by 'setjmp()' + char* max_finish_decompress_err; // count errors and give up afer a while + char* max_destroy_decompress_err; // to avoid recusion and deadlock + + // Clear data... + alloc_array = 0; + array = (uchar *)0; + + // Open the image file... + if ((fp = fopen(jpeg, "rb")) == NULL) return; + + // Setup the decompressor info and read the header... + dinfo.err = jpeg_std_error((jpeg_error_mgr *)&jerr); + jerr.pub_.error_exit = fl_jpeg_error_handler; + jerr.pub_.output_message = fl_jpeg_output_handler; + + // Setup error loop variables + max_finish_decompress_err = (char*)malloc(1); // allocate space on the frame for error counters + max_destroy_decompress_err = (char*)malloc(1); // otherwise, the variables are reset on the longjmp + *max_finish_decompress_err=10; + *max_destroy_decompress_err=10; + + if (setjmp(jerr.errhand_)) + { + // JPEG error handling... + // if any of the cleanup routines hits another error, we would end up + // in a loop. So instead, we decrement max_err for some upper cleanup limit. + if ( ((*max_finish_decompress_err)-- > 0) && array) + jpeg_finish_decompress(&dinfo); + if ( (*max_destroy_decompress_err)-- > 0) + jpeg_destroy_decompress(&dinfo); + + fclose(fp); + + w(0); + h(0); + d(0); + + if (array) { + delete[] (uchar *)array; + array = 0; + alloc_array = 0; + } + + free(max_destroy_decompress_err); + free(max_finish_decompress_err); + + return; + } + + jpeg_create_decompress(&dinfo); + jpeg_stdio_src(&dinfo, fp); + jpeg_read_header(&dinfo, 1); + + dinfo.quantize_colors = (boolean)FALSE; + dinfo.out_color_space = JCS_RGB; + dinfo.out_color_components = 3; + dinfo.output_components = 3; + + jpeg_calc_output_dimensions(&dinfo); + + w(dinfo.output_width); + h(dinfo.output_height); + d(dinfo.output_components); + + array = new uchar[w() * h() * d()]; + alloc_array = 1; + + jpeg_start_decompress(&dinfo); + + while (dinfo.output_scanline < dinfo.output_height) { + row = (JSAMPROW)(array + + dinfo.output_scanline * dinfo.output_width * + dinfo.output_components); + jpeg_read_scanlines(&dinfo, &row, (JDIMENSION)1); + } + + jpeg_finish_decompress(&dinfo); + jpeg_destroy_decompress(&dinfo); + + free(max_destroy_decompress_err); + free(max_finish_decompress_err); + + fclose(fp); +#endif // HAVE_LIBJPEG +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Light_Button.cxx b/Utilities/FLTK/src/Fl_Light_Button.cxx new file mode 100644 index 0000000000..531064913e --- /dev/null +++ b/Utilities/FLTK/src/Fl_Light_Button.cxx @@ -0,0 +1,152 @@ +// +// "$Id$" +// +// Lighted button widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Subclass of Fl_Button where the "box" indicates whether it is +// pushed or not, and the "down box" is drawn small and square on +// the left to indicate the current state. + +// The default down_box of zero draws a rectangle designed to look +// just like Flame's buttons. + +#include <FL/Fl.H> +#include <FL/Fl_Light_Button.H> +#include <FL/fl_draw.H> + +void Fl_Light_Button::draw() { + if (box()) draw_box(this==Fl::pushed() ? fl_down(box()) : box(), color()); + Fl_Color col = value() ? (active_r() ? selection_color() : + fl_inactive(selection_color())) : color(); + int W; + int dx, dy; + + W = labelsize(); + dx = Fl::box_dx(box()) + 2; + dy = (h() - W) / 2; + // if (dy < 0) dy = 0; // neg. offset o.k. for vertical centering + + if (down_box()) { + // draw other down_box() styles: + switch (down_box()) { + case FL_DOWN_BOX : + case FL_UP_BOX : + case _FL_PLASTIC_DOWN_BOX : + case _FL_PLASTIC_UP_BOX : + // Check box... + draw_box(down_box(), x()+dx, y()+dy, W, W, FL_BACKGROUND2_COLOR); + if (value()) { + fl_color(col); + int tx = x() + dx + 3; + int tw = W - 6; + int d1 = tw/3; + int d2 = tw-d1; + int ty = y() + dy + (W+d2)/2-d1-2; + for (int n = 0; n < 3; n++, ty++) { + fl_line(tx, ty, tx+d1, ty+d1); + fl_line(tx+d1, ty+d1, tx+tw-1, ty+d1-d2+1); + } + } + break; + case _FL_ROUND_DOWN_BOX : + case _FL_ROUND_UP_BOX : + // Radio button... + draw_box(down_box(), x()+dx, y()+dy, W, W, FL_BACKGROUND2_COLOR); + if (value()) { + fl_color(col); + int tW = (W - Fl::box_dw(down_box())) / 2 + 1; + if ((W - tW) & 1) tW++; // Make sure difference is even to center + int tdx = dx + (W - tW) / 2; + int tdy = dy + (W - tW) / 2; + + switch (tW) { + // Larger circles draw fine... + default : + fl_pie(x() + tdx, y() + tdy, tW, tW, 0.0, 360.0); + break; + + // Small circles don't draw well on many systems... + case 6 : + fl_rectf(x() + tdx + 2, y() + tdy, tW - 4, tW); + fl_rectf(x() + tdx + 1, y() + tdy + 1, tW - 2, tW - 2); + fl_rectf(x() + tdx, y() + tdy + 2, tW, tW - 4); + break; + + case 5 : + case 4 : + case 3 : + fl_rectf(x() + tdx + 1, y() + tdy, tW - 2, tW); + fl_rectf(x() + tdx, y() + tdy + 1, tW, tW - 2); + break; + + case 2 : + case 1 : + fl_rectf(x() + tdx, y() + tdy, tW, tW); + break; + } + } + break; + default : + draw_box(down_box(), x()+dx, y()+dy, W, W, col); + break; + } + } else { + // if down_box() is zero, draw light button style: + int hh = h()-2*dy - 2; + int ww = W/2+1; + int xx = dx; + if (w()<ww+2*xx) xx = (w()-ww)/2; + if (Fl::scheme()) { + col = active_r() ? selection_color() : fl_inactive(selection_color()); + fl_color(value() ? col : fl_color_average(col, FL_BLACK, 0.5f)); + fl_pie(x()+xx, y()+dy+1, ww, hh, 0, 360); + } else { + draw_box(FL_THIN_DOWN_BOX, x()+xx, y()+dy+1, ww, hh, col); + } + dx = (ww + 2 * dx - W) / 2; + } + draw_label(x()+W+2*dx, y(), w()-W-2*dx, h()); + if (Fl::focus() == this) draw_focus(); +} + +int Fl_Light_Button::handle(int event) { + switch (event) { + case FL_RELEASE: + if (box()) redraw(); + default: + return Fl_Button::handle(event); + } +} + +Fl_Light_Button::Fl_Light_Button(int X, int Y, int W, int H, const char* l) +: Fl_Button(X, Y, W, H, l) { + type(FL_TOGGLE_BUTTON); + selection_color(FL_YELLOW); + align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Menu.cxx b/Utilities/FLTK/src/Fl_Menu.cxx new file mode 100644 index 0000000000..34f6b4b998 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Menu.cxx @@ -0,0 +1,853 @@ +// +// "$Id$" +// +// Menu code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Warning: this menu code is quite a mess! + +// This file contains code for implementing Fl_Menu_Item, and for +// methods for bringing up popup menu hierarchies without using the +// Fl_Menu_ widget. + +#include <FL/Fl.H> +#include <FL/Fl_Menu_Window.H> +#include <FL/Fl_Menu_.H> +#include <FL/fl_draw.H> +#include <stdio.h> + +#ifdef __APPLE__ +# include <Carbon/Carbon.h> +#endif + +int Fl_Menu_Item::size() const { + const Fl_Menu_Item* m = this; + int nest = 0; + for (;;) { + if (!m->text) { + if (!nest) return (m-this+1); + nest--; + } else if (m->flags & FL_SUBMENU) { + nest++; + } + m++; + } +} + +const Fl_Menu_Item* Fl_Menu_Item::next(int n) const { + if (n < 0) return 0; // this is so selected==-1 returns NULL + const Fl_Menu_Item* m = this; + int nest = 0; + if (!m->visible()) n++; + while (n>0) { + if (!m->text) { + if (!nest) return m; + nest--; + } else if (m->flags&FL_SUBMENU) { + nest++; + } + m++; + if (!nest && m->visible()) n--; + } + return m; +} + +// appearance of current menus are pulled from this parent widget: +static const Fl_Menu_* button; + +//////////////////////////////////////////////////////////////// + +// tiny window for title of menu: +class menutitle : public Fl_Menu_Window { + void draw(); +public: + const Fl_Menu_Item* menu; + menutitle(int X, int Y, int W, int H, const Fl_Menu_Item*); +}; + +// each vertical menu has one of these: +class menuwindow : public Fl_Menu_Window { + void draw(); + void drawentry(const Fl_Menu_Item*, int i, int erase); +public: + menutitle* title; + int handle(int); + int itemheight; // zero == menubar + int numitems; + int selected; + int drawn_selected; // last redraw has this selected + const Fl_Menu_Item* menu; + menuwindow(const Fl_Menu_Item* m, int X, int Y, int W, int H, + const Fl_Menu_Item* picked, const Fl_Menu_Item* title, + int menubar = 0, int menubar_title = 0, int right_edge = 0); + ~menuwindow(); + void set_selected(int); + int find_selected(int mx, int my); + int titlex(int); + void autoscroll(int); + void position(int x, int y); +}; + +#define LEADING 4 // extra vertical leading + +extern char fl_draw_shortcut; + +// width of label, including effect of & characters: +int Fl_Menu_Item::measure(int* hp, const Fl_Menu_* m) const { + Fl_Label l; + l.value = text; + l.image = 0; + l.deimage = 0; + l.type = labeltype_; + l.font = labelsize_ || labelfont_ ? labelfont_ : uchar(m ? m->textfont() : FL_HELVETICA); + l.size = labelsize_ ? labelsize_ : m ? m->textsize() : (uchar)FL_NORMAL_SIZE; + l.color = FL_FOREGROUND_COLOR; // this makes no difference? + fl_draw_shortcut = 1; + int w = 0; int h = 0; + l.measure(w, hp ? *hp : h); + fl_draw_shortcut = 0; + if (flags & (FL_MENU_TOGGLE|FL_MENU_RADIO)) w += 14; + return w; +} + +void Fl_Menu_Item::draw(int x, int y, int w, int h, const Fl_Menu_* m, + int selected) const { + Fl_Label l; + l.value = text; + l.image = 0; + l.deimage = 0; + l.type = labeltype_; + l.font = labelsize_ || labelfont_ ? labelfont_ : uchar(m ? m->textfont() : FL_HELVETICA); + l.size = labelsize_ ? labelsize_ : m ? m->textsize() : (uchar)FL_NORMAL_SIZE; + l.color = labelcolor_ ? labelcolor_ : m ? m->textcolor() : int(FL_FOREGROUND_COLOR); + if (!active()) l.color = fl_inactive((Fl_Color)l.color); + Fl_Color color = m ? m->color() : FL_GRAY; + if (selected) { + Fl_Color r = m ? m->selection_color() : FL_SELECTION_COLOR; + Fl_Boxtype b = m && m->down_box() ? m->down_box() : FL_FLAT_BOX; + if (fl_contrast(r,color)!=r) { // back compatability boxtypes + if (selected == 2) { // menu title + r = color; + b = m ? m->box() : FL_UP_BOX; + } else { + r = (Fl_Color)(FL_COLOR_CUBE-1); // white + l.color = fl_contrast((Fl_Color)labelcolor_, r); + } + } else { + l.color = fl_contrast((Fl_Color)labelcolor_, r); + } + if (selected == 2) { // menu title + fl_draw_box(b, x, y, w, h, r); + x += 3; + w -= 8; + } else { + fl_draw_box(b, x+1, y-(LEADING-2)/2, w-2, h+(LEADING-2), r); + } + } + + if (flags & (FL_MENU_TOGGLE|FL_MENU_RADIO)) { + int d = (h - FL_NORMAL_SIZE + 1) / 2; + int W = h - 2 * d; + + if (flags & FL_MENU_RADIO) { + fl_draw_box(FL_ROUND_DOWN_BOX, x+2, y+d, W, W, FL_BACKGROUND2_COLOR); + if (value()) { + fl_color(labelcolor_); + int tW = (W - Fl::box_dw(FL_ROUND_DOWN_BOX)) / 2 + 1; + if ((W - tW) & 1) tW++; // Make sure difference is even to center + int td = Fl::box_dx(FL_ROUND_DOWN_BOX) + 1; + switch (tW) { + // Larger circles draw fine... + default : + fl_pie(x + td + 2, y + d + td, tW, tW, 0.0, 360.0); + break; + + // Small circles don't draw well on many systems... + case 6 : + fl_rectf(x + td + 4, y + d + td, tW - 4, tW); + fl_rectf(x + td + 3, y + d + td + 1, tW - 2, tW - 2); + fl_rectf(x + td + 2, y + d + td + 2, tW, tW - 4); + break; + + case 5 : + case 4 : + case 3 : + fl_rectf(x + td + 3, y + d + td, tW - 2, tW); + fl_rectf(x + td + 2, y + d + td + 1, tW, tW - 2); + break; + + case 2 : + case 1 : + fl_rectf(x + td + 2, y + d + td, tW, tW); + break; + } + } + } else { + fl_draw_box(FL_DOWN_BOX, x+2, y+d, W, W, FL_BACKGROUND2_COLOR); + if (value()) { + fl_color(labelcolor_); + int tx = x + 5; + int tw = W - 6; + int d1 = tw/3; + int d2 = tw-d1; + int ty = y + d + (W+d2)/2-d1-2; + for (int n = 0; n < 3; n++, ty++) { + fl_line(tx, ty, tx+d1, ty+d1); + fl_line(tx+d1, ty+d1, tx+tw-1, ty+d1-d2+1); + } + } + } + x += W + 3; + w -= W + 3; + } + + if (!fl_draw_shortcut) fl_draw_shortcut = 1; + l.draw(x+3, y, w>6 ? w-6 : 0, h, FL_ALIGN_LEFT); + fl_draw_shortcut = 0; +} + +menutitle::menutitle(int X, int Y, int W, int H, const Fl_Menu_Item* L) : + Fl_Menu_Window(X, Y, W, H, 0) { + end(); + set_modal(); + clear_border(); + menu = L; + if (L->labelcolor_ || Fl::scheme() || L->labeltype_ > FL_NO_LABEL) clear_overlay(); +} + +menuwindow::menuwindow(const Fl_Menu_Item* m, int X, int Y, int Wp, int Hp, + const Fl_Menu_Item* picked, const Fl_Menu_Item* t, + int menubar, int menubar_title, int right_edge) + : Fl_Menu_Window(X, Y, Wp, Hp, 0) +{ + int scr_x, scr_y, scr_w, scr_h; + int tx = X, ty = Y; + + Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h); + if (!right_edge || right_edge > scr_x+scr_w) right_edge = scr_x+scr_w; + + end(); + set_modal(); + clear_border(); + menu = m; + if (m) m = m->first(); // find the first item that needs to be rendered + drawn_selected = -1; + if (button) { + box(button->box()); + if (box() == FL_NO_BOX || box() == FL_FLAT_BOX) box(FL_UP_BOX); + } else { + box(FL_UP_BOX); + } + color(button && !Fl::scheme() ? button->color() : FL_GRAY); + selected = -1; + {int j = 0; + if (m) for (const Fl_Menu_Item* m1=m; ; m1 = m1->next(), j++) { + if (picked) { + if (m1 == picked) {selected = j; picked = 0;} + else if (m1 > picked) {selected = j-1; picked = 0; Wp = Hp = 0;} + } + if (!m1->text) break; + } + numitems = j;} + + if (menubar) { + itemheight = 0; + title = 0; + return; + } + + itemheight = 1; + + int hotKeysw = 0; + int Wtitle = 0; + int Htitle = 0; + if (t) Wtitle = t->measure(&Htitle, button) + 12; + int W = 0; + if (m) for (; m->text; m = m->next()) { + int hh; int w1 = m->measure(&hh, button); + if (hh+LEADING>itemheight) itemheight = hh+LEADING; + if (m->flags&(FL_SUBMENU|FL_SUBMENU_POINTER)) w1 += 14; + if (w1 > W) W = w1; + if (m->shortcut_) { + w1 = int(fl_width(fl_shortcut_label(m->shortcut_))) + 8; + if (w1 > hotKeysw) hotKeysw = w1; + } + if (m->labelcolor_ || Fl::scheme() || m->labeltype_ > FL_NO_LABEL) clear_overlay(); + } + if (selected >= 0 && !Wp) X -= W/2; + int BW = Fl::box_dx(box()); + W += hotKeysw+2*BW+7; + if (Wp > W) W = Wp; + if (Wtitle > W) W = Wtitle; + + if (X < scr_x) X = scr_x; if (X > scr_x+scr_w-W) X= scr_x+scr_w-W; + x(X); w(W); + h((numitems ? itemheight*numitems-LEADING : 0)+2*BW+3); + if (selected >= 0) + Y = Y+(Hp-itemheight)/2-selected*itemheight-BW; + else { + Y = Y+Hp; + // if the menu hits the bottom of the screen, we try to draw + // it above the menubar instead. We will not adjust any menu + // that has a selected item. + if (Y+h()>scr_y+scr_h && Y-h()>=scr_y) { + if (Hp>1) + // if we know the height of the Fl_Menu_, use it + Y = Y-Hp-h(); + else if (t) + // assume that the menubar item height relates to the first + // menuitem as well + Y = Y-itemheight-h()-Fl::box_dh(box()); + else + // draw the menu to the right + Y = Y-h()+itemheight+Fl::box_dy(box()); + } + } + if (m) y(Y); else {y(Y-2); w(1); h(1);} + + if (t) { + int dy = menubar_title ? Fl::box_dy(button->box())+1 : 2; + int ht = menubar_title ? button->h()-dy*2 : Htitle+2*BW+3; + title = new menutitle(tx, ty-ht-dy, Wtitle, ht, t); + } else + title = 0; +} + +menuwindow::~menuwindow() { + hide(); + delete title; +} + +void menuwindow::position(int X, int Y) { + if (title) {title->position(X, title->y()+Y-y());} + Fl_Menu_Window::position(X, Y); + // x(X); y(Y); // don't wait for response from X +} + +// scroll so item i is visible on screen +void menuwindow::autoscroll(int n) { + int scr_x, scr_y, scr_w, scr_h; + int Y = y()+Fl::box_dx(box())+2+n*itemheight; + + Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h); + if (Y <= scr_y) Y = scr_y-Y+10; + else { + Y = Y+itemheight-scr_h-scr_y; + if (Y < 0) return; + Y = -Y-10; + } + Fl_Menu_Window::position(x(), y()+Y); + // y(y()+Y); // don't wait for response from X +} + +//////////////////////////////////////////////////////////////// + +void menuwindow::drawentry(const Fl_Menu_Item* m, int n, int eraseit) { + if (!m) return; // this happens if -1 is selected item and redrawn + + int BW = Fl::box_dx(box()); + int xx = BW; + int W = w(); + int ww = W-2*BW-1; + int yy = BW+1+n*itemheight; + int hh = itemheight - LEADING; + + if (eraseit && n != selected) { + fl_push_clip(xx+1, yy-(LEADING-2)/2, ww-2, hh+(LEADING-2)); + draw_box(box(), 0, 0, w(), h(), button ? button->color() : color()); + fl_pop_clip(); + } + + m->draw(xx, yy, ww, hh, button, n==selected); + + // the shortcuts and arrows assumme fl_color() was left set by draw(): + if (m->submenu()) { + int sz = (hh-7)&-2; + int y1 = yy+(hh-sz)/2; + int x1 = xx+ww-sz-3; + fl_polygon(x1+2, y1, x1+2, y1+sz, x1+sz/2+2, y1+sz/2); + } else if (m->shortcut_) { + Fl_Font f = m->labelsize_ || m->labelfont_ ? (Fl_Font)m->labelfont_ : + button ? button->textfont() : FL_HELVETICA; + fl_font(f, m->labelsize_ ? m->labelsize_ : + button ? button->textsize() : FL_NORMAL_SIZE); + fl_draw(fl_shortcut_label(m->shortcut_), xx, yy, ww-3, hh, FL_ALIGN_RIGHT); + } + + if (m->flags & FL_MENU_DIVIDER) { + fl_color(FL_DARK3); + fl_xyline(BW-1, yy+hh+(LEADING-2)/2, W-2*BW+2); + fl_color(FL_LIGHT3); + fl_xyline(BW-1, yy+hh+((LEADING-2)/2+1), W-2*BW+2); + } +} + +void menutitle::draw() { + menu->draw(0, 0, w(), h(), button, 2); +} + +void menuwindow::draw() { + if (damage() != FL_DAMAGE_CHILD) { // complete redraw + fl_draw_box(box(), 0, 0, w(), h(), button ? button->color() : color()); + if (menu) { + const Fl_Menu_Item* m; int j; + for (m=menu->first(), j=0; m->text; j++, m = m->next()) drawentry(m, j, 0); + } + } else { + if (damage() & FL_DAMAGE_CHILD && selected!=drawn_selected) { // change selection + drawentry(menu->next(drawn_selected), drawn_selected, 1); + drawentry(menu->next(selected), selected, 1); + } + } + drawn_selected = selected; +} + +void menuwindow::set_selected(int n) { + if (n != selected) {selected = n; damage(FL_DAMAGE_CHILD);} +} + +//////////////////////////////////////////////////////////////// + +int menuwindow::find_selected(int mx, int my) { + if (!menu || !menu->text) return -1; + mx -= x(); + my -= y(); + if (my < 0 || my >= h()) return -1; + if (!itemheight) { // menubar + int xx = 3; int n = 0; + const Fl_Menu_Item* m = menu ? menu->first() : 0; + for (; ; m = m->next(), n++) { + if (!m->text) return -1; + xx += m->measure(0, button) + 16; + if (xx > mx) break; + } + return n; + } + if (mx < Fl::box_dx(box()) || mx >= w()) return -1; + int n = (my-Fl::box_dx(box())-1)/itemheight; + if (n < 0 || n>=numitems) return -1; + return n; +} + +// return horizontal position for item n in a menubar: +int menuwindow::titlex(int n) { + const Fl_Menu_Item* m; + int xx = 3; + for (m=menu->first(); n--; m = m->next()) xx += m->measure(0, button) + 16; + return xx; +} + +//////////////////////////////////////////////////////////////// +// Fl_Menu_Item::popup(...) + +// Because Fl::grab() is done, all events go to one of the menu windows. +// But the handle method needs to look at all of them to find out +// what item the user is pointing at. And it needs a whole lot +// of other state variables to determine what is going on with +// the currently displayed menus. +// So the main loop (handlemenu()) puts all the state in a structure +// and puts a pointer to it in a static location, so the handle() +// on menus can refer to it and alter it. The handle() method +// changes variables in this state to indicate what item is +// picked, but does not actually alter the display, instead the +// main loop does that. This is because the X mapping and unmapping +// of windows is slow, and we don't want to fall behind the events. + +// values for menustate.state: +#define INITIAL_STATE 0 // no mouse up or down since popup() called +#define PUSH_STATE 1 // mouse has been pushed on a normal item +#define DONE_STATE 2 // exit the popup, the current item was picked +#define MENU_PUSH_STATE 3 // mouse has been pushed on a menu title + +struct menustate { + const Fl_Menu_Item* current_item; // what mouse is pointing at + int menu_number; // which menu it is in + int item_number; // which item in that menu, -1 if none + menuwindow* p[20]; // pointers to menus + int nummenus; + int menubar; // if true p[0] is a menubar + int state; +}; +static menustate* p; + +static inline void setitem(const Fl_Menu_Item* i, int m, int n) { + p->current_item = i; + p->menu_number = m; + p->item_number = n; +} + +static void setitem(int m, int n) { + menustate &pp = *p; + pp.current_item = (n >= 0) ? pp.p[m]->menu->next(n) : 0; + pp.menu_number = m; + pp.item_number = n; +} + +static int forward(int menu) { // go to next item in menu menu if possible + menustate &pp = *p; + menuwindow &m = *(pp.p[menu]); + int item = (menu == pp.menu_number) ? pp.item_number : m.selected; + while (++item < m.numitems) { + const Fl_Menu_Item* m1 = m.menu->next(item); + if (m1->activevisible()) {setitem(m1, menu, item); return 1;} + } + return 0; +} + +static int backward(int menu) { // previous item in menu menu if possible + menustate &pp = *p; + menuwindow &m = *(pp.p[menu]); + int item = (menu == pp.menu_number) ? pp.item_number : m.selected; + if (item < 0) item = m.numitems; + while (--item >= 0) { + const Fl_Menu_Item* m1 = m.menu->next(item); + if (m1->activevisible()) {setitem(m1, menu, item); return 1;} + } + return 0; +} + +int menuwindow::handle(int e) { + menustate &pp = *p; + switch (e) { + case FL_KEYBOARD: + switch (Fl::event_key()) { + case FL_BackSpace: + case 0xFE20: // backtab + BACKTAB: + if (!backward(pp.menu_number)) {pp.item_number = -1;backward(pp.menu_number);} + return 1; + case FL_Up: + if (pp.menubar && pp.menu_number == 0) { + // Do nothing... + } else if (backward(pp.menu_number)) { + // Do nothing... + } else if (pp.menubar && pp.menu_number==1) { + setitem(0, pp.p[0]->selected); + } + return 1; + case FL_Tab: + if (Fl::event_shift()) goto BACKTAB; + case FL_Down: + if (pp.menu_number || !pp.menubar) forward(pp.menu_number); + else if (pp.menu_number < pp.nummenus-1) forward(pp.menu_number+1); + return 1; + case FL_Right: + if (pp.menubar && (pp.menu_number<=0 || pp.menu_number==1 && pp.nummenus==2)) + forward(0); + else if (pp.menu_number < pp.nummenus-1) forward(pp.menu_number+1); + return 1; + case FL_Left: + if (pp.menubar && pp.menu_number<=1) backward(0); + else if (pp.menu_number>0) + setitem(pp.menu_number-1, pp.p[pp.menu_number-1]->selected); + return 1; + case FL_Enter: + case FL_KP_Enter: + case ' ': + pp.state = DONE_STATE; + return 1; + case FL_Escape: + setitem(0, -1, 0); + pp.state = DONE_STATE; + return 1; + } + break; + case FL_SHORTCUT: { + for (int mymenu = pp.nummenus; mymenu--;) { + menuwindow &mw = *(pp.p[mymenu]); + int item; const Fl_Menu_Item* m = mw.menu->find_shortcut(&item); + if (m) { + setitem(m, mymenu, item); + if (!m->submenu()) pp.state = DONE_STATE; + return 1; + } + }} break; + case FL_ENTER: + case FL_MOVE: + case FL_PUSH: + case FL_DRAG: { +#ifdef __QNX__ + // STR 704: workaround QNX X11 bug - in QNX a FL_MOVE event is sent + // right after FL_RELEASE... + if (pp.state == DONE_STATE) return 1; +#endif // __QNX__ + int mx = Fl::event_x_root(); + int my = Fl::event_y_root(); + int item=0; int mymenu = pp.nummenus-1; + if (e == FL_PUSH && (!pp.menubar || mymenu) && + (mx < pp.p[mymenu]->x_root() || + mx >= (pp.p[mymenu]->x_root() + pp.p[mymenu]->w()) || + my < pp.p[mymenu]->y_root() || + my >= (pp.p[mymenu]->y_root() + pp.p[mymenu]->h()))) { + // Clicking outside menu cancels it... + setitem(0, -1, 0); + pp.state = DONE_STATE; + return 1; + } + for (mymenu = pp.nummenus-1; ; mymenu--) { + item = pp.p[mymenu]->find_selected(mx, my); + if (item >= 0) break; + if (mymenu <= 0) return 0; + } + if (my == 0 && item > 0) setitem(mymenu, item - 1); + else setitem(mymenu, item); + if (e == FL_PUSH) { + if (pp.current_item && pp.current_item->submenu() // this is a menu title + && item != pp.p[mymenu]->selected // and it is not already on + && !pp.current_item->callback_) // and it does not have a callback + pp.state = MENU_PUSH_STATE; + else + pp.state = PUSH_STATE; + }} return 1; + case FL_RELEASE: + // do nothing if they try to pick inactive items + if (pp.current_item && !pp.current_item->activevisible()) { + if (pp.state==INITIAL_STATE) { + setitem(0, -1, 0); + pp.state = DONE_STATE; + } + return 1; + } + // Mouse must either be held down/dragged some, or this must be + // the second click (not the one that popped up the menu): + if (!Fl::event_is_click() || pp.state == PUSH_STATE || + pp.menubar && pp.current_item && !pp.current_item->submenu() // button + ) { +#if 0 // makes the check/radio items leave the menu up + const Fl_Menu_Item* m = pp.current_item; + if (m && button && (m->flags & (FL_MENU_TOGGLE|FL_MENU_RADIO))) { + ((Fl_Menu_*)button)->picked(m); + pp.p[pp.menu_number]->redraw(); + } else +#endif + pp.state = DONE_STATE; + } + return 1; + } + return Fl_Window::handle(e); +} + +const Fl_Menu_Item* Fl_Menu_Item::pulldown( + int X, int Y, int W, int H, + const Fl_Menu_Item* initial_item, + const Fl_Menu_* pbutton, + const Fl_Menu_Item* t, + int menubar) const +{ + Fl_Group::current(0); // fix possible user error... + + button = pbutton; + if (pbutton) { + for (Fl_Window* w = pbutton->window(); w; w = w->window()) { + X += w->x(); + Y += w->y(); + } + } else { + X += Fl::event_x_root()-Fl::event_x(); + Y += Fl::event_y_root()-Fl::event_y(); + } + menuwindow mw(this, X, Y, W, H, initial_item, t, menubar); + Fl::grab(mw); + menustate pp; p = &pp; + pp.p[0] = &mw; + pp.nummenus = 1; + pp.menubar = menubar; + pp.state = INITIAL_STATE; + + menuwindow* fakemenu = 0; // kludge for buttons in menubar + + // preselected item, pop up submenus if necessary: + if (initial_item && mw.selected >= 0) { + setitem(0, mw.selected); + goto STARTUP; + } + + pp.current_item = 0; pp.menu_number = 0; pp.item_number = -1; + if (menubar) { + // find the initial menu + if (!mw.handle(FL_DRAG)) { + Fl::release(); + return 0; + } + } + initial_item = pp.current_item; + if (initial_item) goto STARTUP; + + // the main loop, runs until p.state goes to DONE_STATE: + for (;;) { + + // make sure all the menus are shown: + {for (int k = menubar; k < pp.nummenus; k++) + if (!pp.p[k]->shown()) { + if (pp.p[k]->title) pp.p[k]->title->show(); + pp.p[k]->show(); + } + } + + // get events: + {const Fl_Menu_Item* oldi = pp.current_item; + Fl::wait(); + if (pp.state == DONE_STATE) break; // done. + if (pp.current_item == oldi) continue;} + // only do rest if item changes: + + delete fakemenu; fakemenu = 0; // turn off "menubar button" + + if (!pp.current_item) { // pointing at nothing + // turn off selection in deepest menu, but don't erase other menus: + pp.p[pp.nummenus-1]->set_selected(-1); + continue; + } + + delete fakemenu; fakemenu = 0; + initial_item = 0; // stop the startup code + pp.p[pp.menu_number]->autoscroll(pp.item_number); + + STARTUP: + menuwindow& cw = *pp.p[pp.menu_number]; + const Fl_Menu_Item* m = pp.current_item; + if (!m->activevisible()) { // pointing at inactive item + cw.set_selected(-1); + initial_item = 0; // turn off startup code + continue; + } + cw.set_selected(pp.item_number); + + if (m==initial_item) initial_item=0; // stop the startup code if item found + if (m->submenu()) { + const Fl_Menu_Item* title = m; + const Fl_Menu_Item* menutable; + if (m->flags&FL_SUBMENU) menutable = m+1; + else menutable = (Fl_Menu_Item*)(m)->user_data_; + // figure out where new menu goes: + int nX, nY; + if (!pp.menu_number && pp.menubar) { // menu off a menubar: + nX = cw.x() + cw.titlex(pp.item_number); + nY = cw.y() + cw.h(); + initial_item = 0; + } else { + nX = cw.x() + cw.w(); + nY = cw.y() + pp.item_number * cw.itemheight; + title = 0; + } + if (initial_item) { // bring up submenu containing initial item: + menuwindow* n = new menuwindow(menutable,X,Y,W,H,initial_item,title,0,0,cw.x()); + pp.p[pp.nummenus++] = n; + // move all earlier menus to line up with this new one: + if (n->selected>=0) { + int dy = n->y()-nY; + int dx = n->x()-nX; + for (int menu = 0; menu <= pp.menu_number; menu++) { + menuwindow* tt = pp.p[menu]; + int nx = tt->x()+dx; if (nx < 0) {nx = 0; dx = -tt->x();} + int ny = tt->y()+dy; if (ny < 0) {ny = 0; dy = -tt->y();} + tt->position(nx, ny); + } + setitem(pp.nummenus-1, n->selected); + goto STARTUP; + } + } else if (pp.nummenus > pp.menu_number+1 && + pp.p[pp.menu_number+1]->menu == menutable) { + // the menu is already up: + while (pp.nummenus > pp.menu_number+2) delete pp.p[--pp.nummenus]; + pp.p[pp.nummenus-1]->set_selected(-1); + } else { + // delete all the old menus and create new one: + while (pp.nummenus > pp.menu_number+1) delete pp.p[--pp.nummenus]; + pp.p[pp.nummenus++]= new menuwindow(menutable, nX, nY, + title?1:0, 0, 0, title, 0, menubar, cw.x()); + } + } else { // !m->submenu(): + while (pp.nummenus > pp.menu_number+1) delete pp.p[--pp.nummenus]; + if (!pp.menu_number && pp.menubar) { + // kludge so "menubar buttons" turn "on" by using menu title: + fakemenu = new menuwindow(0, + cw.x()+cw.titlex(pp.item_number), + cw.y()+cw.h(), 0, 0, + 0, m, 0, 1); + fakemenu->title->show(); + } + } + } + const Fl_Menu_Item* m = pp.current_item; + Fl::release(); + delete fakemenu; + while (pp.nummenus>1) delete pp.p[--pp.nummenus]; + mw.hide(); + return m; +} + +const Fl_Menu_Item* +Fl_Menu_Item::popup( + int X, int Y, + const char* title, + const Fl_Menu_Item* picked, + const Fl_Menu_* but + ) const +{ + static Fl_Menu_Item dummy; // static so it is all zeros + dummy.text = title; + return pulldown(X, Y, 0, 0, picked, but, title ? &dummy : 0); +} + +// Search only the top level menu for a shortcut. Either &x in the +// label or the shortcut fields are used: +const Fl_Menu_Item* Fl_Menu_Item::find_shortcut(int* ip) const { + const Fl_Menu_Item* m = first(); + if (m) for (int ii = 0; m->text; m = m->next(), ii++) { + if (m->activevisible()) { + if (Fl::test_shortcut(m->shortcut_) + || Fl_Widget::test_shortcut(m->text)) { + if (ip) *ip=ii; + return m; + } + } + } + return 0; +} + +// Recursive search of all submenus for anything with this key as a +// shortcut. Only uses the shortcut field, ignores &x in the labels: +const Fl_Menu_Item* Fl_Menu_Item::test_shortcut() const { + const Fl_Menu_Item* m = first(); + const Fl_Menu_Item* ret = 0; + if (m) for (; m->text; m = m->next()) { + if (m->activevisible()) { + // return immediately any match of an item in top level menu: + if (Fl::test_shortcut(m->shortcut_)) return m; + // if (Fl_Widget::test_shortcut(m->text)) return m; + // only return matches from lower menu if nothing found in top menu: + if (!ret && m->submenu()) { + const Fl_Menu_Item* s = + (m->flags&FL_SUBMENU) ? m+1:(const Fl_Menu_Item*)m->user_data_; + ret = s->test_shortcut(); + } + } + } + return ret; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Menu_.cxx b/Utilities/FLTK/src/Fl_Menu_.cxx new file mode 100644 index 0000000000..f5b3c61a22 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Menu_.cxx @@ -0,0 +1,232 @@ +// +// "$Id$" +// +// Common menu code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// This is a base class for all items that have a menu: +// Fl_Menu_Bar, Fl_Menu_Button, Fl_Choice +// This provides storage for a menu item, functions to add/modify/delete +// items, and a call for when the user picks a menu item. + +// More code in Fl_Menu_add.cxx + +#include <FL/Fl.H> +#include <FL/Fl_Menu_.H> +#include "flstring.h" +#include <stdio.h> +#include <stdlib.h> + +// Set 'pathname' of specified menuitem +// If finditem==NULL, mvalue() is used (the most recently picked menuitem) +// Returns: +// 0 : OK +// -1 : item not found (name="") +// -2 : 'name' not large enough (name="") +// +#define SAFE_STRCAT(s) \ + { len += strlen(s); if ( len >= namelen ) { *name='\0'; return(-2); } else strcat(name,(s)); } +int Fl_Menu_::item_pathname(char *name, int namelen, const Fl_Menu_Item *finditem) const { + int len = 0; + finditem = finditem ? finditem : mvalue(); + name[0] = '\0'; + for ( int t=0; t<size(); t++ ) { + const Fl_Menu_Item *m = &(menu()[t]); + if ( m->submenu() ) { // submenu? descend + if (*name) SAFE_STRCAT("/"); + if (m->label()) SAFE_STRCAT(m->label()); + } else { + if (m->label()) { // menu item? + if ( m == finditem ) { // found? tack on itemname, done. + SAFE_STRCAT("/"); + SAFE_STRCAT(m->label()); + return(0); + } + } else { // end of submenu? pop + char *ss = strrchr(name, '/'); + if ( ss ) { *ss = 0; len = strlen(name); } // "File/Edit" -> "File" + else { name[0] = '\0'; len = 0; } // "File" -> "" + continue; + } + } + } + *name = '\0'; + return(-1); // item not found +} + +// FIND MENU ITEM INDEX, GIVEN MENU PATHNAME +// eg. "Edit/Copy" +// Will also return submenus, eg. "Edit" +// Returns NULL if not found. +// +const Fl_Menu_Item * +Fl_Menu_::find_item(const char *name) +{ + char menupath[1024] = ""; // File/Export + + for ( int t=0; t < size(); t++ ) { + Fl_Menu_Item *m = menu_ + t; + + if (m->flags&FL_SUBMENU) { + // IT'S A SUBMENU + // we do not support searches through FL_SUBMENU_POINTER links + if (menupath[0]) strlcat(menupath, "/", sizeof(menupath)); + strlcat(menupath, m->label(), sizeof(menupath)); + if (!strcmp(menupath, name)) return m; + } else { + if (!m->label()) { + // END OF SUBMENU? Pop back one level. + char *ss = strrchr(menupath, '/'); + if ( ss ) *ss = 0; + else menupath[0] = '\0'; + continue; + } + + // IT'S A MENU ITEM + char itempath[1024]; // eg. Edit/Copy + strcpy(itempath, menupath); + if (itempath[0]) strlcat(itempath, "/", sizeof(itempath)); + strlcat(itempath, m->label(), sizeof(itempath)); + if (!strcmp(itempath, name)) return m; + } + } + + return (const Fl_Menu_Item *)0; +} + +int Fl_Menu_::value(const Fl_Menu_Item* m) { + clear_changed(); + if (value_ != m) {value_ = m; return 1;} + return 0; +} + +// When user picks a menu item, call this. It will do the callback. +// Unfortunatly this also casts away const for the checkboxes, but this +// was necessary so non-checkbox menus can really be declared const... +const Fl_Menu_Item* Fl_Menu_::picked(const Fl_Menu_Item* v) { + if (v) { + if (v->radio()) { + if (!v->value()) { // they are turning on a radio item + set_changed(); + ((Fl_Menu_Item*)v)->setonly(); + } + redraw(); + } else if (v->flags & FL_MENU_TOGGLE) { + set_changed(); + ((Fl_Menu_Item*)v)->flags ^= FL_MENU_VALUE; + redraw(); + } else if (v != value_) { // normal item + set_changed(); + } + value_ = v; + if (when()&(FL_WHEN_CHANGED|FL_WHEN_RELEASE)) { + if (changed() || when()&FL_WHEN_NOT_CHANGED) { + if (value_ && value_->callback_) value_->do_callback((Fl_Widget*)this); + else do_callback(); + } + } + } + return v; +} + +// turn on one of a set of radio buttons +void Fl_Menu_Item::setonly() { + flags |= FL_MENU_RADIO | FL_MENU_VALUE; + Fl_Menu_Item* j; + for (j = this; ; ) { // go down + if (j->flags & FL_MENU_DIVIDER) break; // stop on divider lines + j++; + if (!j->text || !j->radio()) break; // stop after group + j->clear(); + } + for (j = this-1; ; j--) { // go up + if (!j->text || (j->flags&FL_MENU_DIVIDER) || !j->radio()) break; + j->clear(); + } +} + +Fl_Menu_::Fl_Menu_(int X,int Y,int W,int H,const char* l) +: Fl_Widget(X,Y,W,H,l) { + set_flag(SHORTCUT_LABEL); + box(FL_UP_BOX); + when(FL_WHEN_RELEASE_ALWAYS); + value_ = menu_ = 0; + alloc = 0; + selection_color(FL_SELECTION_COLOR); + textfont(FL_HELVETICA); + textsize((uchar)FL_NORMAL_SIZE); + textcolor(FL_FOREGROUND_COLOR); + down_box(FL_NO_BOX); +} + +int Fl_Menu_::size() const { + if (!menu_) return 0; + return menu_->size(); +} + +void Fl_Menu_::menu(const Fl_Menu_Item* m) { + clear(); + value_ = menu_ = (Fl_Menu_Item*)m; +} + +// this version is ok with new Fl_Menu_add code with fl_menu_array_owner: + +void Fl_Menu_::copy(const Fl_Menu_Item* m, void* ud) { + int n = m->size(); + Fl_Menu_Item* newMenu = new Fl_Menu_Item[n]; + memcpy(newMenu, m, n*sizeof(Fl_Menu_Item)); + menu(newMenu); + alloc = 1; // make destructor free array, but not strings + // for convienence, provide way to change all the user data pointers: + if (ud) for (; n--;) { + if (newMenu->callback_) newMenu->user_data_ = ud; + newMenu++; + } +} + +Fl_Menu_::~Fl_Menu_() { + clear(); +} + +// Fl_Menu::add() uses this to indicate the owner of the dynamically- +// expanding array. We must not free this array: +Fl_Menu_* fl_menu_array_owner = 0; + +void Fl_Menu_::clear() { + if (alloc) { + if (alloc>1) for (int i = size(); i--;) + if (menu_[i].text) free((void*)menu_[i].text); + if (this == fl_menu_array_owner) + fl_menu_array_owner = 0; + else + delete[] menu_; + menu_ = 0; + value_ = 0; + alloc = 0; + } +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Menu_Bar.cxx b/Utilities/FLTK/src/Fl_Menu_Bar.cxx new file mode 100644 index 0000000000..9843e394d3 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Menu_Bar.cxx @@ -0,0 +1,78 @@ +// +// "$Id$" +// +// Menu bar widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Menu_Bar.H> +#include <FL/fl_draw.H> + +void Fl_Menu_Bar::draw() { + draw_box(); + if (!menu() || !menu()->text) return; + const Fl_Menu_Item* m; + int X = x()+6; + for (m=menu()->first(); m->text; m = m->next()) { + int W = m->measure(0,this) + 16; + m->draw(X, y(), W, h(), this); + X += W; + if (m->flags & FL_MENU_DIVIDER) { + int y1 = y() + Fl::box_dy(box()); + int y2 = y1 + h() - Fl::box_dh(box()) - 1; + + // Draw a vertical divider between menus... + fl_color(FL_DARK3); + fl_yxline(X - 6, y1, y2); + fl_color(FL_LIGHT3); + fl_yxline(X - 5, y1, y2); + } + } +} + +int Fl_Menu_Bar::handle(int event) { + const Fl_Menu_Item* v; + if (menu() && menu()->text) switch (event) { + case FL_ENTER: + case FL_LEAVE: + return 1; + case FL_PUSH: + v = 0; + J1: + v = menu()->pulldown(x(), y(), w(), h(), v, this, 0, 1); + picked(v); + return 1; + case FL_SHORTCUT: + if (visible_r()) { + v = menu()->find_shortcut(); + if (v && v->submenu()) goto J1; + } + return test_shortcut() != 0; + } + return 0; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Menu_Button.cxx b/Utilities/FLTK/src/Fl_Menu_Button.cxx new file mode 100644 index 0000000000..80768a6e07 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Menu_Button.cxx @@ -0,0 +1,108 @@ +// +// "$Id$" +// +// Menu button widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2006 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Menu_Button.H> +#include <FL/fl_draw.H> + + +static Fl_Menu_Button *pressed_menu_button_ = 0; + +void Fl_Menu_Button::draw() { + if (!box() || type()) return; + draw_box(pressed_menu_button_ == this ? fl_down(box()) : box(), color()); + draw_label(); + if (Fl::focus() == this) draw_focus(); + if (box() == FL_FLAT_BOX) return; // for XForms compatability + int H = (labelsize()-3)&-2; + int X = x()+w()-H*2; + int Y = y()+(h()-H)/2; + fl_color(active_r() ? FL_DARK3 : fl_inactive(FL_DARK3)); + fl_line(X+H/2, Y+H, X, Y, X+H, Y); + fl_color(active_r() ? FL_LIGHT3 : fl_inactive(FL_LIGHT3)); + fl_line(X+H, Y, X+H/2, Y+H); +} + +const Fl_Menu_Item* Fl_Menu_Button::popup() { + const Fl_Menu_Item* m; + pressed_menu_button_ = this; + redraw(); + if (!box() || type()) { + m = menu()->popup(Fl::event_x(), Fl::event_y(), label(), mvalue(), this); + } else { + m = menu()->pulldown(x(), y(), w(), h(), 0, this); + } + picked(m); + pressed_menu_button_ = 0; + redraw(); + return m; +} + +int Fl_Menu_Button::handle(int e) { + if (!menu() || !menu()->text) return 0; + switch (e) { + case FL_ENTER: + case FL_LEAVE: + return (box() && !type()) ? 1 : 0; + case FL_PUSH: + if (!box()) { + if (Fl::event_button() != 3) return 0; + } else if (type()) { + if (!(type() & (1 << (Fl::event_button()-1)))) return 0; + } + if (Fl::visible_focus()) Fl::focus(this); + popup(); + return 1; + case FL_KEYBOARD: + if (!box()) return 0; + if (Fl::event_key() == ' ' && + !(Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) { + popup(); + return 1; + } else return 0; + case FL_SHORTCUT: + if (Fl_Widget::test_shortcut()) {popup(); return 1;} + return test_shortcut() != 0; + case FL_FOCUS: + case FL_UNFOCUS: + if (box() && Fl::visible_focus()) { + redraw(); + return 1; + } + default: + return 0; + } +} + +Fl_Menu_Button::Fl_Menu_Button(int X,int Y,int W,int H,const char *l) +: Fl_Menu_(X,Y,W,H,l) { + down_box(FL_NO_BOX); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Menu_Window.cxx b/Utilities/FLTK/src/Fl_Menu_Window.cxx new file mode 100644 index 0000000000..98bd981343 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Menu_Window.cxx @@ -0,0 +1,104 @@ +// +// "$Id$" +// +// Menu window code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// This is the window type used by Fl_Menu to make the pop-ups. +// It draws in the overlay planes if possible. + +// Also here is the implementation of the mouse & keyboard grab, +// which are used so that clicks outside the program's windows +// can be used to dismiss the menus. + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#include <FL/x.H> +#include <FL/fl_draw.H> +#include <FL/Fl_Menu_Window.H> + +// WIN32 note: HAVE_OVERLAY is false +#if HAVE_OVERLAY +extern XVisualInfo *fl_find_overlay_visual(); +extern XVisualInfo *fl_overlay_visual; +extern Colormap fl_overlay_colormap; +extern unsigned long fl_transparent_pixel; +static GC gc; // the GC used by all X windows +extern uchar fl_overlay; // changes how fl_color(x) works +#endif + +#include <stdio.h> + +void Fl_Menu_Window::show() { +#if HAVE_OVERLAY + if (!shown() && overlay() && fl_find_overlay_visual()) { + XInstallColormap(fl_display, fl_overlay_colormap); + fl_background_pixel = int(fl_transparent_pixel); + Fl_X::make_xid(this, fl_overlay_visual, fl_overlay_colormap); + fl_background_pixel = -1; + } else +#endif + Fl_Single_Window::show(); +} + +void Fl_Menu_Window::flush() { +#if HAVE_OVERLAY + if (!fl_overlay_visual || !overlay()) {Fl_Single_Window::flush(); return;} + Fl_X *myi = Fl_X::i(this); + fl_window = myi->xid; + if (!gc) gc = XCreateGC(fl_display, myi->xid, 0, 0); + fl_gc = gc; + fl_overlay = 1; + fl_clip_region(myi->region); myi->region = 0; current_ = this; + draw(); + fl_overlay = 0; +#else + Fl_Single_Window::flush(); +#endif +} + +void Fl_Menu_Window::erase() { +#if HAVE_OVERLAY + if (!gc || !shown()) return; +//XSetForeground(fl_display, gc, 0); +//XFillRectangle(fl_display, fl_xid(this), gc, 0, 0, w(), h()); + XClearWindow(fl_display, fl_xid(this)); +#endif +} + +// Fix the colormap flashing on Maximum Impact Graphics by erasing the +// menu before unmapping it: +void Fl_Menu_Window::hide() { + erase(); + Fl_Single_Window::hide(); +} + +Fl_Menu_Window::~Fl_Menu_Window() { + hide(); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Menu_add.cxx b/Utilities/FLTK/src/Fl_Menu_add.cxx new file mode 100644 index 0000000000..77a70edd83 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Menu_add.cxx @@ -0,0 +1,268 @@ +// +// "$Id$" +// +// Menu utilities for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Methods to alter the menu in an Fl_Menu_ widget. + +// These are for Forms emulation and for dynamically changing the +// menus. They are in this source file so they are not linked in if +// not used, which is what will happen if the the program only uses +// constant menu tables. + +// Not at all guaranteed to be Forms compatable, especially with any +// string with a % sign in it! + +#include <FL/Fl_Menu_.H> +#include "flstring.h" +#include <stdio.h> +#include <stdlib.h> + +// If the array is this, we will double-reallocate as necessary: +static Fl_Menu_Item* local_array = 0; +static int local_array_alloc = 0; // number allocated +static int local_array_size = 0; // == size(local_array) +extern Fl_Menu_* fl_menu_array_owner; // in Fl_Menu_.cxx + +// For historical reasons there are matching methods that work on a +// user-allocated array of Fl_Menu_Item. These methods are quite +// depreciated and should not be used. These old methods use the +// above pointers to detect if the array belongs to an Fl_Menu_ +// widget, and if so it reallocates as necessary. + +// Insert a single Fl_Menu_Item into an array of size at offset n, +// if this is local_array it will be reallocated if needed. +static Fl_Menu_Item* insert( + Fl_Menu_Item* array, int size, + int n, + const char *text, + int flags +) { + if (array == local_array && size >= local_array_alloc) { + local_array_alloc = 2*size; + Fl_Menu_Item* newarray = new Fl_Menu_Item[local_array_alloc]; + memmove(newarray, array, size*sizeof(Fl_Menu_Item)); + delete[] local_array; + local_array = array = newarray; + } + // move all the later items: + memmove(array+n+1, array+n, sizeof(Fl_Menu_Item)*(size-n)); + // create the new item: + Fl_Menu_Item* m = array+n; + m->text = text ? strdup(text) : 0; + m->shortcut_ = 0; + m->callback_ = 0; + m->user_data_ = 0; + m->flags = flags; + m->labeltype_ = m->labelfont_ = m->labelsize_ = m->labelcolor_ = 0; + return array; +} + +// Comparison that does not care about deleted '&' signs: +static int compare(const char* a, const char* b) { + for (;;) { + int n = *a-*b; + if (n) { + if (*a == '&') a++; + else if (*b == '&') b++; + else return n; + } else if (*a) { + a++; b++; + } else { + return 0; + } + } +} + +// Add an item. The text is split at '/' characters to automatically +// produce submenus (actually a totally unnecessary feature as you can +// now add submenu titles directly by setting SUBMENU in the flags): +int Fl_Menu_Item::add( + const char *mytext, + int sc, + Fl_Callback *cb, + void *data, + int myflags +) { + Fl_Menu_Item *array = this; + Fl_Menu_Item *m = this; + const char *p; + char *q; + char buf[1024]; + + int msize = array==local_array ? local_array_size : array->size(); + int flags1 = 0; + const char* item; + + // split at slashes to make submenus: + for (;;) { + + // leading slash makes us assumme it is a filename: + if (*mytext == '/') {item = mytext; break;} + + // leading underscore causes divider line: + if (*mytext == '_') {mytext++; flags1 = FL_MENU_DIVIDER;} + + // copy to buf, changing \x to x: + q = buf; + for (p=mytext; *p && *p != '/'; *q++ = *p++) if (*p=='\\' && p[1]) p++; + *q = 0; + + item = buf; + if (*p != '/') break; /* not a menu title */ + mytext = p+1; /* point at item title */ + + /* find a matching menu title: */ + for (; m->text; m = m->next()) + if (m->flags&FL_SUBMENU && !compare(item, m->text)) break; + + if (!m->text) { /* create a new menu */ + int n = m-array; + array = insert(array, msize, n, item, FL_SUBMENU|flags1); + msize++; + array = insert(array, msize, n+1, 0, 0); + msize++; + m = array+n; + } + m++; /* go into the submenu */ + flags1 = 0; + } + + /* find a matching menu item: */ + for (; m->text; m = m->next()) + if (!(m->flags&FL_SUBMENU) && !compare(m->text,item)) break; + + if (!m->text) { /* add a new menu item */ + int n = m-array; + array = insert(array, msize, n, item, myflags|flags1); + msize++; + if (myflags & FL_SUBMENU) { // add submenu delimiter + array = insert(array, msize, n+1, 0, 0); + msize++; + } + m = array+n; + } + + /* fill it in */ + m->shortcut_ = sc; + m->callback_ = cb; + m->user_data_ = data; + m->flags = myflags|flags1; + + if (array == local_array) local_array_size = msize; + return m-array; +} + +int Fl_Menu_::add(const char *t, int s, Fl_Callback *c,void *v,int f) { + // make this widget own the local array: + if (this != fl_menu_array_owner) { + if (fl_menu_array_owner) { + Fl_Menu_* o = fl_menu_array_owner; + // the previous owner get's its own correctly-sized array: + int value_offset = o->value_-local_array; + int n = local_array_size; + Fl_Menu_Item* newMenu = o->menu_ = new Fl_Menu_Item[n]; + memcpy(newMenu, local_array, n*sizeof(Fl_Menu_Item)); + if (o->value_) o->value_ = newMenu+value_offset; + } + if (menu_) { + // this already has a menu array, use it as the local one: + delete[] local_array; + if (!alloc) copy(menu_); // duplicate a user-provided static array + // add to the menu's current array: + local_array_alloc = local_array_size = size(); + local_array = menu_; + } else { + // start with a blank array: + alloc = 2; // indicates that the strings can be freed + if (local_array) { + menu_ = local_array; + } else { + local_array_alloc = 15; + local_array = menu_ = new Fl_Menu_Item[local_array_alloc]; + memset(local_array, 0, sizeof(Fl_Menu_Item) * local_array_alloc); + } + memset(menu_, 0, sizeof(Fl_Menu_Item)); + local_array_size = 1; + } + fl_menu_array_owner = this; + } + int r = menu_->add(t,s,c,v,f); + // if it rellocated array we must fix the pointer: + int value_offset = value_-menu_; + menu_ = local_array; // in case it reallocated it + if (value_) value_ = menu_+value_offset; + return r; +} + +// This is a Forms (and SGI GL library) compatable add function, it +// adds many menu items, with '|' seperating the menu items, and tab +// seperating the menu item names from an optional shortcut string. +int Fl_Menu_::add(const char *str) { + char buf[1024]; + int r = 0; + while (*str) { + int sc = 0; + char *c; + for (c = buf; c < (buf + sizeof(buf) - 2) && *str && *str != '|'; str++) { + if (*str == '\t') {*c++ = 0; sc = fl_old_shortcut(str);} + else *c++ = *str; + } + *c = 0; + r = add(buf, sc, 0, 0, 0); + if (*str) str++; + } + return r; +} + +void Fl_Menu_::replace(int i, const char *str) { + if (i<0 || i>=size()) return; + if (!alloc) copy(menu_); + if (alloc > 1) { + free((void *)menu_[i].text); + str = strdup(str); + } + menu_[i].text = str; +} + +void Fl_Menu_::remove(int i) { + int n = size(); + if (i<0 || i>=n) return; + if (!alloc) copy(menu_); + // find the next item, skipping submenus: + Fl_Menu_Item* item = menu_+i; + const Fl_Menu_Item* next_item = item->next(); + // delete the text only if all items were created with add(): + if (alloc > 1) { + for (Fl_Menu_Item* m = item; m < next_item; m++) + if (m->text) free((void*)(m->text)); + } + // MRS: "n" is the menu size(), which includes the trailing NULL entry... + memmove(item, next_item, (menu_+n-next_item)*sizeof(Fl_Menu_Item)); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Menu_global.cxx b/Utilities/FLTK/src/Fl_Menu_global.cxx new file mode 100644 index 0000000000..b7cba6faf4 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Menu_global.cxx @@ -0,0 +1,50 @@ +// +// "$Id$" +// +// Global menu shortcut code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Make all the shortcuts in this menu global. +// Currently only one menu at a time and you cannot destruct the menu, +// is this sufficient? + +#include <FL/Fl.H> +#include <FL/Fl_Menu_.H> + +static Fl_Menu_* the_widget; + +static int handler(int e) { + if (e != FL_SHORTCUT || Fl::modal()) return 0; + Fl::first_window(the_widget->window()); + return the_widget->handle(e); +} + +void Fl_Menu_::global() { + if (!the_widget) Fl::add_handler(handler); + the_widget = this; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Multi_Label.cxx b/Utilities/FLTK/src/Fl_Multi_Label.cxx new file mode 100644 index 0000000000..fdf84f3642 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Multi_Label.cxx @@ -0,0 +1,80 @@ +// +// "$Id$" +// +// Multi-label widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Allows two labels to be used on a widget (by having one of them +// be one of these it allows an infinte number!) + +#include <FL/Fl.H> +#include <FL/Fl_Widget.H> +#include <FL/Fl_Menu_Item.H> +#include <FL/Fl_Multi_Label.H> + +static void multi_labeltype( + const Fl_Label* o, int x, int y, int w, int h, Fl_Align a) +{ + Fl_Multi_Label* b = (Fl_Multi_Label*)(o->value); + Fl_Label local = *o; + local.value = b->labela; + local.type = b->typea; + int W = w; int H = h; local.measure(W, H); + local.draw(x,y,w,h,a); + if (a & FL_ALIGN_BOTTOM) h -= H; + else if (a & FL_ALIGN_TOP) {y += H; h -= H;} + else if (a & FL_ALIGN_RIGHT) w -= W; + else if (a & FL_ALIGN_LEFT) {x += W; w -= W;} + else {int d = (h+H)/2; y += d; h -= d;} + local.value = b->labelb; + local.type = b->typeb; + local.draw(x,y,w,h,a); +} + +// measurement is only correct for left-to-right appending... +static void multi_measure(const Fl_Label* o, int& w, int& h) { + Fl_Multi_Label* b = (Fl_Multi_Label*)(o->value); + Fl_Label local = *o; + local.value = b->labela; + local.type = b->typea; + local.measure(w,h); + local.value = b->labelb; + local.type = b->typeb; + int W = 0; int H = 0; local.measure(W,H); + w += W; if (H>h) h = H; +} + +void Fl_Multi_Label::label(Fl_Widget* o) { + Fl::set_labeltype(_FL_MULTI_LABEL, multi_labeltype, multi_measure); + o->label(_FL_MULTI_LABEL, (const char*)this); +} + +void Fl_Multi_Label::label(Fl_Menu_Item* o) { + Fl::set_labeltype(_FL_MULTI_LABEL, multi_labeltype, multi_measure); + o->label(_FL_MULTI_LABEL, (const char*)this); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Overlay_Window.cxx b/Utilities/FLTK/src/Fl_Overlay_Window.cxx new file mode 100644 index 0000000000..d7ea825257 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Overlay_Window.cxx @@ -0,0 +1,156 @@ +// +// "$Id$" +// +// Overlay window code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// A window using double-buffering and able to draw an overlay +// on top of that. Uses the hardware to draw the overlay if +// possible, otherwise it just draws in the front buffer. +#include <FL/Fl.H> +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#include <FL/Fl_Overlay_Window.H> +#include <FL/fl_draw.H> +#include <FL/x.H> + +void Fl_Overlay_Window::show() { + Fl_Double_Window::show(); + if (overlay_ && overlay_ != this) overlay_->show(); +} + +void Fl_Overlay_Window::hide() { + Fl_Double_Window::hide(); +} + +void Fl_Overlay_Window::flush() { +#ifdef BOXX_BUGS + if (overlay_ && overlay_ != this && overlay_->shown()) { + // all drawing to windows hidden by overlay windows is ignored, fix this + XUnmapWindow(fl_display, fl_xid(overlay_)); + Fl_Double_Window::flush(0); + XMapWindow(fl_display, fl_xid(overlay_)); + return; + } +#endif + int erase_overlay = (damage()&FL_DAMAGE_OVERLAY); + clear_damage((uchar)(damage()&~FL_DAMAGE_OVERLAY)); + Fl_Double_Window::flush(erase_overlay); + if (overlay_ == this) draw_overlay(); +} + +void Fl_Overlay_Window::resize(int X, int Y, int W, int H) { + Fl_Double_Window::resize(X,Y,W,H); + if (overlay_ && overlay_!=this) overlay_->resize(0,0,w(),h()); +} + +Fl_Overlay_Window::~Fl_Overlay_Window() { + hide(); +// delete overlay; this is done by ~Fl_Group +} + +#if !HAVE_OVERLAY + +int Fl_Overlay_Window::can_do_overlay() {return 0;} + +void Fl_Overlay_Window::redraw_overlay() { + overlay_ = this; + clear_damage((uchar)(damage()|FL_DAMAGE_OVERLAY)); + Fl::damage(FL_DAMAGE_CHILD); +} + +#else + +extern XVisualInfo *fl_find_overlay_visual(); +extern XVisualInfo *fl_overlay_visual; +extern Colormap fl_overlay_colormap; +extern unsigned long fl_transparent_pixel; +static GC gc; // the GC used by all X windows +extern uchar fl_overlay; // changes how fl_color(x) works + +class _Fl_Overlay : public Fl_Window { + friend class Fl_Overlay_Window; + void flush(); + void show(); +public: + _Fl_Overlay(int x, int y, int w, int h) : + Fl_Window(x,y,w,h) {set_flag(INACTIVE);} +}; + +int Fl_Overlay_Window::can_do_overlay() { + return fl_find_overlay_visual() != 0; +} + +void _Fl_Overlay::show() { + if (shown()) {Fl_Window::show(); return;} + fl_background_pixel = int(fl_transparent_pixel); + Fl_X::make_xid(this, fl_overlay_visual, fl_overlay_colormap); + fl_background_pixel = -1; + // find the outermost window to tell wm about the colormap: + Fl_Window *w = window(); + for (;;) {Fl_Window *w1 = w->window(); if (!w1) break; w = w1;} + XSetWMColormapWindows(fl_display, fl_xid(w), &(Fl_X::i(this)->xid), 1); +} + +void _Fl_Overlay::flush() { + fl_window = fl_xid(this); + if (!gc) gc = XCreateGC(fl_display, fl_xid(this), 0, 0); + fl_gc = gc; + fl_overlay = 1; + Fl_Overlay_Window *w = (Fl_Overlay_Window *)parent(); + Fl_X *myi = Fl_X::i(this); + if (damage() != FL_DAMAGE_EXPOSE) XClearWindow(fl_display, fl_xid(this)); + fl_clip_region(myi->region); myi->region = 0; + w->draw_overlay(); + fl_overlay = 0; +} + +void Fl_Overlay_Window::redraw_overlay() { + if (!fl_display) return; // this prevents fluid -c from opening display + if (!overlay_) { + if (can_do_overlay()) { + Fl_Group::current(this); + overlay_ = new _Fl_Overlay(0,0,w(),h()); + Fl_Group::current(0); + } else { + overlay_ = this; // fake the overlay + } + } + if (shown()) { + if (overlay_ == this) { + clear_damage(damage()|FL_DAMAGE_OVERLAY); + Fl::damage(FL_DAMAGE_CHILD); + } else if (!overlay_->shown()) + overlay_->show(); + else + overlay_->redraw(); + } +} + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_PNG_Image.cxx b/Utilities/FLTK/src/Fl_PNG_Image.cxx new file mode 100644 index 0000000000..8763d17e15 --- /dev/null +++ b/Utilities/FLTK/src/Fl_PNG_Image.cxx @@ -0,0 +1,156 @@ +// +// "$Id$" +// +// Fl_PNG_Image routines. +// +// Copyright 1997-2005 by Easy Software Products. +// Image support donated by Matthias Melcher, Copyright 2000. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +// Contents: +// +// Fl_PNG_Image::Fl_PNG_Image() - Load a PNG image file. +// + +// +// Include necessary header files... +// + +#include <FL/Fl.H> +#include <FL/Fl_PNG_Image.H> +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#include <stdlib.h> + +extern "C" +{ +#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) +# include <zlib.h> +# ifdef HAVE_PNG_H +# include <png.h> +# else +# include <libpng/png.h> +# endif // HAVE_PNG_H +#endif // HAVE_LIBPNG && HAVE_LIBZ +} + + +// +// 'Fl_PNG_Image::Fl_PNG_Image()' - Load a PNG image file. +// + +Fl_PNG_Image::Fl_PNG_Image(const char *png) // I - File to read + : Fl_RGB_Image(0,0,0) { +#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) + int i; // Looping var + FILE *fp; // File pointer + int channels; // Number of color channels + png_structp pp; // PNG read pointer + png_infop info; // PNG info pointers + png_bytep *rows; // PNG row pointers + + + // Open the PNG file... + if ((fp = fopen(png, "rb")) == NULL) return; + + // Setup the PNG data structures... + pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + info = png_create_info_struct(pp); + + if (setjmp(pp->jmpbuf)) + { + Fl::warning("PNG file \"%s\" contains errors!\n", png); + return; + } + + // Initialize the PNG read "engine"... + png_init_io(pp, fp); + + // Get the image dimensions and convert to grayscale or RGB... + png_read_info(pp, info); + + if (info->color_type == PNG_COLOR_TYPE_PALETTE) + png_set_expand(pp); + + if (info->color_type & PNG_COLOR_MASK_COLOR) + channels = 3; + else + channels = 1; + + if ((info->color_type & PNG_COLOR_MASK_ALPHA) || info->num_trans) + channels ++; + + w((int)(info->width)); + h((int)(info->height)); + d(channels); + + if (info->bit_depth < 8) + { + png_set_packing(pp); + png_set_expand(pp); + } + else if (info->bit_depth == 16) + png_set_strip_16(pp); + +# if defined(HAVE_PNG_GET_VALID) && defined(HAVE_PNG_SET_TRNS_TO_ALPHA) + // Handle transparency... + if (png_get_valid(pp, info, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(pp); +# endif // HAVE_PNG_GET_VALID && HAVE_PNG_SET_TRNS_TO_ALPHA + + array = new uchar[w() * h() * d()]; + alloc_array = 1; + + // Allocate pointers... + rows = new png_bytep[h()]; + + for (i = 0; i < h(); i ++) + rows[i] = (png_bytep)(array + i * w() * d()); + + // Read the image, handling interlacing as needed... + for (i = png_set_interlace_handling(pp); i > 0; i --) + png_read_rows(pp, rows, NULL, h()); + +#ifdef WIN32 + // Some Windows graphics drivers don't honor transparency when RGB == white + if (channels == 4) { + // Convert RGB to 0 when alpha == 0... + uchar *ptr = (uchar *)array; + for (i = w() * h(); i > 0; i --, ptr += 4) + if (!ptr[3]) ptr[0] = ptr[1] = ptr[2] = 0; + } +#endif // WIN32 + + // Free memory and return... + delete[] rows; + + png_read_end(pp, info); + png_destroy_read_struct(&pp, &info, NULL); + + fclose(fp); +#endif // HAVE_LIBPNG && HAVE_LIBZ +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_PNM_Image.cxx b/Utilities/FLTK/src/Fl_PNM_Image.cxx new file mode 100644 index 0000000000..fa5b32b626 --- /dev/null +++ b/Utilities/FLTK/src/Fl_PNM_Image.cxx @@ -0,0 +1,182 @@ +// +// "$Id$" +// +// Fl_PNM_Image routines. +// +// Copyright 1997-2005 by Easy Software Products. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +// Contents: +// +// Fl_PNM_Image::Fl_PNM_Image() - Load a PNM image... +// + +// +// Include necessary header files... +// + +#include <FL/Fl.H> +#include <FL/Fl_PNM_Image.H> +#include <stdio.h> +#include <stdlib.h> +#include "flstring.h" + + +// +// 'Fl_PNM_Image::Fl_PNM_Image()' - Load a PNM image... +// + +Fl_PNM_Image::Fl_PNM_Image(const char *name) // I - File to read + : Fl_RGB_Image(0,0,0) { + FILE *fp; // File pointer + int x, y; // Looping vars + char line[1024], // Input line + *lineptr; // Pointer in line + uchar *ptr, // Pointer to pixel values + byte, // Byte from file + bit; // Bit in pixel + int format, // Format of PNM file + val, // Pixel value + maxval; // Maximum pixel value + + + if ((fp = fopen(name, "rb")) == NULL) return; + + // + // Read the file header in the format: + // + // Pformat + // # comment1 + // # comment2 + // ... + // # commentN + // width + // height + // max sample + // + + lineptr = fgets(line, sizeof(line), fp); + if (!lineptr) { + fclose(fp); + Fl::error("Early end-of-file in PNM file \"%s\"!", name); + return; + } + + lineptr ++; + + format = atoi(lineptr); + while (isdigit(*lineptr)) lineptr ++; + + if (format == 7) lineptr = (char *)""; + + while (lineptr != NULL && w() == 0) { + if (*lineptr == '\0' || *lineptr == '#') { + lineptr = fgets(line, sizeof(line), fp); + } else if (isdigit(*lineptr)) { + w(strtol(lineptr, &lineptr, 10)); + } else lineptr ++; + } + + while (lineptr != NULL && h() == 0) { + if (*lineptr == '\0' || *lineptr == '#') { + lineptr = fgets(line, sizeof(line), fp); + } else if (isdigit(*lineptr)) { + h(strtol(lineptr, &lineptr, 10)); + } else lineptr ++; + } + + if (format != 1 && format != 4) { + maxval = 0; + + while (lineptr != NULL && maxval == 0) { + if (*lineptr == '\0' || *lineptr == '#') { + lineptr = fgets(line, sizeof(line), fp); + } else if (isdigit(*lineptr)) { + maxval = strtol(lineptr, &lineptr, 10); + } else lineptr ++; + } + } else maxval = 1; + + // Allocate memory... + if (format == 1 || format == 2 || format == 4 || format == 5) d(1); + else d(3); + +// printf("%s = %dx%dx%d\n", name, w(), h(), d()); + + array = new uchar[w() * h() * d()]; + alloc_array = 1; + + // Read the image file... + for (y = 0; y < h(); y ++) { + ptr = (uchar *)array + y * w() * d(); + + switch (format) { + case 1 : + case 2 : + for (x = w(); x > 0; x --) + if (fscanf(fp, "%d", &val) == 1) *ptr++ = (uchar)(255 * val / maxval); + break; + + case 3 : + for (x = w(); x > 0; x --) { + if (fscanf(fp, "%d", &val) == 1) *ptr++ = (uchar)(255 * val / maxval); + if (fscanf(fp, "%d", &val) == 1) *ptr++ = (uchar)(255 * val / maxval); + if (fscanf(fp, "%d", &val) == 1) *ptr++ = (uchar)(255 * val / maxval); + } + break; + + case 4 : + for (x = w(), byte = (uchar)getc(fp), bit = 128; x > 0; x --) { + if (byte & bit) *ptr++ = 255; + else *ptr++ = 0; + + if (bit > 1) bit >>= 1; + else { + bit = 128; + byte = (uchar)getc(fp); + } + } + break; + + case 5 : + case 6 : + fread(ptr, w(), d(), fp); + break; + + case 7 : /* XV 3:3:2 thumbnail format */ + for (x = w(); x > 0; x --) { + byte = (uchar)getc(fp); + + *ptr++ = (uchar)(255 * ((byte >> 5) & 7) / 7); + *ptr++ = (uchar)(255 * ((byte >> 2) & 7) / 7); + *ptr++ = (uchar)(255 * (byte & 3) / 3); + } + break; + } + } + + fclose(fp); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Pack.cxx b/Utilities/FLTK/src/Fl_Pack.cxx new file mode 100644 index 0000000000..e82fd19a11 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Pack.cxx @@ -0,0 +1,147 @@ +// +// "$Id$" +// +// Packing widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Based on code by Curtis Edwards +// Group that compresses all it's children together and resizes to surround +// them on each redraw (only if box() is zero) +// Bugs: ? + +#include <FL/Fl.H> +#include <FL/Fl_Pack.H> +#include <FL/fl_draw.H> + +Fl_Pack::Fl_Pack(int X, int Y, int W, int H,const char *l) +: Fl_Group(X, Y, W, H, l) { + resizable(0); + spacing_ = 0; + // type(VERTICAL); // already set like this +} + +void Fl_Pack::draw() { + int tx = x()+Fl::box_dx(box()); + int ty = y()+Fl::box_dy(box()); + int tw = w()-Fl::box_dw(box()); + int th = h()-Fl::box_dh(box()); + int rw, rh; + int current_position = (horizontal() ? tx : ty) + spacing_ / 2; + int maximum_position = current_position; + uchar d = damage(); + Fl_Widget*const* a = array(); + if (horizontal()) { + rw = -spacing_; + rh = th; + + for (int i = children(); i--;) + if (child(i)->visible()) { + if (child(i) != this->resizable()) rw += child(i)->w(); + rw += spacing_; + } + } else { + rw = tw; + rh = -spacing_; + + for (int i = children(); i--;) + if (child(i)->visible()) { + if (child(i) != this->resizable()) rh += child(i)->h(); + rh += spacing_; + } + } + for (int i = children(); i--;) { + Fl_Widget* o = *a++; + if (o->visible()) { + int X,Y,W,H; + if (horizontal()) { + X = current_position; + W = o->w(); + Y = ty; + H = th; + } else { + X = tx; + W = tw; + Y = current_position; + H = o->h(); + } + // Last child, if resizable, takes all remaining room + if(i == 0 && o == this->resizable()) { + if(horizontal()) + W = tw - rw; + else + H = th - rh; + } + if (spacing_ && current_position>maximum_position && box() && + (X != o->x() || Y != o->y() || d&FL_DAMAGE_ALL)) { + fl_color(color()); + if (horizontal()) + fl_rectf(maximum_position, ty, spacing_, th); + else + fl_rectf(tx, maximum_position, tw, spacing_); + } + if (X != o->x() || Y != o->y() || W != o->w() || H != o->h()) { + o->resize(X,Y,W,H); + o->clear_damage(FL_DAMAGE_ALL); + } + if (d&FL_DAMAGE_ALL) { + draw_child(*o); + draw_outside_label(*o); + } else update_child(*o); + // child's draw() can change it's size, so use new size: + current_position += (horizontal() ? o->w() : o->h()); + if (current_position > maximum_position) + maximum_position = current_position; + current_position += spacing_; + } + } + + if (horizontal()) { + if (maximum_position < tx+tw && box()) { + fl_color(color()); + fl_rectf(maximum_position, ty, tx+tw-maximum_position, th); + } + tw = maximum_position-tx; + } else { + if (maximum_position < ty+th && box()) { + fl_color(color()); + fl_rectf(tx, maximum_position, tw, ty+th-maximum_position); + } + th = maximum_position-ty; + } + + tw += Fl::box_dw(box()); if (tw <= 0) tw = 1; + th += Fl::box_dh(box()); if (th <= 0) th = 1; + if (tw != w() || th != h()) { + Fl_Widget::resize(x(),y(),tw,th); + d = FL_DAMAGE_ALL; + } + if (d&FL_DAMAGE_ALL) { + draw_box(); + draw_label(); + } +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Pixmap.cxx b/Utilities/FLTK/src/Fl_Pixmap.cxx new file mode 100644 index 0000000000..a3fad728a6 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Pixmap.cxx @@ -0,0 +1,495 @@ +// +// "$Id$" +// +// Pixmap drawing code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Draws X pixmap data, keeping it stashed in a server pixmap so it +// redraws fast. + +// See fl_draw_pixmap.cxx for code used to get the actual data into pixmap. +// Implemented without using the xpm library (which I can't use because +// it interferes with the color cube used by fl_draw_image). + +#include <FL/Fl.H> +#include <FL/fl_draw.H> +#include <FL/x.H> +#include <FL/Fl_Widget.H> +#include <FL/Fl_Menu_Item.H> +#include <FL/Fl_Pixmap.H> + +#include <stdio.h> +#include "flstring.h" +#include <ctype.h> + +#ifdef WIN32 +extern void fl_release_dc(HWND, HDC); // located in Fl_win32.cxx +#endif + +#ifdef __APPLE_QUARTZ__ +extern Fl_Offscreen fl_create_offscreen_with_alpha(int w, int h); +#endif + +extern uchar **fl_mask_bitmap; // used by fl_draw_pixmap.cxx to store mask +void fl_restore_clip(); // in fl_rect.cxx + +void Fl_Pixmap::measure() { + int W, H; + + // ignore empty or bad pixmap data: + if (w()<0 && data()) { + fl_measure_pixmap(data(), W, H); + w(W); h(H); + } +} + +void Fl_Pixmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) { + // ignore empty or bad pixmap data: + if (!data()) { + draw_empty(XP, YP); + return; + } + if (w()<0) measure(); + if (WP==-1) { + WP = w(); + HP = h(); + } + if (!w()) { + draw_empty(XP, YP); + return; + } + // account for current clip region (faster on Irix): + int X,Y,W,H; fl_clip_box(XP,YP,WP,HP,X,Y,W,H); + cx += X-XP; cy += Y-YP; + // clip the box down to the size of image, quit if empty: + if (cx < 0) {W += cx; X -= cx; cx = 0;} + if (cx+W > w()) W = w()-cx; + if (W <= 0) return; + if (cy < 0) {H += cy; Y -= cy; cy = 0;} + if (cy+H > h()) H = h()-cy; + if (H <= 0) return; + if (!id) { +#ifdef __APPLE_QUARTZ__ + id = fl_create_offscreen_with_alpha(w(), h()); + fl_begin_offscreen((Fl_Offscreen)id); + fl_draw_pixmap(data(), 0, 0, FL_GREEN); + fl_end_offscreen(); +#else + id = fl_create_offscreen(w(), h()); + fl_begin_offscreen((Fl_Offscreen)id); + uchar *bitmap = 0; + fl_mask_bitmap = &bitmap; + fl_draw_pixmap(data(), 0, 0, FL_BLACK); + fl_mask_bitmap = 0; + if (bitmap) { + mask = fl_create_bitmask(w(), h(), bitmap); + delete[] bitmap; + } + fl_end_offscreen(); +#endif + } +#ifdef WIN32 + if (mask) { + HDC new_gc = CreateCompatibleDC(fl_gc); + int save = SaveDC(new_gc); + SelectObject(new_gc, (void*)mask); + BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCAND); + SelectObject(new_gc, (void*)id); + BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCPAINT); + RestoreDC(new_gc,save); + DeleteDC(new_gc); + } else { + fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id, cx, cy); + } +#elif defined(__APPLE_QD__) + if (mask) { + Rect src, dst; + src.left = cx; src.right = cx+W; + src.top = cy; src.bottom = cy+H; + dst.left = X; dst.right = X+W; + dst.top = Y; dst.bottom = Y+H; + RGBColor rgb, oldfg, oldbg; + GetForeColor(&oldfg); + GetBackColor(&oldbg); + rgb.red = 0xffff; rgb.green = 0xffff; rgb.blue = 0xffff; + RGBBackColor(&rgb); + rgb.red = 0x0000; rgb.green = 0x0000; rgb.blue = 0x0000; + RGBForeColor(&rgb); + CopyMask(GetPortBitMapForCopyBits((GrafPtr)id), + GetPortBitMapForCopyBits((GrafPtr)mask), + GetPortBitMapForCopyBits(GetWindowPort(fl_window)), + &src, &src, &dst); + RGBBackColor(&oldbg); + RGBForeColor(&oldfg); + } else { + fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id, cx, cy); + } +#elif defined(__APPLE_QUARTZ__) + fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id, cx, cy); +#else + if (mask) { + // I can't figure out how to combine a mask with existing region, + // so cut the image down to a clipped rectangle: + int nx, ny; fl_clip_box(X,Y,W,H,nx,ny,W,H); + cx += nx-X; X = nx; + cy += ny-Y; Y = ny; + // make X use the bitmap as a mask: + XSetClipMask(fl_display, fl_gc, mask); + int ox = X-cx; if (ox < 0) ox += w(); + int oy = Y-cy; if (oy < 0) oy += h(); + XSetClipOrigin(fl_display, fl_gc, X-cx, Y-cy); + } + fl_copy_offscreen(X, Y, W, H, id, cx, cy); + if (mask) { + // put the old clip region back + XSetClipOrigin(fl_display, fl_gc, 0, 0); + fl_restore_clip(); + } +#endif +} + +Fl_Pixmap::~Fl_Pixmap() { + uncache(); + delete_data(); +} + +void Fl_Pixmap::uncache() { + if (id) { + fl_delete_offscreen((Fl_Offscreen)id); + id = 0; + } + + if (mask) { + fl_delete_bitmask((Fl_Bitmask)mask); + mask = 0; + } +} + +void Fl_Pixmap::label(Fl_Widget* widget) { + widget->image(this); +} + +void Fl_Pixmap::label(Fl_Menu_Item* m) { + Fl::set_labeltype(_FL_IMAGE_LABEL, labeltype, Fl_Image::measure); + m->label(_FL_IMAGE_LABEL, (const char*)this); +} + +void Fl_Pixmap::copy_data() { + if (alloc_data) return; + + char **new_data, // New data array + **new_row; // Current row in image + int i, // Looping var + ncolors, // Number of colors in image + chars_per_pixel,// Characters per color + chars_per_line; // Characters per line + + // Figure out how many colors there are, and how big they are... + sscanf(data()[0],"%*d%*d%d%d", &ncolors, &chars_per_pixel); + chars_per_line = chars_per_pixel * w() + 1; + + // Allocate memory for the new array... + if (ncolors < 0) new_data = new char *[h() + 2]; + else new_data = new char *[h() + ncolors + 1]; + + new_data[0] = new char[strlen(data()[0]) + 1]; + strcpy(new_data[0], data()[0]); + + // Copy colors... + if (ncolors < 0) { + // Copy FLTK colormap values... + ncolors = -ncolors; + new_row = new_data + 1; + *new_row = new char[ncolors * 4]; + memcpy(*new_row, data()[1], ncolors * 4); + ncolors = 1; + new_row ++; + } else { + // Copy standard XPM colormap values... + for (i = 0, new_row = new_data + 1; i < ncolors; i ++, new_row ++) { + *new_row = new char[strlen(data()[i + 1]) + 1]; + strcpy(*new_row, data()[i + 1]); + } + } + + // Copy image data... + for (i = 0; i < h(); i ++, new_row ++) { + *new_row = new char[chars_per_line]; + memcpy(*new_row, data()[i + ncolors + 1], chars_per_line); + } + + // Update pointers... + data((const char **)new_data, h() + ncolors + 1); + alloc_data = 1; +} + +Fl_Image *Fl_Pixmap::copy(int W, int H) { + Fl_Pixmap *new_image; // New pixmap + + // Optimize the simple copy where the width and height are the same... + if (W == w() && H == h()) { + // Make an exact copy of the image and return it... + new_image = new Fl_Pixmap(data()); + new_image->copy_data(); + return new_image; + } + if (W <= 0 || H <= 0) return 0; + + // OK, need to resize the image data; allocate memory and + char **new_data, // New array for image data + **new_row, // Pointer to row in image data + *new_ptr, // Pointer into new array + new_info[255]; // New information line + const char *old_ptr; // Pointer into old array + int i, // Looping var + c, // Channel number + sy, // Source coordinate + dx, dy, // Destination coordinates + xerr, yerr, // X & Y errors + xmod, ymod, // X & Y moduli + xstep, ystep; // X & Y step increments + int ncolors, // Number of colors in image + chars_per_pixel,// Characters per color + chars_per_line; // Characters per line + + // Figure out how many colors there are, and how big they are... + sscanf(data()[0],"%*d%*d%d%d", &ncolors, &chars_per_pixel); + chars_per_line = chars_per_pixel * W + 1; + + sprintf(new_info, "%d %d %d %d", W, H, ncolors, chars_per_pixel); + + // Figure out Bresenheim step/modulus values... + xmod = w() % W; + xstep = (w() / W) * chars_per_pixel; + ymod = h() % H; + ystep = h() / H; + + // Allocate memory for the new array... + if (ncolors < 0) new_data = new char *[H + 2]; + else new_data = new char *[H + ncolors + 1]; + new_data[0] = new char[strlen(new_info) + 1]; + strcpy(new_data[0], new_info); + + // Copy colors... + if (ncolors < 0) { + // Copy FLTK colormap values... + ncolors = -ncolors; + new_row = new_data + 1; + *new_row = new char[ncolors * 4]; + memcpy(*new_row, data()[1], ncolors * 4); + ncolors = 1; + new_row ++; + } else { + // Copy standard XPM colormap values... + for (i = 0, new_row = new_data + 1; i < ncolors; i ++, new_row ++) { + *new_row = new char[strlen(data()[i + 1]) + 1]; + strcpy(*new_row, data()[i + 1]); + } + } + + // Scale the image using a nearest-neighbor algorithm... + for (dy = H, sy = 0, yerr = H; dy > 0; dy --, new_row ++) { + *new_row = new char[chars_per_line]; + new_ptr = *new_row; + + for (dx = W, xerr = W, old_ptr = data()[sy + ncolors + 1]; + dx > 0; + dx --) { + for (c = 0; c < chars_per_pixel; c ++) *new_ptr++ = old_ptr[c]; + + old_ptr += xstep; + xerr -= xmod; + + if (xerr <= 0) { + xerr += W; + old_ptr += chars_per_pixel; + } + } + + *new_ptr = '\0'; + sy += ystep; + yerr -= ymod; + if (yerr <= 0) { + yerr += H; + sy ++; + } + } + + new_image = new Fl_Pixmap((char*const*)new_data); + new_image->alloc_data = 1; + + return new_image; +} + +void Fl_Pixmap::color_average(Fl_Color c, float i) { + // Delete any existing pixmap/mask objects... + uncache(); + + // Allocate memory as needed... + copy_data(); + + // Get the color to blend with... + uchar r, g, b; + unsigned ia, ir, ig, ib; + + Fl::get_color(c, r, g, b); + if (i < 0.0f) i = 0.0f; + else if (i > 1.0f) i = 1.0f; + + ia = (unsigned)(256 * i); + ir = r * (256 - ia); + ig = g * (256 - ia); + ib = b * (256 - ia); + + // Update the colormap to do the blend... + char line[255]; // New colormap line + int color, // Looping var + ncolors, // Number of colors in image + chars_per_pixel;// Characters per color + + + sscanf(data()[0],"%*d%*d%d%d", &ncolors, &chars_per_pixel); + + if (ncolors < 0) { + // Update FLTK colormap... + ncolors = -ncolors; + uchar *cmap = (uchar *)(data()[1]); + for (color = 0; color < ncolors; color ++, cmap += 4) { + cmap[1] = (ia * cmap[1] + ir) >> 8; + cmap[2] = (ia * cmap[2] + ig) >> 8; + cmap[3] = (ia * cmap[3] + ib) >> 8; + } + } else { + // Update standard XPM colormap... + for (color = 0; color < ncolors; color ++) { + // look for "c word", or last word if none: + const char *p = data()[color + 1] + chars_per_pixel + 1; + const char *previous_word = p; + for (;;) { + while (*p && isspace(*p)) p++; + char what = *p++; + while (*p && !isspace(*p)) p++; + while (*p && isspace(*p)) p++; + if (!*p) {p = previous_word; break;} + if (what == 'c') break; + previous_word = p; + while (*p && !isspace(*p)) p++; + } + + if (fl_parse_color(p, r, g, b)) { + r = (ia * r + ir) >> 8; + g = (ia * g + ig) >> 8; + b = (ia * b + ib) >> 8; + + if (chars_per_pixel > 1) sprintf(line, "%c%c c #%02X%02X%02X", + data()[color + 1][0], + data()[color + 1][1], r, g, b); + else sprintf(line, "%c c #%02X%02X%02X", data()[color + 1][0], r, g, b); + + delete[] (char *)data()[color + 1]; + ((char **)data())[color + 1] = new char[strlen(line) + 1]; + strcpy((char *)data()[color + 1], line); + } + } + } +} + +void Fl_Pixmap::delete_data() { + if (alloc_data) { + for (int i = 0; i < count(); i ++) delete[] (char *)data()[i]; + delete[] (char **)data(); + } +} + +void Fl_Pixmap::set_data(const char * const * p) { + int height, // Number of lines in image + ncolors; // Number of colors in image + + if (p) { + sscanf(p[0],"%*d%d%d", &height, &ncolors); + if (ncolors < 0) data(p, height + 2); + else data(p, height + ncolors + 1); + } +} + + +void Fl_Pixmap::desaturate() { + // Delete any existing pixmap/mask objects... + uncache(); + + // Allocate memory as needed... + copy_data(); + + // Update the colormap to grayscale... + char line[255]; // New colormap line + int i, // Looping var + ncolors, // Number of colors in image + chars_per_pixel;// Characters per color + uchar r, g, b; + + sscanf(data()[0],"%*d%*d%d%d", &ncolors, &chars_per_pixel); + + if (ncolors < 0) { + // Update FLTK colormap... + ncolors = -ncolors; + uchar *cmap = (uchar *)(data()[1]); + for (i = 0; i < ncolors; i ++, cmap += 4) { + g = (uchar)((cmap[1] * 31 + cmap[2] * 61 + cmap[3] * 8) / 100); + cmap[1] = cmap[2] = cmap[3] = g; + } + } else { + // Update standard XPM colormap... + for (i = 0; i < ncolors; i ++) { + // look for "c word", or last word if none: + const char *p = data()[i + 1] + chars_per_pixel + 1; + const char *previous_word = p; + for (;;) { + while (*p && isspace(*p)) p++; + char what = *p++; + while (*p && !isspace(*p)) p++; + while (*p && isspace(*p)) p++; + if (!*p) {p = previous_word; break;} + if (what == 'c') break; + previous_word = p; + while (*p && !isspace(*p)) p++; + } + + if (fl_parse_color(p, r, g, b)) { + g = (uchar)((r * 31 + g * 61 + b * 8) / 100); + + if (chars_per_pixel > 1) sprintf(line, "%c%c c #%02X%02X%02X", data()[i + 1][0], + data()[i + 1][1], g, g, g); + else sprintf(line, "%c c #%02X%02X%02X", data()[i + 1][0], g, g, g); + + delete[] (char *)data()[i + 1]; + ((char **)data())[i + 1] = new char[strlen(line) + 1]; + strcpy((char *)data()[i + 1], line); + } + } + } +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Positioner.cxx b/Utilities/FLTK/src/Fl_Positioner.cxx new file mode 100644 index 0000000000..205ddffc7a --- /dev/null +++ b/Utilities/FLTK/src/Fl_Positioner.cxx @@ -0,0 +1,147 @@ +// +// "$Id$" +// +// Positioner widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// The positioner widget from Forms, gives 2D input +// Written by: Mark Overmars + +#include <FL/Fl.H> +#include <FL/Fl_Positioner.H> +#include <FL/fl_draw.H> + +static double flinear(double val, double smin, double smax, double gmin, double gmax) +{ + if (smin == smax) return gmax; + else return gmin + (gmax - gmin) * (val - smin) / (smax - smin); +} + +void Fl_Positioner::draw(int X, int Y, int W, int H) { + int x1 = X + 4; + int y1 = Y + 4; + int w1 = W - 2 * 4; + int h1 = H - 2 * 4; + int xx = int(flinear(xvalue(), xmin, xmax, x1, x1+w1-1)+.5); + int yy = int(flinear(yvalue(), ymin, ymax, y1, y1+h1-1)+.5); + draw_box(box(), X, Y, W, H, color()); + fl_color(selection_color()); + fl_xyline(x1, yy, x1+w1); + fl_yxline(xx, y1, y1+h1); +} + +void Fl_Positioner::draw() { + draw(x(), y(), w(), h()); + draw_label(); +} + +int Fl_Positioner::value(double X, double Y) { + clear_changed(); + if (X == xvalue_ && Y == yvalue_) return 0; + xvalue_ = X; yvalue_ = Y; + redraw(); + return 1; +} + +int Fl_Positioner::xvalue(double X) { + return(value(X, yvalue_)); +} + +int Fl_Positioner::yvalue(double Y) { + return(value(xvalue_, Y)); +} + +int Fl_Positioner::handle(int event, int X, int Y, int W, int H) { + switch (event) { + case FL_PUSH: + case FL_DRAG: + case FL_RELEASE: { + double x1 = X + 4; + double y1 = Y + 4; + double w1 = W - 2 * 4; + double h1 = H - 2 * 4; + double xx = flinear(Fl::event_x(), x1, x1+w1-1.0, xmin, xmax); + if (xstep_) xx = int(xx/xstep_+0.5) * xstep_; + if (xmin < xmax) { + if (xx < xmin) xx = xmin; + if (xx > xmax) xx = xmax; + } else { + if (xx > xmin) xx = xmin; + if (xx < xmax) xx = xmax; + } + double yy = flinear(Fl::event_y(), y1, y1+h1-1.0, ymin, ymax); + if (ystep_) yy = int(yy/ystep_+0.5) * ystep_; + if (ymin < ymax) { + if (yy < ymin) yy = ymin; + if (yy > ymax) yy = ymax; + } else { + if (yy > ymin) yy = ymin; + if (yy < ymax) yy = ymax; + } + if (value(xx, yy)) set_changed();} + if (!(when() & FL_WHEN_CHANGED || + (when() & FL_WHEN_RELEASE && event == FL_RELEASE))) return 1; + if (changed() || when()&FL_WHEN_NOT_CHANGED) { + if (event == FL_RELEASE) clear_changed(); + do_callback(); + } + return 1; + default: + return 0; + } +} + +int Fl_Positioner::handle(int e) { + return handle(e, x(), y(), w(), h()); +} + +Fl_Positioner::Fl_Positioner(int X, int Y, int W, int H, const char* l) +: Fl_Widget(X, Y, W, H, l) { + box(FL_DOWN_BOX); + selection_color(FL_RED); + align(FL_ALIGN_BOTTOM); + when(FL_WHEN_CHANGED); + xmin = ymin = 0; + xmax = ymax = 1; + xvalue_ = yvalue_ = .5; + xstep_ = ystep_ = 0; +} + +void Fl_Positioner::xbounds(double a, double b) { + if (a != xmin || b != xmax) { + xmin = a; xmax = b; + redraw(); + } +} + +void Fl_Positioner::ybounds(double a, double b) { + if (a != ymin || b != ymax) { + ymin = a; ymax = b; + redraw(); + } +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Preferences.cxx b/Utilities/FLTK/src/Fl_Preferences.cxx new file mode 100644 index 0000000000..98321d28a7 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Preferences.cxx @@ -0,0 +1,1127 @@ +// +// "$Id$" +// +// Preferences methods for the Fast Light Tool Kit (FLTK). +// +// Copyright 2002-2005 by Matthias Melcher. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + + +#include <FL/Fl.H> +#include <FL/Fl_Preferences.H> +#include <FL/filename.H> + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include "flstring.h" +#include <sys/stat.h> + +#if defined(WIN32) && !defined(__CYGWIN__) +# include <direct.h> +# include <io.h> +// Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs +// on Windows, which is supposed to be POSIX compliant... +# define access _access +# define mkdir _mkdir +#elif defined (__APPLE__) +# include <Carbon/Carbon.h> +# include <unistd.h> +#else +# include <unistd.h> +#endif + + +char Fl_Preferences::nameBuffer[128]; + + +/** + * create the initial preferences base + * - root: machine or user preferences + * - vendor: unique identification of author or vendor of application + * Must be a valid directory name. + * - application: vendor unique application name, i.e. "PreferencesTest" + * multiple preferences files can be created per application. + * Must be a valid file name. + * example: Fl_Preferences base( Fl_Preferences::USER, "fltk.org", "test01"); + */ +Fl_Preferences::Fl_Preferences( Root root, const char *vendor, const char *application ) +{ + node = new Node( "." ); + rootNode = new RootNode( this, root, vendor, application ); +} + + +/** + * create the initial preferences base + * - path: an application-supplied path + * example: Fl_Preferences base( "/usr/foo" ); + */ +Fl_Preferences::Fl_Preferences( const char *path, const char *vendor, const char *application ) +{ + node = new Node( "." ); + rootNode = new RootNode( this, path, vendor, application ); +} + + +/** + * create a Preferences node in relation to a parent node for reading and writing + * - parent: base name for group + * - group: group name (can contain '/' seperated group names) + * example: Fl_Preferences colors( base, "setup/colors" ); + */ +Fl_Preferences::Fl_Preferences( Fl_Preferences &parent, const char *key ) +{ + rootNode = parent.rootNode; + node = parent.node->addChild( key ); +} + + +/** + * create a Preferences node in relation to a parent node for reading and writing + * - parent: base name for group + * - group: group name (can contain '/' seperated group names) + * example: Fl_Preferences colors( base, "setup/colors" ); + */ +Fl_Preferences::Fl_Preferences( Fl_Preferences *parent, const char *key ) +{ + rootNode = parent->rootNode; + node = parent->node->addChild( key ); +} + + +/** + * destroy individual keys + * - destroying the base preferences will flush changes to the prefs file + * - after destroying the base, none of the depending preferences must be read or written + */ +Fl_Preferences::~Fl_Preferences() +{ + if (!node->parent()) delete rootNode; + // DO NOT delete nodes! The root node will do that after writing the preferences +} + + +/** + * return the number of groups that are contained within a group + * example: int n = base.groups(); + */ +int Fl_Preferences::groups() +{ + return node->nChildren(); +} + + +/** + * return the group name of the n'th group + * - there is no guaranteed order of group names + * - the index must be within the range given by groups() + * example: printf( "Group(%d)='%s'\n", ix, base.group(ix) ); + */ +const char *Fl_Preferences::group( int ix ) +{ + return node->child( ix ); +} + + +/** + * return 1, if a group with this name exists + * example: if ( base.groupExists( "setup/colors" ) ) ... + */ +char Fl_Preferences::groupExists( const char *key ) +{ + return node->search( key ) ? 1 : 0 ; +} + + +/** + * delete a group + * example: setup.deleteGroup( "colors/buttons" ); + */ +char Fl_Preferences::deleteGroup( const char *key ) +{ + Node *nd = node->search( key ); + if ( nd ) return nd->remove(); + return 0; +} + + +/** + * return the number of entries (name/value) pairs for a group + * example: int n = buttonColor.entries(); + */ +int Fl_Preferences::entries() +{ + return node->nEntry; +} + + +/** + * return the name of an entry + * - there is no guaranteed order of entry names + * - the index must be within the range given by entries() + * example: printf( "Entry(%d)='%s'\n", ix, buttonColor.entry(ix) ); + */ +const char *Fl_Preferences::entry( int ix ) +{ + return node->entry[ix].name; +} + + +/** + * return 1, if an entry with this name exists + * example: if ( buttonColor.entryExists( "red" ) ) ... + */ +char Fl_Preferences::entryExists( const char *key ) +{ + return node->getEntry( key )>=0 ? 1 : 0 ; +} + + +/** + * remove a single entry (name/value pair) + * example: buttonColor.deleteEntry( "red" ); + */ +char Fl_Preferences::deleteEntry( const char *key ) +{ + return node->deleteEntry( key ); +} + + +/** + * read an entry from the group + */ +char Fl_Preferences::get( const char *key, int &value, int defaultValue ) +{ + const char *v = node->get( key ); + value = v ? atoi( v ) : defaultValue; + return ( v != 0 ); +} + + +/** + * set an entry (name/value pair) + */ +char Fl_Preferences::set( const char *key, int value ) +{ + sprintf( nameBuffer, "%d", value ); + node->set( key, nameBuffer ); + return 1; +} + + +/** + * read an entry from the group + */ +char Fl_Preferences::get( const char *key, float &value, float defaultValue ) +{ + const char *v = node->get( key ); + value = v ? (float)atof( v ) : defaultValue; + return ( v != 0 ); +} + + +/** + * set an entry (name/value pair) + */ +char Fl_Preferences::set( const char *key, float value ) +{ + sprintf( nameBuffer, "%g", value ); + node->set( key, nameBuffer ); + return 1; +} + + +/** + * read an entry from the group + */ +char Fl_Preferences::get( const char *key, double &value, double defaultValue ) +{ + const char *v = node->get( key ); + value = v ? atof( v ) : defaultValue; + return ( v != 0 ); +} + + +/** + * set an entry (name/value pair) + */ +char Fl_Preferences::set( const char *key, double value ) +{ + sprintf( nameBuffer, "%g", value ); + node->set( key, nameBuffer ); + return 1; +} + + +// remove control sequences from a string +static char *decodeText( const char *src ) +{ + int len = 0; + const char *s = src; + for ( ; *s; s++, len++ ) + { + if ( *s == '\\' ) + if ( isdigit( s[1] ) ) s+=3; else s+=1; + } + char *dst = (char*)malloc( len+1 ), *d = dst; + for ( s = src; *s; s++ ) + { + char c = *s; + if ( c == '\\' ) + { + if ( s[1] == '\\' ) { *d++ = c; s++; } + else if ( s[1] == 'n' ) { *d++ = '\n'; s++; } + else if ( s[1] == 'r' ) { *d++ = '\r'; s++; } + else if ( isdigit( s[1] ) ) { *d++ = ((s[1]-'0')<<6) + ((s[2]-'0')<<3) + (s[3]-'0'); s+=3; } + else s++; // error + } + else + *d++ = c; + } + *d = 0; + return dst; +} + + +/** + * read a text entry from the group + * the text will be moved into the given text buffer + * text will be clipped to the buffer size + */ +char Fl_Preferences::get( const char *key, char *text, const char *defaultValue, int maxSize ) +{ + const char *v = node->get( key ); + if ( v && strchr( v, '\\' ) ) { + char *w = decodeText( v ); + strlcpy(text, w, maxSize); + free( w ); + return 1; + } + if ( !v ) v = defaultValue; + if ( v ) strlcpy(text, v, maxSize); + else text = 0; + return ( v != defaultValue ); +} + + +/** + * read a text entry from the group + * 'text' will be changed to point to a new text buffer + * the text buffer must be deleted with 'free(text)' by the user. + */ +char Fl_Preferences::get( const char *key, char *&text, const char *defaultValue ) +{ + const char *v = node->get( key ); + if ( v && strchr( v, '\\' ) ) + { + text = decodeText( v ); + return 1; + } + if ( !v ) v = defaultValue; + if ( v ) + text = strdup( v ); + else + text = 0; + return ( v != defaultValue ); +} + + +/** + * set an entry (name/value pair) + */ +char Fl_Preferences::set( const char *key, const char *text ) +{ + const char *s = text; + int n=0, ns=0; + for ( ; *s; s++ ) { n++; if ( *s<32 || *s=='\\' || *s==0x7f ) ns+=4; } + if ( ns ) + { + char *buffer = (char*)malloc( n+ns+1 ), *d = buffer; + for ( s=text; *s; ) + { + char c = *s; + if ( c=='\\' ) { *d++ = '\\'; *d++ = '\\'; s++; } + else if ( c=='\n' ) { *d++ = '\\'; *d++ = 'n'; s++; } + else if ( c=='\r' ) { *d++ = '\\'; *d++ = 'r'; s++; } + else if ( c<32 || c==0x7f ) + { *d++ = '\\'; *d++ = '0'+((c>>6)&3); *d++ = '0'+((c>>3)&7); *d++ = '0'+(c&7); s++; } + else *d++ = *s++; + } + *d = 0; + node->set( key, buffer ); + free( buffer ); + } + else + node->set( key, text ); + return 1; +} + + +// convert a hex string to binary data +static void *decodeHex( const char *src, int &size ) +{ + size = strlen( src )/2; + unsigned char *data = (unsigned char*)malloc( size ), *d = data; + const char *s = src; + int i; + + for ( i=size; i>0; i-- ) + { + int v; + char x = tolower(*s++); + if ( x >= 'a' ) v = x-'a'+10; else v = x-'0'; + v = v<<4; + x = tolower(*s++); + if ( x >= 'a' ) v += x-'a'+10; else v += x-'0'; + *d++ = (uchar)v; + } + + return (void*)data; +} + + +/** + * read a binary entry from the group + * the data will be moved into the given destination buffer + * data will be clipped to the buffer size + */ +char Fl_Preferences::get( const char *key, void *data, const void *defaultValue, int defaultSize, int maxSize ) +{ + const char *v = node->get( key ); + if ( v ) + { + int dsize; + void *w = decodeHex( v, dsize ); + memmove( data, w, dsize>maxSize?maxSize:dsize ); + free( w ); + return 1; + } + if ( defaultValue ) + memmove( data, defaultValue, defaultSize>maxSize?maxSize:defaultSize ); + return 0; +} + + +/** + * read a binary entry from the group + * 'data' will be changed to point to a new data buffer + * the data buffer must be deleted with 'free(data)' by the user. + */ +char Fl_Preferences::get( const char *key, void *&data, const void *defaultValue, int defaultSize ) +{ + const char *v = node->get( key ); + if ( v ) + { + int dsize; + data = decodeHex( v, dsize ); + return 1; + } + if ( defaultValue ) + { + data = (void*)malloc( defaultSize ); + memmove( data, defaultValue, defaultSize ); + } + else + data = 0; + return 0; +} + + +/** + * set an entry (name/value pair) + */ +char Fl_Preferences::set( const char *key, const void *data, int dsize ) +{ + char *buffer = (char*)malloc( dsize*2+1 ), *d = buffer;; + unsigned char *s = (unsigned char*)data; + for ( ; dsize>0; dsize-- ) + { + static char lu[] = "0123456789abcdef"; + unsigned char v = *s++; + *d++ = lu[v>>4]; + *d++ = lu[v&0xf]; + } + *d = 0; + node->set( key, buffer ); + free( buffer ); + return 1; +} + + +/** + * return the size of the value part of an entry + */ +int Fl_Preferences::size( const char *key ) +{ + const char *v = node->get( key ); + return v ? strlen( v ) : 0 ; +} + +/** + * creates a path that is related to the preferences file + * and that is usable for application data beyond what is covered + * by Fl_Preferences. + * - 'getUserdataPath' actually creates the directory + * - 'path' must be large enough to receive a complete file path + * example: + * Fl_Preferences prefs( USER, "matthiasm.com", "test" ); + * char path[FL_PATH_MAX]; + * prefs.getUserdataPath( path ); + * sample returns: + * Win32: c:/Documents and Settings/matt/Application Data/matthiasm.com/test/ + * prefs: c:/Documents and Settings/matt/Application Data/matthiasm.com/test.prefs + */ +char Fl_Preferences::getUserdataPath( char *path, int pathlen ) +{ + if ( rootNode ) + return rootNode->getPath( path, pathlen ); + return 0; +} + +/** + * write all preferences to disk + * - this function works only with the base preference group + * - this function is rarely used as deleting the base preferences flushes automatically + */ +void Fl_Preferences::flush() +{ + if ( rootNode && node->dirty() ) + rootNode->write(); +} + +//----------------------------------------------------------------------------- +// helper class to create dynamic group and entry names on the fly +// + +/** + * create a group name or entry name on the fly + * - this version creates a simple unsigned integer as an entry name + * example: + * int n, i; + * Fl_Preferences prev( appPrefs, "PreviousFiles" ); + * prev.get( "n", 0 ); + * for ( i=0; i<n; i++ ) + * prev.get( Fl_Preferences::Name(i), prevFile[i], "" ); + */ +Fl_Preferences::Name::Name( unsigned int n ) +{ + data_ = (char*)malloc(20); + sprintf(data_, "%u", n); +} + +/** + * create a group name or entry name on the fly + * - this version creates entry names as in 'printf' + * example: + * int n, i; + * Fl_Preferences prefs( USER, "matthiasm.com", "test" ); + * prev.get( "nFiles", 0 ); + * for ( i=0; i<n; i++ ) + * prev.get( Fl_Preferences::Name( "File%d", i ), prevFile[i], "" ); + */ +Fl_Preferences::Name::Name( const char *format, ... ) +{ + data_ = (char*)malloc(1024); + va_list args; + va_start(args, format); + vsnprintf(data_, 1024, format, args); + va_end(args); +} + +// delete the name +Fl_Preferences::Name::~Name() +{ + free(data_); +} + +//----------------------------------------------------------------------------- +// internal methods, do not modify or use as they will change without notice +// + +int Fl_Preferences::Node::lastEntrySet = -1; + +// recursively create a path in the file system +static char makePath( const char *path ) { + if (access(path, 0)) { + const char *s = strrchr( path, '/' ); + if ( !s ) return 0; + int len = s-path; + char *p = (char*)malloc( len+1 ); + memcpy( p, path, len ); + p[len] = 0; + makePath( p ); + free( p ); +#if defined(WIN32) && !defined(__CYGWIN__) + return ( mkdir( path ) == 0 ); +#else + return ( mkdir( path, 0777 ) == 0 ); +#endif // WIN32 && !__CYGWIN__ + } + return 1; +} + +// strip the filename and create a path +static void makePathForFile( const char *path ) +{ + const char *s = strrchr( path, '/' ); + if ( !s ) return; + int len = s-path; + char *p = (char*)malloc( len+1 ); + memcpy( p, path, len ); + p[len] = 0; + makePath( p ); + free( p ); +} + +// create the root node +// - construct the name of the file that will hold our preferences +Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, Root root, const char *vendor, const char *application ) +{ + char filename[ FL_PATH_MAX ]; filename[0] = 0; +#ifdef WIN32 +# define FLPREFS_RESOURCE "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders" + int appDataLen = strlen(vendor) + strlen(application) + 8; + DWORD type, nn; + LONG err; + HKEY key; + + switch (root) { + case SYSTEM: + err = RegOpenKey( HKEY_LOCAL_MACHINE, FLPREFS_RESOURCE, &key ); + if (err == ERROR_SUCCESS) { + nn = FL_PATH_MAX - appDataLen; + err = RegQueryValueEx( key, "Common AppData", 0L, &type, (BYTE*)filename, &nn ); + if ( ( err != ERROR_SUCCESS ) && ( type == REG_SZ ) ) + filename[0] = 0; + RegCloseKey(key); + } + break; + case USER: + err = RegOpenKey( HKEY_CURRENT_USER, FLPREFS_RESOURCE, &key ); + if (err == ERROR_SUCCESS) { + nn = FL_PATH_MAX - appDataLen; + err = RegQueryValueEx( key, "AppData", 0L, &type, (BYTE*)filename, &nn ); + if ( ( err != ERROR_SUCCESS ) && ( type == REG_SZ ) ) + { + err = RegQueryValueEx( key, "Personal", 0L, &type, (BYTE*)filename, &nn ); + if ( ( err != ERROR_SUCCESS ) && ( type == REG_SZ ) ) + filename[0] = 0; + } + RegCloseKey(key); + } + break; + } + + if (!filename[0]) { + strcpy(filename, "C:\\FLTK"); + } + + snprintf(filename + strlen(filename), sizeof(filename) - strlen(filename), + "/%s/%s.prefs", vendor, application); + for (char *s = filename; *s; s++) if (*s == '\\') *s = '/'; +#elif defined ( __APPLE__ ) + FSSpec spec = { 0 }; + FSRef ref; + OSErr err = fnfErr; + switch (root) { + case SYSTEM: + err = FindFolder( kLocalDomain, kPreferencesFolderType, + 1, &spec.vRefNum, &spec.parID ); + break; + case USER: + err = FindFolder( kUserDomain, kPreferencesFolderType, + 1, &spec.vRefNum, &spec.parID ); + break; + } + FSpMakeFSRef( &spec, &ref ); + FSRefMakePath( &ref, (UInt8*)filename, FL_PATH_MAX ); + snprintf(filename + strlen(filename), sizeof(filename) - strlen(filename), + "/%s/%s.prefs", vendor, application ); +#else + const char *e; + switch (root) { + case USER: + if ((e = getenv("HOME")) != NULL) { + strlcpy(filename, e, sizeof(filename)); + + if (filename[strlen(filename)-1] != '/') { + strlcat(filename, "/.fltk/", sizeof(filename)); + } else { + strlcat(filename, ".fltk/", sizeof(filename)); + } + break; + } + + case SYSTEM: + strcpy(filename, "/etc/fltk/"); + break; + } + + snprintf(filename + strlen(filename), sizeof(filename) - strlen(filename), + "%s/%s.prefs", vendor, application); +#endif + + prefs_ = prefs; + filename_ = strdup(filename); + vendor_ = strdup(vendor); + application_ = strdup(application); + + read(); +} + +// create the root node +// - construct the name of the file that will hold our preferences +Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, const char *path, const char *vendor, const char *application ) +{ + char filename[ FL_PATH_MAX ]; filename[0] = 0; + + snprintf(filename, sizeof(filename), "%s/%s.prefs", path, application); + + prefs_ = prefs; + filename_ = strdup(filename); + vendor_ = strdup(vendor); + application_ = strdup(application); + + read(); +} + +// destroy the root node and all depending nodes +Fl_Preferences::RootNode::~RootNode() +{ + if ( prefs_->node->dirty() ) + write(); + if ( filename_ ) + free( filename_ ); + if ( vendor_ ) + free( vendor_ ); + if ( application_ ) + free( application_ ); + delete prefs_->node; +} + +// read a preferences file and construct the group tree and with all entry leafs +int Fl_Preferences::RootNode::read() +{ + char buf[1024]; + FILE *f = fopen( filename_, "rb" ); + if ( !f ) return 0; + fgets( buf, 1024, f ); + fgets( buf, 1024, f ); + fgets( buf, 1024, f ); + Node *nd = prefs_->node; + for (;;) + { + if ( !fgets( buf, 1024, f ) ) break; // EOF or Error + if ( buf[0]=='[' ) // read a new group + { + int end = strcspn( buf+1, "]\n\r" ); + buf[ end+1 ] = 0; + nd = prefs_->node->find( buf+1 ); + } + else if ( buf[0]=='+' ) // + { // value of previous name/value pair spans multiple lines + int end = strcspn( buf+1, "\n\r" ); + if ( end != 0 ) // if entry is not empty + { + buf[ end+1 ] = 0; + nd->add( buf+1 ); + } + } + else // read a name/value pair + { + int end = strcspn( buf, "\n\r" ); + if ( end != 0 ) // if entry is not empty + { + buf[ end ] = 0; + nd->set( buf ); + } + } + } + fclose( f ); + return 0; +} + +// write the group tree and all entry leafs +int Fl_Preferences::RootNode::write() +{ + makePathForFile(filename_); + FILE *f = fopen( filename_, "wb" ); + if ( !f ) return 1; + fprintf( f, "; FLTK preferences file format 1.0\n" ); + fprintf( f, "; vendor: %s\n", vendor_ ); + fprintf( f, "; application: %s\n", application_ ); + prefs_->node->write( f ); + fclose( f ); + return 0; +} + +// get the path to the preferences directory +char Fl_Preferences::RootNode::getPath( char *path, int pathlen ) +{ + strlcpy( path, filename_, pathlen); + + char *s; + for ( s = path; *s; s++ ) if ( *s == '\\' ) *s = '/'; + s = strrchr( path, '.' ); + if ( !s ) return 0; + *s = 0; + char ret = makePath( path ); + strcpy( s, "/" ); + return ret; +} + +// create a node that represents a group +// - path must be a single word, prferable alnum(), dot and underscore only. Space is ok. +Fl_Preferences::Node::Node( const char *path ) +{ + if ( path ) path_ = strdup( path ); else path_ = 0; + child_ = 0; next_ = 0; parent_ = 0; + entry = 0; + nEntry = NEntry = 0; + dirty_ = 0; +} + +// delete this and all depending nodes +Fl_Preferences::Node::~Node() +{ + Node *nx; + for ( Node *nd = child_; nd; nd = nx ) + { + nx = nd->next_; + delete nd; + } + if ( entry ) + { + for ( int i = 0; i < nEntry; i++ ) + { + if ( entry[i].name ) + free( entry[i].name ); + if ( entry[i].value ) + free( entry[i].value ); + } + free( entry ); + } + if ( path_ ) + free( path_ ); +} + +// recursively check if any entry is dirty (was changed after loading a fresh prefs file) +char Fl_Preferences::Node::dirty() +{ + if ( dirty_ ) return 1; + if ( next_ && next_->dirty() ) return 1; + if ( child_ && child_->dirty() ) return 1; + return 0; +} + +// write this node (recursively from the last neighbor back to this) +// write all entries +// write all children +int Fl_Preferences::Node::write( FILE *f ) +{ + if ( next_ ) next_->write( f ); + fprintf( f, "\n[%s]\n\n", path_ ); + for ( int i = 0; i < nEntry; i++ ) + { + char *src = entry[i].value; + if ( src ) + { // hack it into smaller pieces if needed + fprintf( f, "%s:", entry[i].name ); + int cnt; + for ( cnt = 0; cnt < 60; cnt++ ) + if ( src[cnt]==0 ) break; + fwrite( src, cnt, 1, f ); + fprintf( f, "\n" ); + src += cnt; + for (;*src;) + { + for ( cnt = 0; cnt < 80; cnt++ ) + if ( src[cnt]==0 ) break; + fputc( '+', f ); + fwrite( src, cnt, 1, f ); + fputc( '\n', f ); + src += cnt; + } + } + else + fprintf( f, "%s\n", entry[i].name ); + } + if ( child_ ) child_->write( f ); + dirty_ = 0; + return 0; +} + +// set the parent node and create the full path +void Fl_Preferences::Node::setParent( Node *pn ) +{ + parent_ = pn; + next_ = pn->child_; + pn->child_ = this; + sprintf( nameBuffer, "%s/%s", pn->path_, path_ ); + free( path_ ); + path_ = strdup( nameBuffer ); +} + +// add a child to this node and set its path (try to find it first...) +Fl_Preferences::Node *Fl_Preferences::Node::addChild( const char *path ) +{ + sprintf( nameBuffer, "%s/%s", path_, path ); + char *name = strdup( nameBuffer ); + Node *nd = find( name ); + free( name ); + dirty_ = 1; + return nd; +} + +// create and set, or change an entry within this node +void Fl_Preferences::Node::set( const char *name, const char *value ) +{ + for ( int i=0; i<nEntry; i++ ) + { + if ( strcmp( name, entry[i].name ) == 0 ) + { + if ( !value ) return; // annotation + if ( strcmp( value, entry[i].value ) != 0 ) + { + if ( entry[i].value ) + free( entry[i].value ); + entry[i].value = strdup( value ); + dirty_ = 1; + } + lastEntrySet = i; + return; + } + } + if ( NEntry==nEntry ) + { + NEntry = NEntry ? NEntry*2 : 10; + entry = (Entry*)realloc( entry, NEntry * sizeof(Entry) ); + } + entry[ nEntry ].name = strdup( name ); + entry[ nEntry ].value = value?strdup( value ):0; + lastEntrySet = nEntry; + nEntry++; + dirty_ = 1; +} + +// create or set a value (or annotation) from a single line in the file buffer +void Fl_Preferences::Node::set( const char *line ) +{ + // hmm. If we assume that we always read this file in the beginning, + // we can handle the dirty flag 'quick and dirty' + char dirt = dirty_; + if ( line[0]==';' || line[0]==0 || line[0]=='#' ) + { + set( line, 0 ); + } + else + { + const char *c = strchr( line, ':' ); + if ( c ) + { + strlcpy( nameBuffer, line, c-line+1); + set( nameBuffer, c+1 ); + } + else + set( line, "" ); + } + dirty_ = dirt; +} + +// add more data to an existing entry +void Fl_Preferences::Node::add( const char *line ) +{ + if ( lastEntrySet<0 || lastEntrySet>=nEntry ) return; + char *&dst = entry[ lastEntrySet ].value; + int a = strlen( dst ); + int b = strlen( line ); + dst = (char*)realloc( dst, a+b+1 ); + memcpy( dst+a, line, b+1 ); + dirty_ = 1; +} + +// get the value for a name, returns 0 if no such name +const char *Fl_Preferences::Node::get( const char *name ) +{ + int i = getEntry( name ); + return i>=0 ? entry[i].value : 0 ; +} + +// find the index of an entry, returns -1 if no such entry +int Fl_Preferences::Node::getEntry( const char *name ) +{ + for ( int i=0; i<nEntry; i++ ) + { + if ( strcmp( name, entry[i].name ) == 0 ) + { + return i; + } + } + return -1; +} + +// remove one entry form this group +char Fl_Preferences::Node::deleteEntry( const char *name ) +{ + int ix = getEntry( name ); + if ( ix == -1 ) return 0; + memmove( entry+ix, entry+ix+1, (nEntry-ix-1) * sizeof(Entry) ); + nEntry--; + dirty_ = 1; + return 1; +} + +// find a group somewhere in the tree starting here +// - this method will always return a valid node (except for memory allocation problems) +// - if the node was not found, 'find' will create the required branch +Fl_Preferences::Node *Fl_Preferences::Node::find( const char *path ) +{ + int len = strlen( path_ ); + if ( strncmp( path, path_, len ) == 0 ) + { + if ( path[ len ] == 0 ) + return this; + if ( path[ len ] == '/' ) + { + Node *nd; + for ( nd = child_; nd; nd = nd->next_ ) + { + Node *nn = nd->find( path ); + if ( nn ) return nn; + } + const char *s = path+len+1; + const char *e = strchr( s, '/' ); + if (e) strlcpy( nameBuffer, s, e-s+1 ); + else strlcpy( nameBuffer, s, sizeof(nameBuffer)); + nd = new Node( nameBuffer ); + nd->setParent( this ); + return nd->find( path ); + } + } + return 0; +} + +// find a group somewhere in the tree starting here +// caller must not set 'offset' argument +// - if the node does not exist, 'search' returns NULL +// - if the pathname is "." (current node) return this node +// - if the pathname is "./" (root node) return the topmost node +// - if the pathname starts with "./", start the search at the root node instead +Fl_Preferences::Node *Fl_Preferences::Node::search( const char *path, int offset ) +{ + + if ( offset == 0 ) + { + if ( path[0] == '.' ) + { + if ( path[1] == 0 ) + { + return this; // user was searching for current node + } + else if ( path[1] == '/' ) + { + Node *nn = this; + while ( nn->parent_ ) nn = nn->parent_; + if ( path[2]==0 ) + { // user is searching for root ( "./" ) + return nn; + } + return nn->search( path+2, 2 ); // do a relative search on the root node + } + } + offset = strlen( path_ ) + 1; + } + + int len = strlen( path_ ); + if ( len < offset-1 ) return 0; + len -= offset; + if ( ( len <= 0 ) || ( strncmp( path, path_+offset, len ) == 0 ) ) + { + if ( len > 0 && path[ len ] == 0 ) + return this; + if ( len <= 0 || path[ len ] == '/' ) + { + for ( Node *nd = child_; nd; nd = nd->next_ ) + { + Node *nn = nd->search( path, offset ); + if ( nn ) return nn; + } + return 0; + } + } + return 0; +} + +// return the number of child nodes (groups) +int Fl_Preferences::Node::nChildren() +{ + int cnt = 0; + for ( Node *nd = child_; nd; nd = nd->next_ ) + cnt++; + return cnt; +} + +// return the n'th child node +const char *Fl_Preferences::Node::child( int ix ) +{ + Node *nd; + for ( nd = child_; nd; nd = nd->next_ ) + { + if ( !ix-- ) break; + } + if ( nd && nd->path_ ) + { + char *r = strrchr( nd->path_, '/' ); + return r ? r+1 : nd->path_ ; + } + return 0L ; +} + +// remove myself from the list and delete me (and all children) +char Fl_Preferences::Node::remove() +{ + Node *nd = 0, *np; + if ( parent_ ) + { + nd = parent_->child_; np = 0L; + for ( ; nd; np = nd, nd = nd->next_ ) + { + if ( nd == this ) + { + if ( np ) + np->next_ = nd->next_; + else + parent_->child_ = nd->next_; + break; + } + } + parent_->dirty_ = 1; + } + delete this; + return ( nd != 0 ); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Progress.cxx b/Utilities/FLTK/src/Fl_Progress.cxx new file mode 100644 index 0000000000..88a8ad7730 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Progress.cxx @@ -0,0 +1,115 @@ +// +// "$Id$" +// +// Progress bar widget routines. +// +// Copyright 2000-2005 by Michael Sweet. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +// Contents: +// +// Fl_Progress::draw() - Draw the check button. +// Fl_Progress::Fl_Progress() - Construct a Fl_Progress widget. +// + +// +// Include necessary header files... +// + +#include <FL/Fl.H> +#include <FL/Fl_Progress.H> +#include <FL/fl_draw.H> + + +// +// Fl_Progress is a progress bar widget based off Fl_Widget that shows a +// standard progress bar... +// + + +// +// 'Fl_Progress::draw()' - Draw the check button. +// + +void Fl_Progress::draw() +{ + int progress; // Size of progress bar... + int bx, by, bw, bh; // Box areas... + int tx, tw; // Temporary X + width + + + // Get the box borders... + bx = Fl::box_dx(box()); + by = Fl::box_dy(box()); + bw = Fl::box_dw(box()); + bh = Fl::box_dh(box()); + + tx = x() + bx; + tw = w() - bw; + + // Draw the progress bar... + if (maximum_ > minimum_) + progress = (int)(tw * (value_ - minimum_) / (maximum_ - minimum_) + 0.5f); + else + progress = 0; + + // Draw the box and label... + if (progress > 0) { + Fl_Color c = labelcolor(); + labelcolor(fl_contrast(labelcolor(), color2())); + + fl_clip(x(), y(), progress + bx, h()); + draw_box(box(), x(), y(), w(), h(), active_r() ? color2() : fl_inactive(color2())); + draw_label(tx, y() + by, tw, h() - bh); + fl_pop_clip(); + + labelcolor(c); + + fl_clip(tx + progress, y(), w() - progress, h()); + draw_box(box(), x(), y(), w(), h(), active_r() ? color() : fl_inactive(color())); + draw_label(tx, y() + by, tw, h() - bh); + fl_pop_clip(); + } else { + draw_box(box(), x(), y(), w(), h(), color()); + draw_label(tx, y() + by, tw, h() - bh); + } +} + + +// +// 'Fl_Progress::Fl_Progress()' - Construct a Fl_Progress widget. +// + +Fl_Progress::Fl_Progress(int X, int Y, int W, int H, const char* l) +: Fl_Widget(X, Y, W, H, l) +{ + align(FL_ALIGN_INSIDE); + box(FL_DOWN_BOX); + color(FL_BACKGROUND2_COLOR, FL_YELLOW); + minimum(0.0f); + maximum(100.0f); + value(0.0f); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Repeat_Button.cxx b/Utilities/FLTK/src/Fl_Repeat_Button.cxx new file mode 100644 index 0000000000..638cc4c814 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Repeat_Button.cxx @@ -0,0 +1,68 @@ +// +// "$Id$" +// +// Repeat button widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Repeat_Button.H> + +#define INITIALREPEAT .5 +#define REPEAT .1 + +void Fl_Repeat_Button::repeat_callback(void *v) { + Fl_Button *b = (Fl_Button*)v; + Fl::add_timeout(REPEAT,repeat_callback,b); + b->do_callback(); +} + +int Fl_Repeat_Button::handle(int event) { + int newval; + switch (event) { + case FL_HIDE: + case FL_DEACTIVATE: + case FL_RELEASE: + newval = 0; goto J1; + case FL_PUSH: + case FL_DRAG: + if (Fl::visible_focus()) Fl::focus(this); + newval = Fl::event_inside(this); + J1: + if (value(newval)) { + if (newval) { + Fl::add_timeout(INITIALREPEAT,repeat_callback,this); + do_callback(); + } else { + Fl::remove_timeout(repeat_callback,this); + } + } + return 1; + default: + return Fl_Button::handle(event); + } +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Return_Button.cxx b/Utilities/FLTK/src/Fl_Return_Button.cxx new file mode 100644 index 0000000000..d09f622658 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Return_Button.cxx @@ -0,0 +1,72 @@ +// +// "$Id$" +// +// Return button widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Return_Button.H> +#include <FL/fl_draw.H> + +int fl_return_arrow(int x, int y, int w, int h) { + int size = w; if (h<size) size = h; + int d = (size+2)/4; if (d<3) d = 3; + int t = (size+9)/12; if (t<1) t = 1; + int x0 = x+(w-2*d-2*t-1)/2; + int x1 = x0+d; + int y0 = y+h/2; + fl_color(FL_LIGHT3); + fl_line(x0, y0, x1, y0+d); + fl_yxline(x1, y0+d, y0+t, x1+d+2*t, y0-d); + fl_yxline(x1, y0-t, y0-d); + fl_color(fl_gray_ramp(0)); + fl_line(x0, y0, x1, y0-d); + fl_color(FL_DARK3); + fl_xyline(x1+1, y0-t, x1+d, y0-d, x1+d+2*t); + return 1; +} + +void Fl_Return_Button::draw() { + if (type() == FL_HIDDEN_BUTTON) return; + draw_box(value() ? (down_box()?down_box():fl_down(box())) : box(), + value() ? selection_color() : color()); + int W = h(); + if (w()/3 < W) W = w()/3; + fl_return_arrow(x()+w()-W-4, y(), W, h()); + draw_label(x(), y(), w()-W+4, h()); + if (Fl::focus() == this) draw_focus(); +} + +int Fl_Return_Button::handle(int event) { + if (event == FL_SHORTCUT && + (Fl::event_key() == FL_Enter || Fl::event_key() == FL_KP_Enter)) { + do_callback(); + return 1; + } else + return Fl_Button::handle(event); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Roller.cxx b/Utilities/FLTK/src/Fl_Roller.cxx new file mode 100644 index 0000000000..9a4947ef64 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Roller.cxx @@ -0,0 +1,180 @@ +// +// "$Id$" +// +// Roller widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Rapid-App style knob + +#include <FL/Fl.H> +#include <FL/Fl_Roller.H> +#include <FL/fl_draw.H> +#include <math.h> + +int Fl_Roller::handle(int event) { + static int ipos; + int newpos = horizontal() ? Fl::event_x() : Fl::event_y(); + switch (event) { + case FL_PUSH: + if (Fl::visible_focus()) { + Fl::focus(this); + redraw(); + } + handle_push(); + ipos = newpos; + return 1; + case FL_DRAG: + handle_drag(clamp(round(increment(previous_value(),newpos-ipos)))); + return 1; + case FL_RELEASE: + handle_release(); + return 1; + case FL_KEYBOARD : + switch (Fl::event_key()) { + case FL_Up: + if (horizontal()) return 0; + handle_drag(clamp(increment(value(),-1))); + return 1; + case FL_Down: + if (horizontal()) return 0; + handle_drag(clamp(increment(value(),1))); + return 1; + case FL_Left: + if (!horizontal()) return 0; + handle_drag(clamp(increment(value(),-1))); + return 1; + case FL_Right: + if (!horizontal()) return 0; + handle_drag(clamp(increment(value(),1))); + return 1; + default: + return 0; + } + // break not required because of switch... + case FL_FOCUS : + case FL_UNFOCUS : + if (Fl::visible_focus()) { + redraw(); + return 1; + } else return 0; + case FL_ENTER : + case FL_LEAVE : + return 1; + default: + return 0; + } +} + +void Fl_Roller::draw() { + if (damage()&FL_DAMAGE_ALL) draw_box(); + int X = x()+Fl::box_dx(box()); + int Y = y()+Fl::box_dy(box()); + int W = w()-Fl::box_dw(box())-1; + int H = h()-Fl::box_dh(box())-1; + if (W<=0 || H <=0) return; + int offset = step() ? int(value()/step()) : 0; + const double ARC = 1.5; // 1/2 the number of radians visible + const double delta = .2; // radians per knurl + if (horizontal()) { // horizontal one + // draw shaded ends of wheel: + int h1 = W/4+1; // distance from end that shading starts + fl_color(color()); fl_rectf(X+h1,Y,W-2*h1,H); + for (int i=0; h1; i++) { + fl_color((Fl_Color)(FL_GRAY-i-1)); + int h2 = FL_GRAY-i-1 > FL_DARK3 ? 2*h1/3+1 : 0; + fl_rectf(X+h2,Y,h1-h2,H); + fl_rectf(X+W-h1,Y,h1-h2,H); + h1 = h2; + } + if (active_r()) { + // draw ridges: + double junk; + for (double yy = -ARC+modf(offset*sin(ARC)/(W/2)/delta,&junk)*delta;; + yy += delta) { + int yy1 = int((sin(yy)/sin(ARC)+1)*W/2); + if (yy1 <= 0) continue; else if (yy1 >= W-1) break; + fl_color(FL_DARK3); fl_yxline(X+yy1,Y+1,Y+H-1); + if (yy < 0) yy1--; else yy1++; + fl_color(FL_LIGHT1);fl_yxline(X+yy1,Y+1,Y+H-1); + } + // draw edges: + h1 = W/8+1; // distance from end the color inverts + fl_color(FL_DARK2); + fl_xyline(X+h1,Y+H-1,X+W-h1); + fl_color(FL_DARK3); + fl_yxline(X,Y+H,Y,X+h1); + fl_xyline(X+W-h1,Y,X+W); + fl_color(FL_LIGHT2); + fl_xyline(X+h1,Y-1,X+W-h1); + fl_yxline(X+W,Y,Y+H,X+W-h1); + fl_xyline(X+h1,Y+H,X); + } + } else { // vertical one + // draw shaded ends of wheel: + int h1 = H/4+1; // distance from end that shading starts + fl_color(color()); fl_rectf(X,Y+h1,W,H-2*h1); + for (int i=0; h1; i++) { + fl_color((Fl_Color)(FL_GRAY-i-1)); + int h2 = FL_GRAY-i-1 > FL_DARK3 ? 2*h1/3+1 : 0; + fl_rectf(X,Y+h2,W,h1-h2); + fl_rectf(X,Y+H-h1,W,h1-h2); + h1 = h2; + } + if (active_r()) { + // draw ridges: + double junk; + for (double yy = -ARC+modf(offset*sin(ARC)/(H/2)/delta,&junk)*delta; + ; yy += delta) { + int yy1 = int((sin(yy)/sin(ARC)+1)*H/2); + if (yy1 <= 0) continue; else if (yy1 >= H-1) break; + fl_color(FL_DARK3); fl_xyline(X+1,Y+yy1,X+W-1); + if (yy < 0) yy1--; else yy1++; + fl_color(FL_LIGHT1);fl_xyline(X+1,Y+yy1,X+W-1); + } + // draw edges: + h1 = H/8+1; // distance from end the color inverts + fl_color(FL_DARK2); + fl_yxline(X+W-1,Y+h1,Y+H-h1); + fl_color(FL_DARK3); + fl_xyline(X+W,Y,X,Y+h1); + fl_yxline(X,Y+H-h1,Y+H); + fl_color(FL_LIGHT2); + fl_yxline(X,Y+h1,Y+H-h1); + fl_xyline(X,Y+H,X+W,Y+H-h1); + fl_yxline(X+W,Y+h1,Y); + } + } + + if (Fl::focus() == this) draw_focus(FL_THIN_UP_FRAME, x(), y(), w(), h()); +} + +Fl_Roller::Fl_Roller(int X,int Y,int W,int H,const char* L) + : Fl_Valuator(X,Y,W,H,L) { + box(FL_UP_BOX); + step(1,1000); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Round_Button.cxx b/Utilities/FLTK/src/Fl_Round_Button.cxx new file mode 100644 index 0000000000..7ea65bfd04 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Round_Button.cxx @@ -0,0 +1,44 @@ +// +// "$Id$" +// +// Round button for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// A subclass of Fl_Button that always draws as a round circle. This +// circle is smaller than the widget size and can be surrounded by +// another box type, for compatability with Forms. + +#include <FL/Fl.H> +#include <FL/Fl_Round_Button.H> + +Fl_Round_Button::Fl_Round_Button(int X,int Y,int W,int H, const char *l) +: Fl_Light_Button(X,Y,W,H,l) { + box(FL_NO_BOX); + down_box(FL_ROUND_DOWN_BOX); + selection_color(FL_FOREGROUND_COLOR); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Scroll.cxx b/Utilities/FLTK/src/Fl_Scroll.cxx new file mode 100644 index 0000000000..09bf543bf7 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Scroll.cxx @@ -0,0 +1,297 @@ +// +// "$Id$" +// +// Scroll widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Tiled_Image.H> +#include <FL/Fl_Scroll.H> +#include <FL/fl_draw.H> + +// Clear all but the scrollbars... +void Fl_Scroll::clear() { + for (int i=children() - 1; i >= 0; i --) { + Fl_Widget* o = child(i); + if (o != &hscrollbar && o != &scrollbar) { + remove(o); + delete o; + } + } +} + +// Insure the scrollbars are the last children: +void Fl_Scroll::fix_scrollbar_order() { + Fl_Widget** a = (Fl_Widget**)array(); + if (a[children()-1] != &scrollbar) { + int i,j; for (i = j = 0; j < children(); j++) + if (a[j] != &hscrollbar && a[j] != &scrollbar) a[i++] = a[j]; + a[i++] = &hscrollbar; + a[i++] = &scrollbar; + } +} + +void Fl_Scroll::draw_clip(void* v,int X, int Y, int W, int H) { + fl_clip(X,Y,W,H); + Fl_Scroll* s = (Fl_Scroll*)v; + // erase background as needed... + switch (s->box()) { + case FL_NO_BOX : + case FL_UP_FRAME : + case FL_DOWN_FRAME : + case FL_THIN_UP_FRAME : + case FL_THIN_DOWN_FRAME : + case FL_ENGRAVED_FRAME : + case FL_EMBOSSED_FRAME : + case FL_BORDER_FRAME : + case _FL_SHADOW_FRAME : + case _FL_ROUNDED_FRAME : + case _FL_OVAL_FRAME : + case _FL_PLASTIC_UP_FRAME : + case _FL_PLASTIC_DOWN_FRAME : + if (s->parent() == (Fl_Group *)s->window() && Fl::scheme_bg_) { + Fl::scheme_bg_->draw(X-(X%((Fl_Tiled_Image *)Fl::scheme_bg_)->image()->w()), + Y-(Y%((Fl_Tiled_Image *)Fl::scheme_bg_)->image()->h()), + W+((Fl_Tiled_Image *)Fl::scheme_bg_)->image()->w(), + H+((Fl_Tiled_Image *)Fl::scheme_bg_)->image()->h()); + break; + } + + default : + fl_color(s->color()); + fl_rectf(X,Y,W,H); + break; + } + Fl_Widget*const* a = s->array(); + for (int i=s->children()-2; i--;) { + Fl_Widget& o = **a++; + s->draw_child(o); + s->draw_outside_label(o); + } + fl_pop_clip(); +} + +void Fl_Scroll::bbox(int& X, int& Y, int& W, int& H) { + X = x()+Fl::box_dx(box()); + Y = y()+Fl::box_dy(box()); + W = w()-Fl::box_dw(box()); + H = h()-Fl::box_dh(box()); + if (scrollbar.visible()) { + W -= scrollbar.w(); + if (scrollbar.align() & FL_ALIGN_LEFT) X += scrollbar.w(); + } + if (hscrollbar.visible()) { + H -= hscrollbar.h(); + if (scrollbar.align() & FL_ALIGN_TOP) Y += hscrollbar.h(); + } +} + +void Fl_Scroll::draw() { + fix_scrollbar_order(); + int X,Y,W,H; bbox(X,Y,W,H); + + uchar d = damage(); + + if (d & FL_DAMAGE_ALL) { // full redraw + draw_box(box(),x(),y(),w(),h(),color()); + draw_clip(this, X, Y, W, H); + } else { + if (d & FL_DAMAGE_SCROLL) { + // scroll the contents: + fl_scroll(X, Y, W, H, oldx-xposition_, oldy-yposition_, draw_clip, this); + + // Erase the background as needed... + Fl_Widget*const* a = array(); + int L, R, T, B; + L = 999999; + R = 0; + T = 999999; + B = 0; + for (int i=children()-2; i--; a++) { + if ((*a)->x() < L) L = (*a)->x(); + if (((*a)->x() + (*a)->w()) > R) R = (*a)->x() + (*a)->w(); + if ((*a)->y() < T) T = (*a)->y(); + if (((*a)->y() + (*a)->h()) > B) B = (*a)->y() + (*a)->h(); + } + if (L > X) draw_clip(this, X, Y, L - X, H); + if (R < (X + W)) draw_clip(this, R, Y, X + W - R, H); + if (T > Y) draw_clip(this, X, Y, W, T - Y); + if (B < (Y + H)) draw_clip(this, X, B, W, Y + H - B); + } + if (d & FL_DAMAGE_CHILD) { // draw damaged children + fl_clip(X, Y, W, H); + Fl_Widget*const* a = array(); + for (int i=children()-2; i--;) update_child(**a++); + fl_pop_clip(); + } + } + + // accumulate bounding box of children: + int l = X; int r = X; int t = Y; int b = Y; + Fl_Widget*const* a = array(); + for (int i=children()-2; i--;) { + Fl_Object* o = *a++; + if (o->x() < l) l = o->x(); + if (o->y() < t) t = o->y(); + if (o->x()+o->w() > r) r = o->x()+o->w(); + if (o->y()+o->h() > b) b = o->y()+o->h(); + } + + // turn the scrollbars on and off as necessary: + // See if children would fit if we had no scrollbars... + X = x()+Fl::box_dx(box()); + Y = y()+Fl::box_dy(box()); + W = w()-Fl::box_dw(box()); + H = h()-Fl::box_dh(box()); + int vneeded = 0; + int hneeded = 0; + if (type() & VERTICAL) { + if ((type() & ALWAYS_ON) || t < Y || b > Y+H) { + vneeded = 1; + W -= scrollbar.w(); + if (scrollbar.align() & FL_ALIGN_LEFT) X += scrollbar.w(); + } + } + if (type() & HORIZONTAL) { + if ((type() & ALWAYS_ON) || l < X || r > X+W) { + hneeded = 1; + H -= hscrollbar.h(); + if (scrollbar.align() & FL_ALIGN_TOP) Y += hscrollbar.h(); + // recheck vertical since we added a horizontal scrollbar + if (!vneeded && (type() & VERTICAL)) { + if ((type() & ALWAYS_ON) || t < Y || b > Y+H) { + vneeded = 1; + W -= scrollbar.w(); + if (scrollbar.align() & FL_ALIGN_LEFT) X += scrollbar.w(); + } + } + } + } + // Now that we know what's needed, make it so. + if (vneeded && !scrollbar.visible()) { + scrollbar.set_visible(); + d = FL_DAMAGE_ALL; + } + else if (!vneeded && scrollbar.visible()) { + scrollbar.clear_visible(); + draw_clip(this, + scrollbar.align()&FL_ALIGN_LEFT ? X : X+W-scrollbar.w(), + Y, scrollbar.w(), H); + d = FL_DAMAGE_ALL; + } + if (hneeded && !hscrollbar.visible()) { + hscrollbar.set_visible(); + d = FL_DAMAGE_ALL; + } + else if (!hneeded && hscrollbar.visible()) { + hscrollbar.clear_visible(); + draw_clip(this, + X, scrollbar.align()&FL_ALIGN_TOP ? Y : Y+H-hscrollbar.h(), + W, hscrollbar.h()); + d = FL_DAMAGE_ALL; + } + + scrollbar.resize(scrollbar.align()&FL_ALIGN_LEFT ? X-scrollbar.w() : X+W, + Y, scrollbar.w(), H); + scrollbar.value(oldy = yposition_ = (Y-t), H, 0, b-t); + + hscrollbar.resize(X, + scrollbar.align()&FL_ALIGN_TOP ? Y-hscrollbar.h() : Y+H, + W, hscrollbar.h()); + hscrollbar.value(oldx = xposition_ = (X-l), W, 0, r-l); + + // draw the scrollbars: + if (d & FL_DAMAGE_ALL) { + draw_child(scrollbar); + draw_child(hscrollbar); + if (scrollbar.visible() && hscrollbar.visible()) { + // fill in the little box in the corner + fl_color(color()); + fl_rectf(scrollbar.x(), hscrollbar.y(), scrollbar.w(), hscrollbar.h()); + } + } else { + update_child(scrollbar); + update_child(hscrollbar); + } +} + +void Fl_Scroll::resize(int X, int Y, int W, int H) { + fix_scrollbar_order(); + // move all the children: + Fl_Widget*const* a = array(); + for (int i=children()-2; i--;) { + Fl_Object* o = *a++; + o->position(o->x()+X-x(), o->y()+Y-y()); + } + Fl_Widget::resize(X,Y,W,H); +} + +void Fl_Scroll::position(int X, int Y) { + int dx = xposition_-X; + int dy = yposition_-Y; + if (!dx && !dy) return; + xposition_ = X; + yposition_ = Y; + Fl_Widget*const* a = array(); + for (int i=children(); i--;) { + Fl_Widget* o = *a++; + if (o == &hscrollbar || o == &scrollbar) continue; + o->position(o->x()+dx, o->y()+dy); + } + if (parent() == (Fl_Group *)window() && Fl::scheme_bg_) damage(FL_DAMAGE_ALL); + else damage(FL_DAMAGE_SCROLL); +} + +void Fl_Scroll::hscrollbar_cb(Fl_Widget* o, void*) { + Fl_Scroll* s = (Fl_Scroll*)(o->parent()); + s->position(int(((Fl_Scrollbar*)o)->value()), s->yposition()); +} + +void Fl_Scroll::scrollbar_cb(Fl_Widget* o, void*) { + Fl_Scroll* s = (Fl_Scroll*)(o->parent()); + s->position(s->xposition(), int(((Fl_Scrollbar*)o)->value())); +} + +#define SLIDER_WIDTH 16 + +Fl_Scroll::Fl_Scroll(int X,int Y,int W,int H,const char* L) + : Fl_Group(X,Y,W,H,L), + scrollbar(X+W-SLIDER_WIDTH,Y,SLIDER_WIDTH,H-SLIDER_WIDTH), + hscrollbar(X,Y+H-SLIDER_WIDTH,W-SLIDER_WIDTH,SLIDER_WIDTH) { + type(BOTH); + xposition_ = 0; + yposition_ = 0; + hscrollbar.type(FL_HORIZONTAL); + hscrollbar.callback(hscrollbar_cb); + scrollbar.callback(scrollbar_cb); +} + +int Fl_Scroll::handle(int event) { + fix_scrollbar_order(); + return Fl_Group::handle(event); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Scrollbar.cxx b/Utilities/FLTK/src/Fl_Scrollbar.cxx new file mode 100644 index 0000000000..66547b469f --- /dev/null +++ b/Utilities/FLTK/src/Fl_Scrollbar.cxx @@ -0,0 +1,257 @@ +// +// "$Id$" +// +// Scroll bar widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Scrollbar.H> +#include <FL/fl_draw.H> +#include <math.h> + +#define INITIALREPEAT .5 +#define REPEAT .05 + +void Fl_Scrollbar::increment_cb() { + int ls = maximum()>=minimum() ? linesize_ : -linesize_; + int i; + switch (pushed_) { + case 1: + i = -ls; + break; + default: + i = ls; + break; + case 5: + i = -int((maximum()-minimum())*slider_size()/(1.0-slider_size())) + ls; + if (i > -ls) i = -ls; + break; + case 6: + i = int((maximum()-minimum())*slider_size()/(1.0-slider_size())) - ls; + if (i < ls) i = ls; + break; + } + handle_drag(clamp(value() + i)); +} + +void Fl_Scrollbar::timeout_cb(void* v) { + Fl_Scrollbar* s = (Fl_Scrollbar*)v; + s->increment_cb(); + Fl::add_timeout(REPEAT, timeout_cb, s); +} + +int Fl_Scrollbar::handle(int event) { + // area of scrollbar: + int area; + int X=x(); int Y=y(); int W=w(); int H=h(); + + // adjust slider area to be inside the arrow buttons: + if (horizontal()) { + if (W >= 3*H) {X += H; W -= 2*H;} + } else { + if (H >= 3*W) {Y += W; H -= 2*W;} + } + + // which widget part is highlighted? + int relx; + int ww; + if (horizontal()) { + relx = Fl::event_x()-X; + ww = W; + } else { + relx = Fl::event_y()-Y; + ww = H; + } + if (relx < 0) area = 1; + else if (relx >= ww) area = 2; + else { + int S = int(slider_size()*ww+.5); + int T = (horizontal() ? H : W)/2+1; + if (type()==FL_VERT_NICE_SLIDER || type()==FL_HOR_NICE_SLIDER) T += 4; + if (S < T) S = T; + double val = + (maximum()-minimum()) ? (value()-minimum())/(maximum()-minimum()) : 0.5; + int sliderx; + if (val >= 1.0) sliderx = ww-S; + else if (val <= 0.0) sliderx = 0; + else sliderx = int(val*(ww-S)+.5); + if (Fl::event_button() == FL_MIDDLE_MOUSE) area = 8; + else if (relx < sliderx) area = 5; + else if (relx >= sliderx+S) area = 6; + else area = 8; + } + + switch (event) { + case FL_ENTER: + case FL_LEAVE: + return 1; + case FL_RELEASE: + damage(FL_DAMAGE_ALL); + if (pushed_) { + Fl::remove_timeout(timeout_cb, this); + pushed_ = 0; + } + handle_release(); + return 1; + case FL_PUSH: + if (pushed_) return 1; + if (area != 8) pushed_ = area; + if (pushed_) { + handle_push(); + Fl::add_timeout(INITIALREPEAT, timeout_cb, this); + increment_cb(); + damage(FL_DAMAGE_ALL); + return 1; + } + return Fl_Slider::handle(event, X,Y,W,H); + case FL_DRAG: + if (pushed_) return 1; + return Fl_Slider::handle(event, X,Y,W,H); + case FL_MOUSEWHEEL : + if (horizontal()) { + if (Fl::e_dx==0) return 0; + handle_drag(clamp(value() + linesize_ * Fl::e_dx)); + return 1; + } else { + if (Fl::e_dy==0) return 0; + handle_drag(clamp(value() + linesize_ * Fl::e_dy)); + return 1; + } + break; + case FL_SHORTCUT: + case FL_KEYBOARD: { + int v = value(); + int ls = maximum()>=minimum() ? linesize_ : -linesize_; + if (horizontal()) { + switch (Fl::event_key()) { + case FL_Left: + v -= ls; + break; + case FL_Right: + v += ls; + break; + default: + return 0; + } + } else { // vertical + switch (Fl::event_key()) { + case FL_Up: + v -= ls; + break; + case FL_Down: + v += ls; + break; + case FL_Page_Up: + if (slider_size() >= 1.0) return 0; + v -= int((maximum()-minimum())*slider_size()/(1.0-slider_size())); + v += ls; + break; + case FL_Page_Down: + if (slider_size() >= 1.0) return 0; + v += int((maximum()-minimum())*slider_size()/(1.0-slider_size())); + v -= ls; + break; + case FL_Home: + v = int(minimum()); + break; + case FL_End: + v = int(maximum()); + break; + default: + return 0; + } + } + v = int(clamp(v)); + if (v != value()) { + Fl_Slider::value(v); + value_damage(); + set_changed(); + do_callback(); + } + return 1;} + } + return 0; +} + +void Fl_Scrollbar::draw() { + if (damage()&FL_DAMAGE_ALL) draw_box(); + int X = x()+Fl::box_dx(box()); + int Y = y()+Fl::box_dy(box()); + int W = w()-Fl::box_dw(box()); + int H = h()-Fl::box_dh(box()); + if (horizontal()) { + if (W < 3*H) {Fl_Slider::draw(X,Y,W,H); return;} + Fl_Slider::draw(X+H,Y,W-2*H,H); + if (damage()&FL_DAMAGE_ALL) { + draw_box((pushed_==1) ? fl_down(slider()) : slider(), + X, Y, H, H, selection_color()); + draw_box((pushed_==2) ? fl_down(slider()) : slider(), + X+W-H, Y, H, H, selection_color()); + if (active_r()) + fl_color(labelcolor()); + else + fl_color(fl_inactive(labelcolor())); + int w1 = (H-4)/3; if (w1 < 1) w1 = 1; + int x1 = X+(H-w1-1)/2; + int yy1 = Y+(H-2*w1-1)/2; + fl_polygon(x1, yy1+w1, x1+w1, yy1+2*w1, x1+w1, yy1); + x1 += (W-H); + fl_polygon(x1, yy1, x1, yy1+2*w1, x1+w1, yy1+w1); + } + } else { // vertical + if (H < 3*W) {Fl_Slider::draw(X,Y,W,H); return;} + Fl_Slider::draw(X,Y+W,W,H-2*W); + if (damage()&FL_DAMAGE_ALL) { + draw_box((pushed_==1) ? fl_down(slider()) : slider(), + X, Y, W, W, selection_color()); + draw_box((pushed_==2) ? fl_down(slider()) : slider(), + X, Y+H-W, W, W, selection_color()); + if (active_r()) + fl_color(labelcolor()); + else + fl_color(fl_inactive(labelcolor())); + int w1 = (W-4)/3; if (w1 < 1) w1 = 1; + int x1 = X+(W-2*w1-1)/2; + int yy1 = Y+(W-w1-1)/2; + fl_polygon(x1, yy1+w1, x1+2*w1, yy1+w1, x1+w1, yy1); + yy1 += H-W; + fl_polygon(x1, yy1, x1+w1, yy1+w1, x1+2*w1, yy1); + } + } +} + +Fl_Scrollbar::Fl_Scrollbar(int X, int Y, int W, int H, const char* L) + : Fl_Slider(X, Y, W, H, L) +{ + box(FL_FLAT_BOX); + color(FL_DARK2); + slider(FL_UP_BOX); + linesize_ = 16; + pushed_ = 0; + step(1); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Shared_Image.cxx b/Utilities/FLTK/src/Fl_Shared_Image.cxx new file mode 100644 index 0000000000..b7447ff900 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Shared_Image.cxx @@ -0,0 +1,467 @@ +// +// "$Id$" +// +// Shared image code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <stdio.h> +#include <stdlib.h> +#include "flstring.h" + +#include <FL/Fl.H> +#include <FL/Fl_Shared_Image.H> +#include <FL/Fl_XBM_Image.H> +#include <FL/Fl_XPM_Image.H> + + +// +// Global class vars... +// + +Fl_Shared_Image **Fl_Shared_Image::images_ = 0; // Shared images +int Fl_Shared_Image::num_images_ = 0; // Number of shared images +int Fl_Shared_Image::alloc_images_ = 0; // Allocated shared images + +Fl_Shared_Handler *Fl_Shared_Image::handlers_ = 0;// Additional format handlers +int Fl_Shared_Image::num_handlers_ = 0; // Number of format handlers +int Fl_Shared_Image::alloc_handlers_ = 0; // Allocated format handlers + + +// +// Typedef the C API sort function type the only way I know how... +// + +extern "C" { + typedef int (*compare_func_t)(const void *, const void *); +} + + +// Static methods that really should be inline, but some WIN32 compilers +// can't handle it... +Fl_Shared_Image **Fl_Shared_Image::images() { + return images_; +} + +int Fl_Shared_Image::num_images() { + return num_images_; +} + + +// +// 'Fl_Shared_Image::compare()' - Compare two shared images... +// + +int +Fl_Shared_Image::compare(Fl_Shared_Image **i0, // I - First image + Fl_Shared_Image **i1) { // I - Second image + int i = strcmp((*i0)->name(), (*i1)->name()); + + if (i) return i; + else if (((*i0)->w() == 0 && (*i1)->original_) || + ((*i1)->w() == 0 && (*i0)->original_)) return 0; + else if ((*i0)->w() != (*i1)->w()) return (*i0)->w() - (*i1)->w(); + else return (*i0)->h() - (*i1)->h(); +} + + +// +// 'Fl_Shared_Image::Fl_Shared_Image()' - Basic constructor. +// + +Fl_Shared_Image::Fl_Shared_Image() : Fl_Image(0,0,0) { + name_ = 0; + refcount_ = 1; + original_ = 0; + image_ = 0; + alloc_image_ = 0; +} + + +// +// 'Fl_Shared_Image::Fl_Shared_Image()' - Add an image to the image cache. +// + +Fl_Shared_Image::Fl_Shared_Image(const char *n, // I - Filename + Fl_Image *img) // I - Image + : Fl_Image(0,0,0) { + name_ = new char[strlen(n) + 1]; + strcpy((char *)name_, n); + + refcount_ = 1; + image_ = img; + alloc_image_ = !img; + original_ = 1; + + if (!img) reload(); + else update(); +} + + +// +// 'Fl_Shared_Image::add()' - Add a shared image to the array. +// + +void +Fl_Shared_Image::add() { + Fl_Shared_Image **temp; // New image pointer array... + + if (num_images_ >= alloc_images_) { + // Allocate more memory... + temp = new Fl_Shared_Image *[alloc_images_ + 32]; + + if (alloc_images_) { + memcpy(temp, images_, alloc_images_ * sizeof(Fl_Shared_Image *)); + + delete[] images_; + } + + images_ = temp; + alloc_images_ += 32; + } + + images_[num_images_] = this; + num_images_ ++; + + if (num_images_ > 1) { + qsort(images_, num_images_, sizeof(Fl_Shared_Image *), + (compare_func_t)compare); + } +} + + +// +// 'Fl_Shared_Image::update()' - Update the dimensions of the shared images. +// + +void +Fl_Shared_Image::update() { + if (image_) { + w(image_->w()); + h(image_->h()); + d(image_->d()); + data(image_->data(), image_->count()); + } +} + + +// +// 'Fl_Shared_Image::~Fl_Shared_Image()' - Destroy a shared image... +// + +Fl_Shared_Image::~Fl_Shared_Image() { + if (name_) delete[] (char *)name_; + if (alloc_image_) delete image_; +} + + +// +// 'Fl_Shared_Image::release()' - Release and possibly destroy a shared image. +// + +void +Fl_Shared_Image::release() { + int i; // Looping var... + + refcount_ --; + if (refcount_ > 0) return; + + for (i = 0; i < num_images_; i ++) + if (images_[i] == this) { + num_images_ --; + + if (i < num_images_) { + memmove(images_ + i, images_ + i + 1, + (num_images_ - i) * sizeof(Fl_Shared_Image *)); + } + + break; + } + + delete this; + + if (num_images_ == 0 && images_) { + delete[] images_; + + images_ = 0; + alloc_images_ = 0; + } +} + + +// +// 'Fl_Shared_Image::reload()' - Reload the shared image... +// + +void +Fl_Shared_Image::reload() { + // Load image from disk... + int i; // Looping var + FILE *fp; // File pointer + uchar header[64]; // Buffer for auto-detecting files + Fl_Image *img; // New image + + if (!name_) return; + + if ((fp = fopen(name_, "rb")) != NULL) { + fread(header, 1, sizeof(header), fp); + fclose(fp); + } else { + memset(header, 0, sizeof(header)); + } + + // Load the image as appropriate... + if (memcmp(header, "#define", 7) == 0) // XBM file + img = new Fl_XBM_Image(name_); + else if (memcmp(header, "/* XPM */", 9) == 0) // XPM file + img = new Fl_XPM_Image(name_); + else { + // Not a standard format; try an image handler... + for (i = 0, img = 0; i < num_handlers_; i ++) { + img = (handlers_[i])(name_, header, sizeof(header)); + + if (img) break; + } + } + + if (img) { + if (alloc_image_) delete image_; + + alloc_image_ = 1; + + if ((img->w() != w() && w()) || (img->h() != h() && h())) { + // Make sure the reloaded image is the same size as the existing one. + Fl_Image *temp = img->copy(w(), h()); + delete img; + image_ = temp; + } else { + image_ = img; + } + + update(); + } +} + + +// +// 'Fl_Shared_Image::copy()' - Copy and resize a shared image... +// + +Fl_Image * +Fl_Shared_Image::copy(int W, int H) { + Fl_Image *temp_image; // New image file + Fl_Shared_Image *temp_shared; // New shared image + + // Make a copy of the image we're sharing... + if (!image_) temp_image = 0; + else temp_image = image_->copy(W, H); + + // Then make a new shared image... + temp_shared = new Fl_Shared_Image(); + + temp_shared->name_ = new char[strlen(name_) + 1]; + strcpy((char *)temp_shared->name_, name_); + + temp_shared->refcount_ = 1; + temp_shared->image_ = temp_image; + temp_shared->alloc_image_ = 1; + + temp_shared->update(); + + return temp_shared; +} + + +// +// 'Fl_Shared_Image::color_average()' - Blend colors... +// + +void +Fl_Shared_Image::color_average(Fl_Color c, // I - Color to blend with + float i) { // I - Blend fraction + if (!image_) return; + + image_->color_average(c, i); + update(); +} + + +// +// 'Fl_Shared_Image::desaturate()' - Convert the image to grayscale... +// + +void +Fl_Shared_Image::desaturate() { + if (!image_) return; + + image_->desaturate(); + update(); +} + + +// +// 'Fl_Shared_Image::draw()' - Draw a shared image... +// + +void +Fl_Shared_Image::draw(int X, int Y, int W, int H, int cx, int cy) { + if (image_) image_->draw(X, Y, W, H, cx, cy); + else Fl_Image::draw(X, Y, W, H, cx, cy); +} + + +// +// 'Fl_Shared_Image::uncache()' - Uncache the shared image... +// + +void +Fl_Shared_Image::uncache() +{ + if (image_) image_->uncache(); +} + + +// +// 'Fl_Shared_Image::find()' - Find a shared image... +// + +Fl_Shared_Image * +Fl_Shared_Image::find(const char *n, int W, int H) { + Fl_Shared_Image *key, // Image key + **match; // Matching image + + if (num_images_) { + key = new Fl_Shared_Image(); + key->name_ = new char[strlen(n) + 1]; + strcpy((char *)key->name_, n); + key->w(W); + key->h(H); + + match = (Fl_Shared_Image **)bsearch(&key, images_, num_images_, + sizeof(Fl_Shared_Image *), + (compare_func_t)compare); + + delete key; + + if (match) { + (*match)->refcount_ ++; + return *match; + } + } + + return 0; +} + + +// +// 'Fl_Shared_Image::get()' - Get a shared image... +// + +Fl_Shared_Image * +Fl_Shared_Image::get(const char *n, int W, int H) { + Fl_Shared_Image *temp; // Image + + if ((temp = find(n, W, H)) != NULL) return temp; + + if ((temp = find(n)) == NULL) { + temp = new Fl_Shared_Image(n); + + if (!temp->image_) { + delete temp; + return NULL; + } + + temp->add(); + } + + if ((temp->w() != W || temp->h() != H) && W && H) { + temp = (Fl_Shared_Image *)temp->copy(W, H); + temp->add(); + } + + return temp; +} + + +// +// 'Fl_Shared_Image::add_handler()' - Add a shared image handler. +// + +void +Fl_Shared_Image::add_handler(Fl_Shared_Handler f) { + int i; // Looping var... + Fl_Shared_Handler *temp; // New image handler array... + + // First see if we have already added the handler... + for (i = 0; i < num_handlers_; i ++) { + if (handlers_[i] == f) return; + } + + if (num_handlers_ >= alloc_handlers_) { + // Allocate more memory... + temp = new Fl_Shared_Handler [alloc_handlers_ + 32]; + + if (alloc_handlers_) { + memcpy(temp, handlers_, alloc_handlers_ * sizeof(Fl_Shared_Handler)); + + delete[] handlers_; + } + + handlers_ = temp; + alloc_handlers_ += 32; + } + + handlers_[num_handlers_] = f; + num_handlers_ ++; +} + + +// +// 'Fl_Shared_Image::remove_handler()' - Remove a shared image handler. +// + +void +Fl_Shared_Image::remove_handler(Fl_Shared_Handler f) { + int i; // Looping var... + + // First see if the handler has been added... + for (i = 0; i < num_handlers_; i ++) { + if (handlers_[i] == f) break; + } + + if (i >= num_handlers_) return; + + // OK, remove the handler from the array... + num_handlers_ --; + + if (i < num_handlers_) { + // Shift later handlers down 1... + memmove(handlers_ + i, handlers_ + i + 1, + (num_handlers_ - i) * sizeof(Fl_Shared_Handler )); + } +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Single_Window.cxx b/Utilities/FLTK/src/Fl_Single_Window.cxx new file mode 100644 index 0000000000..6392df1c8e --- /dev/null +++ b/Utilities/FLTK/src/Fl_Single_Window.cxx @@ -0,0 +1,41 @@ +// +// "$Id$" +// +// Single-buffered window for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// A window with a single-buffered context +// +// This is provided for systems where the base class is double +// buffered. You can turn it off using this subclass in case +// your display looks better without it. + +#include <FL/Fl_Single_Window.H> + +void Fl_Single_Window::show() {Fl_Window::show();} +void Fl_Single_Window::flush() {Fl_Window::flush();} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Slider.cxx b/Utilities/FLTK/src/Fl_Slider.cxx new file mode 100644 index 0000000000..0b58e924f8 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Slider.cxx @@ -0,0 +1,295 @@ +// +// "$Id$" +// +// Slider widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Slider.H> +#include <FL/fl_draw.H> +#include <math.h> + +void Fl_Slider::_Fl_Slider() { + slider_size_ = 0; + slider_ = 0; // FL_UP_BOX; +} + +Fl_Slider::Fl_Slider(int X, int Y, int W, int H, const char* l) +: Fl_Valuator(X, Y, W, H, l) { + box(FL_DOWN_BOX); + _Fl_Slider(); +} + +Fl_Slider::Fl_Slider(uchar t, int X, int Y, int W, int H, const char* l) + : Fl_Valuator(X, Y, W, H, l) { + type(t); + box(t==FL_HOR_NICE_SLIDER || t==FL_VERT_NICE_SLIDER ? + FL_FLAT_BOX : FL_DOWN_BOX); + _Fl_Slider(); +} + +void Fl_Slider::slider_size(double v) { + if (v < 0) v = 0; + if (v > 1) v = 1; + if (slider_size_ != float(v)) { + slider_size_ = float(v); + damage(FL_DAMAGE_EXPOSE); + } +} + +void Fl_Slider::bounds(double a, double b) { + if (minimum() != a || maximum() != b) { + Fl_Valuator::bounds(a, b); + damage(FL_DAMAGE_EXPOSE); + } +} + +int Fl_Slider::scrollvalue(int p, int W, int t, int l) { +// p = position, first line displayed +// w = window, number of lines displayed +// t = top, number of first line +// l = length, total number of lines + step(1, 1); + if (p+W > t+l) l = p+W-t; + slider_size(W >= l ? 1.0 : double(W)/double(l)); + bounds(t, l-W+t); + return value(p); +} + +// All slider interaction is done as though the slider ranges from +// zero to one, and the left (bottom) edge of the slider is at the +// given position. Since when the slider is all the way to the +// right (top) the left (bottom) edge is not all the way over, a +// position on the widget itself covers a wider range than 0-1, +// actually it ranges from 0 to 1/(1-size). + +void Fl_Slider::draw_bg(int X, int Y, int W, int H) { + fl_push_clip(X, Y, W, H); + draw_box(); + fl_pop_clip(); + + Fl_Color black = active_r() ? FL_FOREGROUND_COLOR : FL_INACTIVE_COLOR; + if (type() == FL_VERT_NICE_SLIDER) { + draw_box(FL_THIN_DOWN_BOX, X+W/2-2, Y, 4, H, black); + } else if (type() == FL_HOR_NICE_SLIDER) { + draw_box(FL_THIN_DOWN_BOX, X, Y+H/2-2, W, 4, black); + } +} + +void Fl_Slider::draw(int X, int Y, int W, int H) { + + double val; + if (minimum() == maximum()) + val = 0.5; + else { + val = (value()-minimum())/(maximum()-minimum()); + if (val > 1.0) val = 1.0; + else if (val < 0.0) val = 0.0; + } + + int ww = (horizontal() ? W : H); + int xx, S; + if (type()==FL_HOR_FILL_SLIDER || type() == FL_VERT_FILL_SLIDER) { + S = int(val*ww+.5); + if (minimum()>maximum()) {S = ww-S; xx = ww-S;} + else xx = 0; + } else { + S = int(slider_size_*ww+.5); + int T = (horizontal() ? H : W)/2+1; + if (type()==FL_VERT_NICE_SLIDER || type()==FL_HOR_NICE_SLIDER) T += 4; + if (S < T) S = T; + xx = int(val*(ww-S)+.5); + } + int xsl, ysl, wsl, hsl; + if (horizontal()) { + xsl = X+xx; + wsl = S; + ysl = Y; + hsl = H; + } else { + ysl = Y+xx; + hsl = S; + xsl = X; + wsl = W; + } + + draw_bg(X, Y, W, H); + + Fl_Boxtype box1 = slider(); + if (!box1) {box1 = (Fl_Boxtype)(box()&-2); if (!box1) box1 = FL_UP_BOX;} + if (type() == FL_VERT_NICE_SLIDER) { + draw_box(box1, xsl, ysl, wsl, hsl, FL_GRAY); + int d = (hsl-4)/2; + draw_box(FL_THIN_DOWN_BOX, xsl+2, ysl+d, wsl-4, hsl-2*d,selection_color()); + } else if (type() == FL_HOR_NICE_SLIDER) { + draw_box(box1, xsl, ysl, wsl, hsl, FL_GRAY); + int d = (wsl-4)/2; + draw_box(FL_THIN_DOWN_BOX, xsl+d, ysl+2, wsl-2*d, hsl-4,selection_color()); + } else { + if (wsl>0 && hsl>0) draw_box(box1, xsl, ysl, wsl, hsl, selection_color()); + } + + draw_label(xsl, ysl, wsl, hsl); + if (Fl::focus() == this) { + if (type() == FL_HOR_FILL_SLIDER || type() == FL_VERT_FILL_SLIDER) draw_focus(); + else draw_focus(box1, xsl, ysl, wsl, hsl); + } +} + +void Fl_Slider::draw() { + if (damage()&FL_DAMAGE_ALL) draw_box(); + draw(x()+Fl::box_dx(box()), + y()+Fl::box_dy(box()), + w()-Fl::box_dw(box()), + h()-Fl::box_dh(box())); +} + +int Fl_Slider::handle(int event, int X, int Y, int W, int H) { + switch (event) { + case FL_PUSH: + if (!Fl::event_inside(X, Y, W, H)) return 0; + handle_push(); + case FL_DRAG: { + + double val; + if (minimum() == maximum()) + val = 0.5; + else { + val = (value()-minimum())/(maximum()-minimum()); + if (val > 1.0) val = 1.0; + else if (val < 0.0) val = 0.0; + } + + int ww = (horizontal() ? W : H); + int mx = (horizontal() ? Fl::event_x()-X : Fl::event_y()-Y); + int S; + static int offcenter; + + if (type() == FL_HOR_FILL_SLIDER || type() == FL_VERT_FILL_SLIDER) { + + S = 0; + if (event == FL_PUSH) { + int xx = int(val*ww+.5); + offcenter = mx-xx; + if (offcenter < -10 || offcenter > 10) offcenter = 0; + else return 1; + } + + } else { + + S = int(slider_size_*ww+.5); if (S >= ww) return 0; + int T = (horizontal() ? H : W)/2+1; + if (type()==FL_VERT_NICE_SLIDER || type()==FL_HOR_NICE_SLIDER) T += 4; + if (S < T) S = T; + if (event == FL_PUSH) { + int xx = int(val*(ww-S)+.5); + offcenter = mx-xx; + if (offcenter < 0) offcenter = 0; + else if (offcenter > S) offcenter = S; + else return 1; + } + } + + int xx = mx-offcenter; + double v; + char tryAgain = 1; + while (tryAgain) + { + tryAgain = 0; + if (xx < 0) { + xx = 0; + offcenter = mx; if (offcenter < 0) offcenter = 0; + } else if (xx > (ww-S)) { + xx = ww-S; + offcenter = mx-xx; if (offcenter > S) offcenter = S; + } + v = round(xx*(maximum()-minimum())/(ww-S) + minimum()); + // make sure a click outside the sliderbar moves it: + if (event == FL_PUSH && v == value()) { + offcenter = S/2; + event = FL_DRAG; + tryAgain = 1; + } + } + handle_drag(clamp(v)); + } return 1; + case FL_RELEASE: + handle_release(); + return 1; + case FL_KEYBOARD : + switch (Fl::event_key()) { + case FL_Up: + if (horizontal()) return 0; + handle_drag(clamp(increment(value(),-1))); + handle_release(); + return 1; + case FL_Down: + if (horizontal()) return 0; + handle_drag(clamp(increment(value(),1))); + handle_release(); + return 1; + case FL_Left: + if (!horizontal()) return 0; + handle_drag(clamp(increment(value(),-1))); + handle_release(); + return 1; + case FL_Right: + if (!horizontal()) return 0; + handle_drag(clamp(increment(value(),1))); + handle_release(); + return 1; + default: + return 0; + } + // break not required because of switch... + case FL_FOCUS : + case FL_UNFOCUS : + if (Fl::visible_focus()) { + redraw(); + return 1; + } else return 0; + case FL_ENTER : + case FL_LEAVE : + return 1; + default: + return 0; + } +} + +int Fl_Slider::handle(int event) { + if (event == FL_PUSH && Fl::visible_focus()) { + Fl::focus(this); + redraw(); + } + + return handle(event, + x()+Fl::box_dx(box()), + y()+Fl::box_dy(box()), + w()-Fl::box_dw(box()), + h()-Fl::box_dh(box())); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Sys_Menu_Bar.cxx b/Utilities/FLTK/src/Fl_Sys_Menu_Bar.cxx new file mode 100644 index 0000000000..0026899175 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Sys_Menu_Bar.cxx @@ -0,0 +1,329 @@ +// +// "$Id$" +// +// MacOS system menu bar widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/** + * This code is a quick hack! It was written as a proof of concept. + * It has been tested on the "menubar" sample program and provides + * basic functionality. + * + * To use the System Menu Bar, simply replace the main Fl_Menu_Bar + * in an application with Fl_Sys_Menu_Bar. + * + * FLTK features not supported by the Mac System menu + * + * - no invisible menu items + * - no sybolic labels + * - embossed labels will be underlined instead + * - no font sizes + * - Shortcut Characters should be English alphanumeric only, no modifiers yet + * - no disable main menus + * - changes to menubar in run-time don't update! + * (disable, etc. - toggle and readio button do!) + * + * No care was taken to clean up the menu bar after destruction! + * ::menu(bar) should only be called once! + * Many other calls of the parent class don't work. + * Changing the menu items has no effect on the menu bar. + */ + +#if defined(__APPLE__) + +#include <FL/x.H> +#include <FL/Fl.H> +#include <FL/Fl_Sys_Menu_Bar.H> + +#include "flstring.h" +#include <stdio.h> +#include <ctype.h> + +typedef const Fl_Menu_Item *pFl_Menu_Item; + +/** + * copy the text of a menuitem into a buffer. + * Skip all '&' which would mark the shortcut in FLTK + * Skip all Mac control characters ('(', '<', ';', '^', '!' ) + */ +static void catMenuText( const char *src, char *dst ) +{ + char c; + while ( *dst ) + dst++; + if ( *src == '-' ) + src++; + while ( ( c = *src++ ) ) + { + if ( !strchr( "&(<;^!", c ) ) + *dst++ = c; + } + *dst = 0; +} + +/** + * append a marker to identify the menu font style + * <B, I, U, O, and S + */ +static void catMenuFont( const Fl_Menu_Item *m, char *dst ) +{ + if ( !m->labeltype_ && !m->labelfont_ ) + return; + while ( *dst ) + dst++; + + if ( m->labelfont_ & FL_BOLD ) + strcat( dst, "<B" ); + if ( m->labelfont_ & FL_ITALIC ) + strcat( dst, "<I" ); + //if ( m->labelfont_ & FL_UNDERLINE ) + // strcat( dst, "<U" ); + + if ( m->labeltype_ == FL_EMBOSSED_LABEL ) + strcat( dst, "<U" ); + else if ( m->labeltype_ == FL_ENGRAVED_LABEL ) + strcat( dst, "<O" ); + else if ( m->labeltype_ == FL_SHADOW_LABEL ) + strcat( dst, "<S" ); + //else if ( m->labeltype_ == FL_SYMBOL_LABEL ) + ; // not supported +} + +/** + * append a marker to identify the menu shortcut + * <B, I, U, O, and S +enum { + kMenuNoModifiers = 0, + kMenuShiftModifier = (1 << 0), + kMenuOptionModifier = (1 << 1), + kMenuControlModifier = (1 << 2), + kMenuNoCommandModifier = (1 << 3) +}; + */ +static void setMenuShortcut( MenuHandle mh, int miCnt, const Fl_Menu_Item *m ) +{ + if ( !m->shortcut_ ) + return; + if ( m->flags & FL_SUBMENU ) + return; + if ( m->flags & FL_SUBMENU_POINTER ) + return; + char key = m->shortcut_ & 0xff; + if ( !isalnum( key ) ) + return; + + long macMod = kMenuNoCommandModifier; + if ( m->shortcut_ & FL_META ) macMod = kMenuNoModifiers; + if ( m->shortcut_ & FL_SHIFT || isupper(key) ) macMod |= kMenuShiftModifier; + if ( m->shortcut_ & FL_ALT ) macMod |= kMenuOptionModifier; + if ( m->shortcut_ & FL_CTRL ) macMod |= kMenuControlModifier; + + //SetMenuItemKeyGlyph( mh, miCnt, key ); + SetItemCmd( mh, miCnt, toupper(key) ); + SetMenuItemModifiers( mh, miCnt, macMod ); +} + +#if 0 +// this function needs to be verified before we compile it back in. +static void catMenuShortcut( const Fl_Menu_Item *m, char *dst ) +{ + if ( !m->shortcut_ ) + return; + char c = m->shortcut_ & 0xff; + if ( !isalnum( c & 0xff ) ) + return; + while ( *dst ) + dst++; + if ( m->shortcut_ & FL_CTRL ) + { + sprintf( dst, "/%c", toupper( c ) ); + } + //if ( isalnum( mm->shortcut_ ) && !( mm->flags & FL_SUBMENU ) ) + //sprintf( buf+strlen(buf), "/%c", mm->shortcut_ ); +} +#endif + +static void setMenuFlags( MenuHandle mh, int miCnt, const Fl_Menu_Item *m ) +{ + if ( m->flags & FL_MENU_TOGGLE ) + { + SetItemMark( mh, miCnt, ( m->flags & FL_MENU_VALUE ) ? 0x12 : 0 ); + } + else if ( m->flags & FL_MENU_RADIO ) + SetItemMark( mh, miCnt, ( m->flags & FL_MENU_VALUE ) ? 0x13 : 0 ); +} + +static void catMenuFlags( const Fl_Menu_Item *m, char *dst ) +{ + if ( !m->flags ) + return; + while ( *dst ) + dst++; + if ( m->flags & FL_MENU_INACTIVE ) + strcat( dst, "(" ); +} + +/** + * create a sub menu for a specific menu handle + */ +static void createSubMenu( MenuHandle mh, int &cnt, pFl_Menu_Item &mm ) +{ + char buf[255]; + int miCnt = 1; + while ( mm->text ) + { + MenuHandle smh = 0; + buf[1] = 0; + catMenuFont( mm, buf+1 ); + //catMenuShortcut( mm, buf+1 ); + catMenuText( mm->text, buf+1 ); + catMenuFlags( mm, buf+1 ); + if ( mm->flags & (FL_SUBMENU | FL_SUBMENU_POINTER) ) + { + cnt++; + smh = NewMenu( cnt, (unsigned char*)"\001 " ); + sprintf( buf+1+strlen(buf+1), "/\033!%c", cnt ); + } + if ( mm->flags & FL_MENU_DIVIDER ) + strcat( buf+1, ";-" ); + buf[0] = strlen( buf+1 ); + AppendMenu( mh, (unsigned char*)buf ); + // insert Appearanc manager functions here! + setMenuFlags( mh, miCnt, mm ); + setMenuShortcut( mh, miCnt, mm ); + SetMenuItemRefCon( mh, miCnt, (UInt32)mm ); + miCnt++; + if ( mm->flags & FL_MENU_DIVIDER ) + miCnt++; + if ( mm->flags & FL_SUBMENU ) + { + createSubMenu( smh, cnt, ++mm ); + } + else if ( mm->flags & FL_SUBMENU_POINTER ) + { + const Fl_Menu_Item *smm = (Fl_Menu_Item*)mm->user_data_; + createSubMenu( mh, cnt, smm ); + } + mm++; + } + InsertMenu( mh, -1 ); +} + + +/** + * create a system menu bar using the given list of menu structs + * + * \author Matthias Melcher + * + * @param m list of Fl_Menu_Item + */ +void Fl_Sys_Menu_Bar::menu(const Fl_Menu_Item *m) +{ + fl_open_display(); + Fl_Menu_Bar::menu( m ); + fl_sys_menu_bar = this; + + char buf[255]; + int cnt = 1; // first menu is no 2. no 1 is the Apple Menu + + const Fl_Menu_Item *mm = m; + for (;;) + { + if ( !mm->text ) + break; + buf[1] = 0; + catMenuText( mm->text, buf+1 ); + buf[0] = strlen( buf+1 ); + MenuHandle mh = NewMenu( ++cnt, (unsigned char*)buf ); + if ( mm->flags & FL_SUBMENU ) + createSubMenu( mh, cnt, ++mm ); + else if ( mm->flags & FL_SUBMENU_POINTER ) + { + const Fl_Menu_Item *smm = (Fl_Menu_Item*)mm->user_data_; + createSubMenu( mh, cnt, smm ); + } + + InsertMenu( mh, 0 ); + if ( mm->flags & FL_MENU_INACTIVE ) DisableMenuItem( mh, 0 ); + mm++; + } + DrawMenuBar(); +} + +/* +const Fl_Menu_Item* Fl_Sys_Menu_Bar::picked(const Fl_Menu_Item* v) { + Fl_menu_Item *ret = Fl_Menu_Bar::picked( v ); + + if ( m->flags & FL_MENU_TOGGLE ) + { + SetItemMark( mh, miCnt, ( m->flags & FL_MENU_VALUE ) ? 0x12 : 0 ); + } + + return ret; +} +*/ + +void Fl_Sys_Menu_Bar::draw() { +/* -- nothing to do, system should take care of this + draw_box(); + if (!menu() || !menu()->text) return; + const Fl_Menu_Item* m; + int X = x()+6; + for (m=menu(); m->text; m = m->next()) { + int W = m->measure(0,this) + 16; + m->draw(X, y(), W, h(), this); + X += W; + } + */ +} + +/* +int Fl_Menu_Bar::handle(int event) { + const Fl_Menu_Item* v; + if (menu() && menu()->text) switch (event) { + case FL_ENTER: + case FL_LEAVE: + return 1; + case FL_PUSH: + v = 0; + J1: + v = menu()->pulldown(x(), y(), w(), h(), v, this, 0, 1); + picked(v); + return 1; + case FL_SHORTCUT: + if (visible_r()) { + v = menu()->find_shortcut(); + if (v && v->submenu()) goto J1; + } + return test_shortcut() != 0; + } + return 0; +} +*/ + +#endif /* __APPLE__ */ + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Tabs.cxx b/Utilities/FLTK/src/Fl_Tabs.cxx new file mode 100644 index 0000000000..59c06b4d59 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Tabs.cxx @@ -0,0 +1,353 @@ +// +// "$Id$" +// +// Tab widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// This is the "file card tabs" interface to allow you to put lots and lots +// of buttons and switches in a panel, as popularized by many toolkits. + +// Each child widget is a card, and it's label() is printed on the card tab. +// Clicking the tab makes that card visible. + +#include <stdio.h> +#include <FL/Fl.H> +#include <FL/Fl_Tabs.H> +#include <FL/fl_draw.H> + +#define BORDER 2 +#define EXTRASPACE 10 + +// return the left edges of each tab (plus a fake left edge for a tab +// past the right-hand one). These position are actually of the left +// edge of the slope. They are either seperated by the correct distance +// or by EXTRASPACE or by zero. +// Return value is the index of the selected item. + +int Fl_Tabs::tab_positions(int* p, int* wp) { + int selected = 0; + Fl_Widget*const* a = array(); + int i; + p[0] = Fl::box_dx(box()); + for (i=0; i<children(); i++) { + Fl_Widget* o = *a++; + if (o->visible()) selected = i; + + int wt = 0; int ht = 0; + o->measure_label(wt,ht); + + wp[i] = wt+EXTRASPACE; + p[i+1] = p[i]+wp[i]+BORDER; + } + int r = w(); + if (p[i] <= r) return selected; + // uh oh, they are too big: + // pack them against right edge: + p[i] = r; + for (i = children(); i--;) { + int l = r-wp[i]; + if (p[i+1] < l) l = p[i+1]; + if (p[i] <= l) break; + p[i] = l; + r -= EXTRASPACE; + } + // pack them against left edge and truncate width if they still don't fit: + for (i = 0; i<children(); i++) { + if (p[i] >= i*EXTRASPACE) break; + p[i] = i*EXTRASPACE; + int W = w()-1-EXTRASPACE*(children()-i) - p[i]; + if (wp[i] > W) wp[i] = W; + } + // adjust edges according to visiblity: + for (i = children(); i > selected; i--) { + p[i] = p[i-1]+wp[i-1]; + } + return selected; +} + +// return space needed for tabs. Negative to put them on the bottom: +int Fl_Tabs::tab_height() { + int H = h(); + int H2 = y(); + Fl_Widget*const* a = array(); + for (int i=children(); i--;) { + Fl_Widget* o = *a++; + if (o->y() < y()+H) H = o->y()-y(); + if (o->y()+o->h() > H2) H2 = o->y()+o->h(); + } + H2 = y()+h()-H2; + if (H2 > H) return (H2 <= 0) ? 0 : -H2; + else return (H <= 0) ? 0 : H; +} + +// this is used by fluid to pick tabs: +Fl_Widget *Fl_Tabs::which(int event_x, int event_y) { + int H = tab_height(); + if (H < 0) { + if (event_y > y()+h() || event_y < y()+h()+H) return 0; + } else { + if (event_y > y()+H || event_y < y()) return 0; + } + if (event_x < x()) return 0; + int p[128], wp[128]; + tab_positions(p, wp); + for (int i=0; i<children(); i++) { + if (event_x < x()+p[i+1]) return child(i); + } + return 0; +} + +int Fl_Tabs::handle(int event) { + + Fl_Widget *o; + int i; + + switch (event) { + + case FL_PUSH: { + int H = tab_height(); + if (H >= 0) { + if (Fl::event_y() > y()+H) return Fl_Group::handle(event); + } else { + if (Fl::event_y() < y()+h()+H) return Fl_Group::handle(event); + }} + case FL_DRAG: + case FL_RELEASE: + o = which(Fl::event_x(), Fl::event_y()); + if (event == FL_RELEASE) { + push(0); + if (o && value(o)) { + set_changed(); + do_callback(); + } + } else push(o); + if (Fl::visible_focus() && event == FL_RELEASE) Fl::focus(this); + return 1; + case FL_FOCUS: + case FL_UNFOCUS: + if (!Fl::visible_focus()) return Fl_Group::handle(event); + if (Fl::event() == FL_RELEASE || + Fl::event() == FL_SHORTCUT || + Fl::event() == FL_KEYBOARD || + Fl::event() == FL_FOCUS || + Fl::event() == FL_UNFOCUS) { + int H = tab_height(); + if (H >= 0) { + H += Fl::box_dy(box()); + damage(FL_DAMAGE_SCROLL, x(), y(), w(), H); + } else { + H = Fl::box_dy(box()) - H; + damage(FL_DAMAGE_SCROLL, x(), y() + h() - H, w(), H); + } + if (Fl::event() == FL_FOCUS || Fl::event() == FL_UNFOCUS) return 0; + else return 1; + } else return Fl_Group::handle(event); + case FL_KEYBOARD: + switch (Fl::event_key()) { + case FL_Left: + if (child(0)->visible()) return 0; + for (i = 1; i < children(); i ++) + if (child(i)->visible()) break; + value(child(i - 1)); + set_changed(); + do_callback(); + return 1; + case FL_Right: + if (child(children() - 1)->visible()) return 0; + for (i = 0; i < children(); i ++) + if (child(i)->visible()) break; + value(child(i + 1)); + set_changed(); + do_callback(); + return 1; + case FL_Down: + redraw(); + return Fl_Group::handle(FL_FOCUS); + default: + break; + } + case FL_SHOW: + value(); // update visibilities and fall through + default: + return Fl_Group::handle(event); + + } +} + +int Fl_Tabs::push(Fl_Widget *o) { + if (push_ == o) return 0; + if (push_ && !push_->visible() || o && !o->visible()) + redraw(); + push_ = o; + return 1; +} + +// The value() is the first visible child (or the last child if none +// are visible) and this also hides any other children. +// This allows the tabs to be deleted, moved to other groups, and +// show()/hide() called without it screwing up. +Fl_Widget* Fl_Tabs::value() { + Fl_Widget* v = 0; + Fl_Widget*const* a = array(); + for (int i=children(); i--;) { + Fl_Widget* o = *a++; + if (v) o->hide(); + else if (o->visible()) v = o; + else if (!i) {o->show(); v = o;} + } + return v; +} + +// Setting the value hides all other children, and makes this one +// visible, iff it is really a child: +int Fl_Tabs::value(Fl_Widget *newvalue) { + Fl_Widget*const* a = array(); + int ret = 0; + for (int i=children(); i--;) { + Fl_Widget* o = *a++; + if (o == newvalue) { + if (!o->visible()) ret = 1; + o->show(); + } else { + o->hide(); + } + } + return ret; +} + +enum {LEFT, RIGHT, SELECTED}; + +void Fl_Tabs::draw() { + Fl_Widget *v = value(); + int H = tab_height(); + + if (damage() & FL_DAMAGE_ALL) { // redraw the entire thing: + Fl_Color c = v ? v->color() : color(); + + draw_box(box(), x(), y()+(H>=0?H:0), w(), h()-(H>=0?H:-H), c); + + if (selection_color() != c) { + // Draw the top 5 lines of the tab pane in the selection color so + // that the user knows which tab is selected... + if (H >= 0) fl_push_clip(x(), y() + H, w(), 5); + else fl_push_clip(x(), y() + h() - H - 4, w(), 5); + + draw_box(box(), x(), y()+(H>=0?H:0), w(), h()-(H>=0?H:-H), + selection_color()); + + fl_pop_clip(); + } + if (v) draw_child(*v); + } else { // redraw the child + if (v) update_child(*v); + } + if (damage() & (FL_DAMAGE_SCROLL|FL_DAMAGE_ALL)) { + int p[128]; int wp[128]; + int selected = tab_positions(p,wp); + int i; + Fl_Widget*const* a = array(); + for (i=0; i<selected; i++) + draw_tab(x()+p[i], x()+p[i+1], wp[i], H, a[i], LEFT); + for (i=children()-1; i > selected; i--) + draw_tab(x()+p[i], x()+p[i+1], wp[i], H, a[i], RIGHT); + if (v) { + i = selected; + draw_tab(x()+p[i], x()+p[i+1], wp[i], H, a[i], SELECTED); + } + } +} + +void Fl_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) { + int sel = (what == SELECTED); + int dh = Fl::box_dh(box()); + int dy = Fl::box_dy(box()); + + // compute offsets to make selected tab look bigger + int yofs = sel ? 0 : BORDER; + + if ((x2 < x1+W) && what == RIGHT) x1 = x2 - W; + + if (H >= 0) { + if (sel) fl_clip(x1, y(), x2 - x1, H + dh - dy); + else fl_clip(x1, y(), x2 - x1, H); + + H += dh; + + Fl_Color c = sel ? selection_color() : o->selection_color(); + + draw_box(box(), x1, y() + yofs, W, H + 10 - yofs, c); + + // Save the previous label color + Fl_Color oc = o->labelcolor(); + + // Draw the label using the current color... + o->labelcolor(sel ? labelcolor() : o->labelcolor()); + o->draw_label(x1, y() + yofs, W, H - yofs, FL_ALIGN_CENTER); + + // Restore the original label color... + o->labelcolor(oc); + + if (Fl::focus() == this && o->visible()) + draw_focus(box(), x1, y(), W, H); + + fl_pop_clip(); + } else { + H = -H; + + if (sel) fl_clip(x1, y() + h() - H - dy, x2 - x1, H + dy); + else fl_clip(x1, y() + h() - H, x2 - x1, H); + + H += dh; + + Fl_Color c = sel ? selection_color() : o->selection_color(); + + draw_box(box(), x1, y() + h() - H - 10, W, H + 10 - yofs, c); + + // Save the previous label color + Fl_Color oc = o->labelcolor(); + + // Draw the label using the current color... + o->labelcolor(sel ? labelcolor() : o->labelcolor()); + o->draw_label(x1, y() + h() - H, W, H - yofs, FL_ALIGN_CENTER); + + // Restore the original label color... + o->labelcolor(oc); + + if (Fl::focus() == this && o->visible()) + draw_focus(box(), x1, y() + h() - H, W, H); + + fl_pop_clip(); + } +} + +Fl_Tabs::Fl_Tabs(int X,int Y,int W, int H, const char *l) : + Fl_Group(X,Y,W,H,l) +{ + box(FL_THIN_UP_BOX); + push_ = 0; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Text_Buffer.cxx b/Utilities/FLTK/src/Fl_Text_Buffer.cxx new file mode 100644 index 0000000000..7495be19ad --- /dev/null +++ b/Utilities/FLTK/src/Fl_Text_Buffer.cxx @@ -0,0 +1,2524 @@ +// +// "$Id$" +// +// Copyright 2001-2005 by Bill Spitzak and others. +// Original code Copyright Mark Edel. Permission to distribute under +// the LGPL for the FLTK library granted by Mark Edel. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <stdio.h> +#include <stdlib.h> +#include "flstring.h" +#include <ctype.h> +#include <FL/Fl.H> +#include <FL/Fl_Text_Buffer.H> + + +#define PREFERRED_GAP_SIZE 80 +/* Initial size for the buffer gap (empty space +in the buffer where text might be inserted +if the user is typing sequential chars ) */ + +static void histogramCharacters( const char *string, int length, char hist[ 256 ], + int init ); +static void subsChars( char *string, int length, char fromChar, char toChar ); +static char chooseNullSubsChar( char hist[ 256 ] ); +static void insertColInLine( const char *line, char *insLine, int column, int insWidth, + int tabDist, int useTabs, char nullSubsChar, char *outStr, int *outLen, + int *endOffset ); +static void deleteRectFromLine( const char *line, int rectStart, int rectEnd, + int tabDist, int useTabs, char nullSubsChar, char *outStr, int *outLen, + int *endOffset ); +static void overlayRectInLine( const char *line, char *insLine, int rectStart, + int rectEnd, int tabDist, int useTabs, char nullSubsChar, char *outStr, + int *outLen, int *endOffset ); + +static void addPadding( char *string, int startIndent, int toIndent, + int tabDist, int useTabs, char nullSubsChar, int *charsAdded ); +static char *copyLine( const char* text, int *lineLen ); +static int countLines( const char *string ); +static int textWidth( const char *text, int tabDist, char nullSubsChar ); +static char *realignTabs( const char *text, int origIndent, int newIndent, + int tabDist, int useTabs, char nullSubsChar, int *newLength ); +static char *expandTabs( const char *text, int startIndent, int tabDist, + char nullSubsChar, int *newLen ); +static char *unexpandTabs( char *text, int startIndent, int tabDist, + char nullSubsChar, int *newLen ); +static int max( int i1, int i2 ); +static int min( int i1, int i2 ); + +static const char *ControlCodeTable[ 32 ] = { + "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", + "bs", "ht", "nl", "vt", "np", "cr", "so", "si", + "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", + "can", "em", "sub", "esc", "fs", "gs", "rs", "us"}; + +static char* undobuffer; +static int undobufferlength; +static Fl_Text_Buffer* undowidget; +static int undoat; // points after insertion +static int undocut; // number of characters deleted there +static int undoinsert; // number of characters inserted +static int undoyankcut; // length of valid contents of buffer, even if undocut=0 + +static void undobuffersize(int n) { + if (n > undobufferlength) { + if (undobuffer) { + do {undobufferlength *= 2;} while (undobufferlength < n); + undobuffer = (char*)realloc(undobuffer, undobufferlength); + } else { + undobufferlength = n+9; + undobuffer = (char*)malloc(undobufferlength); + } + } +} + +/* +** Create an empty text buffer of a pre-determined size (use this to +** avoid unnecessary re-allocation if you know exactly how much the buffer +** will need to hold +*/ +Fl_Text_Buffer::Fl_Text_Buffer( int requestedSize ) { + mLength = 0; + mBuf = (char *)malloc( requestedSize + PREFERRED_GAP_SIZE ); + mGapStart = 0; + mGapEnd = PREFERRED_GAP_SIZE; + mTabDist = 8; + mUseTabs = 1; + mPrimary.mSelected = 0; + mPrimary.mRectangular = 0; + mPrimary.mStart = mPrimary.mEnd = 0; + mSecondary.mSelected = 0; + mSecondary.mStart = mSecondary.mEnd = 0; + mSecondary.mRectangular = 0; + mHighlight.mSelected = 0; + mHighlight.mStart = mHighlight.mEnd = 0; + mHighlight.mRectangular = 0; + mNodifyProcs = NULL; + mCbArgs = NULL; + mNModifyProcs = 0; + mNPredeleteProcs = 0; + mPredeleteProcs = NULL; + mPredeleteCbArgs = NULL; + mCursorPosHint = 0; + mNullSubsChar = '\0'; + mCanUndo = 1; +#ifdef PURIFY +{ int i; for (i = mGapStart; i < mGapEnd; i++) mBuf[ i ] = '.'; } +#endif +} + +/* +** Free a text buffer +*/ +Fl_Text_Buffer::~Fl_Text_Buffer() { + free( mBuf ); + if ( mNModifyProcs != 0 ) { + delete[] mNodifyProcs; + delete[] mCbArgs; + } + if ( mNPredeleteProcs != 0 ) { + delete[] mPredeleteProcs; + delete[] mPredeleteCbArgs; + } +} + +/* +** Get the entire contents of a text buffer. Memory is allocated to contain +** the returned string, which the caller must free. +*/ +char * Fl_Text_Buffer::text() { + char *t; + + t = (char *)malloc( mLength + 1 ); + memcpy( t, mBuf, mGapStart ); + memcpy( &t[ mGapStart ], &mBuf[ mGapEnd ], + mLength - mGapStart ); + t[ mLength ] = '\0'; + return t; +} + +/* +** Replace the entire contents of the text buffer +*/ +void Fl_Text_Buffer::text( const char *t ) { + int insertedLength, deletedLength; + const char *deletedText; + + call_predelete_callbacks(0, length()); + + /* Save information for redisplay, and get rid of the old buffer */ + deletedText = text(); + deletedLength = mLength; + free( (void *)mBuf ); + + /* Start a new buffer with a gap of PREFERRED_GAP_SIZE in the center */ + insertedLength = strlen( t ); + mBuf = (char *)malloc( insertedLength + PREFERRED_GAP_SIZE ); + mLength = insertedLength; + mGapStart = insertedLength / 2; + mGapEnd = mGapStart + PREFERRED_GAP_SIZE; + memcpy( mBuf, t, mGapStart ); + memcpy( &mBuf[ mGapEnd ], &t[ mGapStart ], insertedLength - mGapStart ); +#ifdef PURIFY +{ int i; for ( i = mGapStart; i < mGapEnd; i++ ) mBuf[ i ] = '.'; } +#endif + + /* Zero all of the existing selections */ + update_selections( 0, deletedLength, 0 ); + + /* Call the saved display routine(s) to update the screen */ + call_modify_callbacks( 0, deletedLength, insertedLength, 0, deletedText ); + free( (void *)deletedText ); +} + +/* +** Return a copy of the text between "start" and "end" character positions +** from text buffer "buf". Positions start at 0, and the range does not +** include the character pointed to by "end" +*/ +char * Fl_Text_Buffer::text_range( int start, int end ) { + char * s; + int copiedLength, part1Length; + + /* Make sure start and end are ok, and allocate memory for returned string. + If start is bad, return "", if end is bad, adjust it. */ + if ( start < 0 || start > mLength ) { + s = (char *)malloc( 1 ); + s[ 0 ] = '\0'; + return s; + } + if ( end < start ) { + int temp = start; + start = end; + end = temp; + } + if ( end > mLength ) + end = mLength; + copiedLength = end - start; + s = (char *)malloc( copiedLength + 1 ); + + /* Copy the text from the buffer to the returned string */ + if ( end <= mGapStart ) { + memcpy( s, &mBuf[ start ], copiedLength ); + } else if ( start >= mGapStart ) { + memcpy( s, &mBuf[ start + ( mGapEnd - mGapStart ) ], copiedLength ); + } else { + part1Length = mGapStart - start; + memcpy( s, &mBuf[ start ], part1Length ); + memcpy( &s[ part1Length ], &mBuf[ mGapEnd ], copiedLength - part1Length ); + } + s[ copiedLength ] = '\0'; + return s; +} + +/* +** Return the character at buffer position "pos". Positions start at 0. +*/ +char Fl_Text_Buffer::character( int pos ) { + if ( pos < 0 || pos >= mLength ) + return '\0'; + if ( pos < mGapStart ) + return mBuf[ pos ]; + else + return mBuf[ pos + mGapEnd - mGapStart ]; +} + +/* +** Insert null-terminated string "text" at position "pos" in "buf" +*/ +void Fl_Text_Buffer::insert( int pos, const char *s ) { + int nInserted; + + /* if pos is not contiguous to existing text, make it */ + if ( pos > mLength ) pos = mLength; + if ( pos < 0 ) pos = 0; + + /* Even if nothing is deleted, we must call these callbacks */ + call_predelete_callbacks( pos, 0 ); + + /* insert and redisplay */ + nInserted = insert_( pos, s ); + mCursorPosHint = pos + nInserted; + call_modify_callbacks( pos, 0, nInserted, 0, NULL ); +} + +/* +** Delete the characters between "start" and "end", and insert the +** null-terminated string "text" in their place in in "buf" +*/ +void Fl_Text_Buffer::replace( int start, int end, const char *s ) { + const char * deletedText; + int nInserted; + + // Range check... + if (!s) return; + if (start < 0) start = 0; + if (end > mLength) end = mLength; + + call_predelete_callbacks( start, end-start ); + deletedText = text_range( start, end ); + remove_( start, end ); + //undoyankcut = undocut; + nInserted = insert_( start, s ); + mCursorPosHint = start + nInserted; + call_modify_callbacks( start, end - start, nInserted, 0, deletedText ); + free( (void *)deletedText ); +} + +void Fl_Text_Buffer::remove( int start, int end ) { + const char * deletedText; + + /* Make sure the arguments make sense */ + if ( start > end ) { + int temp = start; + start = end; + end = temp; + } + if ( start > mLength ) start = mLength; + if ( start < 0 ) start = 0; + if ( end > mLength ) end = mLength; + if ( end < 0 ) end = 0; + + if (start == end) return; + + call_predelete_callbacks( start, end-start ); + /* Remove and redisplay */ + deletedText = text_range( start, end ); + remove_( start, end ); + mCursorPosHint = start; + call_modify_callbacks( start, end - start, 0, 0, deletedText ); + free( (void *)deletedText ); +} + +void Fl_Text_Buffer::copy( Fl_Text_Buffer *fromBuf, int fromStart, + int fromEnd, int toPos ) { + int copiedLength = fromEnd - fromStart; + int part1Length; + + /* Prepare the buffer to receive the new text. If the new text fits in + the current buffer, just move the gap (if necessary) to where + the text should be inserted. If the new text is too large, reallocate + the buffer with a gap large enough to accomodate the new text and a + gap of PREFERRED_GAP_SIZE */ + if ( copiedLength > mGapEnd - mGapStart ) + reallocate_with_gap( toPos, copiedLength + PREFERRED_GAP_SIZE ); + else if ( toPos != mGapStart ) + move_gap( toPos ); + + /* Insert the new text (toPos now corresponds to the start of the gap) */ + if ( fromEnd <= fromBuf->mGapStart ) { + memcpy( &mBuf[ toPos ], &fromBuf->mBuf[ fromStart ], copiedLength ); + } else if ( fromStart >= fromBuf->mGapStart ) { + memcpy( &mBuf[ toPos ], + &fromBuf->mBuf[ fromStart + ( fromBuf->mGapEnd - fromBuf->mGapStart ) ], + copiedLength ); + } else { + part1Length = fromBuf->mGapStart - fromStart; + memcpy( &mBuf[ toPos ], &fromBuf->mBuf[ fromStart ], part1Length ); + memcpy( &mBuf[ toPos + part1Length ], &fromBuf->mBuf[ fromBuf->mGapEnd ], + copiedLength - part1Length ); + } + mGapStart += copiedLength; + mLength += copiedLength; + update_selections( toPos, 0, copiedLength ); +} + +/* +** remove text according to the undo variables or insert text +** from the undo buffer +*/ +int Fl_Text_Buffer::undo(int *cursorPos) { + if (undowidget != this || !undocut && !undoinsert &&!mCanUndo) return 0; + + int ilen = undocut; + int xlen = undoinsert; + int b = undoat-xlen; + + if (xlen && undoyankcut && !ilen) { + ilen = undoyankcut; + } + + if (xlen && ilen) { + undobuffersize(ilen+1); + undobuffer[ilen] = 0; + char *tmp = strdup(undobuffer); + replace(b, undoat, tmp); + if (cursorPos) *cursorPos = mCursorPosHint; + free(tmp); + } + else if (xlen) { + remove(b, undoat); + if (cursorPos) *cursorPos = mCursorPosHint; + } + else if (ilen) { + undobuffersize(ilen+1); + undobuffer[ilen] = 0; + insert(undoat, undobuffer); + if (cursorPos) *cursorPos = mCursorPosHint; + undoyankcut = 0; + } + + return 1; +} + +/* +** let the undo system know if we can undo changes +*/ +void Fl_Text_Buffer::canUndo(char flag) { + mCanUndo = flag; +} + +/* +** Insert "text" columnwise into buffer starting at displayed character +** position "column" on the line beginning at "startPos". Opens a rectangular +** space the width and height of "text", by moving all text to the right of +** "column" right. If charsInserted and charsDeleted are not NULL, the +** number of characters inserted and deleted in the operation (beginning +** at startPos) are returned in these arguments +*/ +void Fl_Text_Buffer::insert_column( int column, int startPos, const char *s, + int *charsInserted, int *charsDeleted ) { + int nLines, lineStartPos, nDeleted, insertDeleted, nInserted; + const char *deletedText; + + nLines = countLines( s ); + lineStartPos = line_start( startPos ); + nDeleted = line_end( skip_lines( startPos, nLines ) ) - + lineStartPos; + call_predelete_callbacks( lineStartPos, nDeleted ); + deletedText = text_range( lineStartPos, lineStartPos + nDeleted ); + insert_column_( column, lineStartPos, s, &insertDeleted, &nInserted, + &mCursorPosHint ); + if ( nDeleted != insertDeleted ) + Fl::error("Fl_Text_Buffer::insert_column(): internal consistency check ins1 failed"); + call_modify_callbacks( lineStartPos, nDeleted, nInserted, 0, deletedText ); + free( (void *) deletedText ); + if ( charsInserted != NULL ) + * charsInserted = nInserted; + if ( charsDeleted != NULL ) + * charsDeleted = nDeleted; +} + +/* +** Overlay "text" between displayed character positions "rectStart" and +** "rectEnd" on the line beginning at "startPos". If charsInserted and +** charsDeleted are not NULL, the number of characters inserted and deleted +** in the operation (beginning at startPos) are returned in these arguments. +*/ +void Fl_Text_Buffer::overlay_rectangular( int startPos, int rectStart, + int rectEnd, const char *s, int *charsInserted, int *charsDeleted ) { + int nLines, lineStartPos, nDeleted, insertDeleted, nInserted; + const char *deletedText; + + nLines = countLines( s ); + lineStartPos = line_start( startPos ); + nDeleted = line_end( skip_lines( startPos, nLines ) ) - + lineStartPos; + call_predelete_callbacks( lineStartPos, nDeleted ); + deletedText = text_range( lineStartPos, lineStartPos + nDeleted ); + overlay_rectangular_( lineStartPos, rectStart, rectEnd, s, &insertDeleted, + &nInserted, &mCursorPosHint ); + if ( nDeleted != insertDeleted ) + Fl::error("Fl_Text_Buffer::overlay_rectangle(): internal consistency check ovly1 failed"); + call_modify_callbacks( lineStartPos, nDeleted, nInserted, 0, deletedText ); + free( (void *) deletedText ); + if ( charsInserted != NULL ) + * charsInserted = nInserted; + if ( charsDeleted != NULL ) + * charsDeleted = nDeleted; +} + +/* +** Replace a rectangular area in buf, given by "start", "end", "rectStart", +** and "rectEnd", with "text". If "text" is vertically longer than the +** rectangle, add extra lines to make room for it. +*/ +void Fl_Text_Buffer::replace_rectangular( int start, int end, int rectStart, + int rectEnd, const char *s ) { + char *insPtr; + const char *deletedText; + char *insText = (char *)""; + int i, nInsertedLines, nDeletedLines, insLen, hint; + int insertDeleted, insertInserted, deleteInserted; + int linesPadded = 0; + + /* Make sure start and end refer to complete lines, since the + columnar delete and insert operations will replace whole lines */ + start = line_start( start ); + end = line_end( end ); + + call_predelete_callbacks( start, end-start ); + + /* If more lines will be deleted than inserted, pad the inserted text + with newlines to make it as long as the number of deleted lines. This + will indent all of the text to the right of the rectangle to the same + column. If more lines will be inserted than deleted, insert extra + lines in the buffer at the end of the rectangle to make room for the + additional lines in "text" */ + nInsertedLines = countLines( s ); + nDeletedLines = count_lines( start, end ); + if ( nInsertedLines < nDeletedLines ) { + insLen = strlen( s ); + insText = (char *)malloc( insLen + nDeletedLines - nInsertedLines + 1 ); + strcpy( insText, s ); + insPtr = insText + insLen; + for ( i = 0; i < nDeletedLines - nInsertedLines; i++ ) + *insPtr++ = '\n'; + *insPtr = '\0'; + } else if ( nDeletedLines < nInsertedLines ) { + linesPadded = nInsertedLines - nDeletedLines; + for ( i = 0; i < linesPadded; i++ ) + insert_( end, "\n" ); + } /* else nDeletedLines == nInsertedLines; */ + + /* Save a copy of the text which will be modified for the modify CBs */ + deletedText = text_range( start, end ); + + /* Delete then insert */ + remove_rectangular_( start, end, rectStart, rectEnd, &deleteInserted, &hint ); + insert_column_( rectStart, start, insText, &insertDeleted, &insertInserted, + &mCursorPosHint ); + + /* Figure out how many chars were inserted and call modify callbacks */ + if ( insertDeleted != deleteInserted + linesPadded ) + Fl::error("Fl_Text_Buffer::replace_rectangular(): internal consistency check repl1 failed"); + call_modify_callbacks( start, end - start, insertInserted, 0, deletedText ); + free( (void *) deletedText ); + if ( nInsertedLines < nDeletedLines ) + free( (void *) insText ); +} + +/* +** Remove a rectangular swath of characters between character positions start +** and end and horizontal displayed-character offsets rectStart and rectEnd. +*/ +void Fl_Text_Buffer::remove_rectangular( int start, int end, int rectStart, + int rectEnd ) { + const char * deletedText; + int nInserted; + + start = line_start( start ); + end = line_end( end ); + call_predelete_callbacks( start, end-start ); + deletedText = text_range( start, end ); + remove_rectangular_( start, end, rectStart, rectEnd, &nInserted, + &mCursorPosHint ); + call_modify_callbacks( start, end - start, nInserted, 0, deletedText ); + free( (void *) deletedText ); +} + +/* +** Clear a rectangular "hole" out of the buffer between character positions +** start and end and horizontal displayed-character offsets rectStart and +** rectEnd. +*/ +void Fl_Text_Buffer::clear_rectangular( int start, int end, int rectStart, + int rectEnd ) { + int i, nLines; + char *newlineString; + + nLines = count_lines( start, end ); + newlineString = (char *)malloc( nLines + 1 ); + for ( i = 0; i < nLines; i++ ) + newlineString[ i ] = '\n'; + newlineString[ i ] = '\0'; + overlay_rectangular( start, rectStart, rectEnd, newlineString, + NULL, NULL ); + free( (void *) newlineString ); +} + +char * Fl_Text_Buffer::text_in_rectangle( int start, int end, + int rectStart, int rectEnd ) { + int lineStart, selLeft, selRight, len; + char *textOut, *outPtr, *retabbedStr; + const char *textIn; + + start = line_start( start ); + end = line_end( end ); + textOut = (char *)malloc( ( end - start ) + 1 ); + lineStart = start; + outPtr = textOut; + while ( lineStart <= end ) { + rectangular_selection_boundaries( lineStart, rectStart, rectEnd, + &selLeft, &selRight ); + textIn = text_range( selLeft, selRight ); + len = selRight - selLeft; + memcpy( outPtr, textIn, len ); + free( (void *) textIn ); + outPtr += len; + lineStart = line_end( selRight ) + 1; + *outPtr++ = '\n'; + } + if ( outPtr != textOut ) + outPtr--; /* don't leave trailing newline */ + *outPtr = '\0'; + + /* If necessary, realign the tabs in the selection as if the text were + positioned at the left margin */ + retabbedStr = realignTabs( textOut, rectStart, 0, mTabDist, + mUseTabs, mNullSubsChar, &len ); + free( (void *) textOut ); + return retabbedStr; +} + +/* +** Set the hardware tab distance used by all displays for this buffer, +** and used in computing offsets for rectangular selection operations. +*/ +void Fl_Text_Buffer::tab_distance( int tabDist ) { + const char * deletedText; + + /* First call the pre-delete callbacks with the previous tab setting + still active. */ + call_predelete_callbacks( 0, mLength ); + + /* Change the tab setting */ + mTabDist = tabDist; + + /* Force any display routines to redisplay everything (unfortunately, + this means copying the whole buffer contents to provide "deletedText" */ + deletedText = text(); + call_modify_callbacks( 0, mLength, mLength, 0, deletedText ); + free( (void *) deletedText ); +} + +void Fl_Text_Buffer::select( int start, int end ) { + Fl_Text_Selection oldSelection = mPrimary; + + mPrimary.set( start, end ); + redisplay_selection( &oldSelection, &mPrimary ); +} + +void Fl_Text_Buffer::unselect() { + Fl_Text_Selection oldSelection = mPrimary; + + mPrimary.mSelected = 0; + redisplay_selection( &oldSelection, &mPrimary ); +} + +void Fl_Text_Buffer::select_rectangular( int start, int end, int rectStart, + int rectEnd ) { + Fl_Text_Selection oldSelection = mPrimary; + + mPrimary.set_rectangular( start, end, rectStart, rectEnd ); + redisplay_selection( &oldSelection, &mPrimary ); +} + +int Fl_Text_Buffer::selection_position( int *start, int *end + ) { + return mPrimary.position( start, end ); +} + +int Fl_Text_Buffer::selection_position( int *start, int *end, + int *isRect, int *rectStart, int *rectEnd ) { + return mPrimary.position( start, end, isRect, rectStart, + rectEnd ); +} + +char * Fl_Text_Buffer::selection_text() { + return selection_text_( &mPrimary ); +} + +void Fl_Text_Buffer::remove_selection() { + remove_selection_( &mPrimary ); +} + +void Fl_Text_Buffer::replace_selection( const char *s ) { + replace_selection_( &mPrimary, s ); +} + +void Fl_Text_Buffer::secondary_select( int start, int end ) { + Fl_Text_Selection oldSelection = mSecondary; + + mSecondary.set( start, end ); + redisplay_selection( &oldSelection, &mSecondary ); +} + +void Fl_Text_Buffer::secondary_unselect() { + Fl_Text_Selection oldSelection = mSecondary; + + mSecondary.mSelected = 0; + redisplay_selection( &oldSelection, &mSecondary ); +} + +void Fl_Text_Buffer::secondary_select_rectangular( int start, int end, + int rectStart, int rectEnd ) { + Fl_Text_Selection oldSelection = mSecondary; + + mSecondary.set_rectangular( start, end, rectStart, rectEnd ); + redisplay_selection( &oldSelection, &mSecondary ); +} + +int Fl_Text_Buffer::secondary_selection_position( int *start, int *end, + int *isRect, int *rectStart, int *rectEnd ) { + return mSecondary.position( start, end, isRect, rectStart, + rectEnd ); +} + +char * Fl_Text_Buffer::secondary_selection_text() { + return selection_text_( &mSecondary ); +} + +void Fl_Text_Buffer::remove_secondary_selection() { + remove_selection_( &mSecondary ); +} + +void Fl_Text_Buffer::replace_secondary_selection( const char *s ) { + replace_selection_( &mSecondary, s ); +} + +void Fl_Text_Buffer::highlight( int start, int end ) { + Fl_Text_Selection oldSelection = mHighlight; + + mHighlight.set( start, end ); + redisplay_selection( &oldSelection, &mHighlight ); +} + +void Fl_Text_Buffer::unhighlight() { + Fl_Text_Selection oldSelection = mHighlight; + + mHighlight.mSelected = 0; + redisplay_selection( &oldSelection, &mHighlight ); +} + +void Fl_Text_Buffer::highlight_rectangular( int start, int end, + int rectStart, int rectEnd ) { + Fl_Text_Selection oldSelection = mHighlight; + + mHighlight.set_rectangular( start, end, rectStart, rectEnd ); + redisplay_selection( &oldSelection, &mHighlight ); +} + +int Fl_Text_Buffer::highlight_position( int *start, int *end, + int *isRect, int *rectStart, int *rectEnd ) { + return mHighlight.position( start, end, isRect, rectStart, + rectEnd ); +} + +char * Fl_Text_Buffer::highlight_text() { + return selection_text_( &mHighlight ); +} + +/* +** Add a callback routine to be called when the buffer is modified +*/ +void Fl_Text_Buffer::add_modify_callback( Fl_Text_Modify_Cb bufModifiedCB, + void *cbArg ) { + Fl_Text_Modify_Cb * newModifyProcs; + void **newCBArgs; + int i; + + newModifyProcs = new Fl_Text_Modify_Cb [ mNModifyProcs + 1 ]; + newCBArgs = new void * [ mNModifyProcs + 1 ]; + for ( i = 0; i < mNModifyProcs; i++ ) { + newModifyProcs[ i + 1 ] = mNodifyProcs[ i ]; + newCBArgs[ i + 1 ] = mCbArgs[ i ]; + } + if ( mNModifyProcs != 0 ) { + delete [] mNodifyProcs; + delete [] mCbArgs; + } + newModifyProcs[ 0 ] = bufModifiedCB; + newCBArgs[ 0 ] = cbArg; + mNModifyProcs++; + mNodifyProcs = newModifyProcs; + mCbArgs = newCBArgs; +} + +void Fl_Text_Buffer::remove_modify_callback( Fl_Text_Modify_Cb bufModifiedCB, + void *cbArg ) { + int i, toRemove = -1; + Fl_Text_Modify_Cb *newModifyProcs; + void **newCBArgs; + + /* find the matching callback to remove */ + for ( i = 0; i < mNModifyProcs; i++ ) { + if ( mNodifyProcs[ i ] == bufModifiedCB && mCbArgs[ i ] == cbArg ) { + toRemove = i; + break; + } + } + if ( toRemove == -1 ) { + Fl::error("Fl_Text_Buffer::remove_modify_callback(): Can't find modify CB to remove"); + return; + } + + /* Allocate new lists for remaining callback procs and args (if + any are left) */ + mNModifyProcs--; + if ( mNModifyProcs == 0 ) { + mNModifyProcs = 0; + delete[] mNodifyProcs; + mNodifyProcs = NULL; + delete[] mCbArgs; + mCbArgs = NULL; + return; + } + newModifyProcs = new Fl_Text_Modify_Cb [ mNModifyProcs ]; + newCBArgs = new void * [ mNModifyProcs ]; + + /* copy out the remaining members and free the old lists */ + for ( i = 0; i < toRemove; i++ ) { + newModifyProcs[ i ] = mNodifyProcs[ i ]; + newCBArgs[ i ] = mCbArgs[ i ]; + } + for ( ; i < mNModifyProcs; i++ ) { + newModifyProcs[ i ] = mNodifyProcs[ i + 1 ]; + newCBArgs[ i ] = mCbArgs[ i + 1 ]; + } + delete[] mNodifyProcs; + delete[] mCbArgs; + mNodifyProcs = newModifyProcs; + mCbArgs = newCBArgs; +} + +/* +** Add a callback routine to be called before text is deleted from the buffer. +*/ +void Fl_Text_Buffer::add_predelete_callback(Fl_Text_Predelete_Cb bufPreDeleteCB, + void *cbArg) { + Fl_Text_Predelete_Cb *newPreDeleteProcs; + void **newCBArgs; + int i; + + newPreDeleteProcs = new Fl_Text_Predelete_Cb[ mNPredeleteProcs + 1 ]; + newCBArgs = new void * [ mNPredeleteProcs + 1 ]; + for ( i = 0; i < mNPredeleteProcs; i++ ) { + newPreDeleteProcs[i + 1] = mPredeleteProcs[i]; + newCBArgs[i + 1] = mPredeleteCbArgs[i]; + } + if (! mNPredeleteProcs != 0) { + delete [] mPredeleteProcs; + delete [] mPredeleteCbArgs; + } + newPreDeleteProcs[0] = bufPreDeleteCB; + newCBArgs[0] = cbArg; + mNPredeleteProcs++; + mPredeleteProcs = newPreDeleteProcs; + mPredeleteCbArgs = newCBArgs; +} + +void Fl_Text_Buffer::remove_predelete_callback( + Fl_Text_Predelete_Cb bufPreDeleteCB, void *cbArg) { + int i, toRemove = -1; + Fl_Text_Predelete_Cb *newPreDeleteProcs; + void **newCBArgs; + + /* find the matching callback to remove */ + for ( i = 0; i < mNPredeleteProcs; i++) { + if (mPredeleteProcs[i] == bufPreDeleteCB && + mPredeleteCbArgs[i] == cbArg) { + toRemove = i; + break; + } + } + if (toRemove == -1) { + Fl::error("Fl_Text_Buffer::remove_predelete_callback(): Can't find pre-delete CB to remove"); + return; + } + + /* Allocate new lists for remaining callback procs and args (if + any are left) */ + mNPredeleteProcs--; + if (mNPredeleteProcs == 0) { + mNPredeleteProcs = 0; + delete[] mPredeleteProcs; + mPredeleteProcs = NULL; + delete[] mPredeleteCbArgs; + mPredeleteCbArgs = NULL; + return; + } + newPreDeleteProcs = new Fl_Text_Predelete_Cb [ mNPredeleteProcs ]; + newCBArgs = new void * [ mNPredeleteProcs ]; + + /* copy out the remaining members and free the old lists */ + for ( i = 0; i < toRemove; i++) { + newPreDeleteProcs[i] = mPredeleteProcs[i]; + newCBArgs[i] = mPredeleteCbArgs[i]; + } + for ( ; i < mNPredeleteProcs; i++) { + newPreDeleteProcs[i] = mPredeleteProcs[i+1]; + newCBArgs[i] = mPredeleteCbArgs[i+1]; + } + delete[] mPredeleteProcs; + delete[] mPredeleteCbArgs; + mPredeleteProcs = newPreDeleteProcs; + mPredeleteCbArgs = newCBArgs; +} + +/* +** Return the text from the entire line containing position "pos" +*/ +char * Fl_Text_Buffer::line_text( int pos ) { + return text_range( line_start( pos ), line_end( pos ) ); +} + +/* +** Find the position of the start of the line containing position "pos" +*/ +int Fl_Text_Buffer::line_start( int pos ) { + if ( !findchar_backward( pos, '\n', &pos ) ) + return 0; + return pos + 1; +} + +/* +** Find the position of the end of the line containing position "pos" +** (which is either a pointer to the newline character ending the line, +** or a pointer to one character beyond the end of the buffer) +*/ +int Fl_Text_Buffer::line_end( int pos ) { + if ( !findchar_forward( pos, '\n', &pos ) ) + pos = mLength; + return pos; +} + +int Fl_Text_Buffer::word_start( int pos ) { + while ( pos && ( isalnum( character( pos ) ) || character( pos ) == '_' ) ) { + pos--; + } + if ( !( isalnum( character( pos ) ) || character( pos ) == '_' ) ) pos++; + return pos; +} + +int Fl_Text_Buffer::word_end( int pos ) { + while (pos < length() && (isalnum(character(pos)) || character(pos) == '_' )) { + pos++; + } + return pos; +} + +/* +** Get a character from the text buffer expanded into it's screen +** representation (which may be several characters for a tab or a +** control code). Returns the number of characters written to "outStr". +** "indent" is the number of characters from the start of the line +** for figuring tabs. Output string is guranteed to be shorter or +** equal in length to FL_TEXT_MAX_EXP_CHAR_LEN +*/ +int Fl_Text_Buffer::expand_character( int pos, int indent, char *outStr ) { + return expand_character( character( pos ), indent, outStr, + mTabDist, mNullSubsChar ); +} + +/* +** Expand a single character from the text buffer into it's screen +** representation (which may be several characters for a tab or a +** control code). Returns the number of characters added to "outStr". +** "indent" is the number of characters from the start of the line +** for figuring tabs. Output string is guranteed to be shorter or +** equal in length to FL_TEXT_MAX_EXP_CHAR_LEN +*/ +int Fl_Text_Buffer::expand_character( char c, int indent, char *outStr, int tabDist, + char nullSubsChar ) { + int i, nSpaces; + + /* Convert tabs to spaces */ + if ( c == '\t' ) { + nSpaces = tabDist - ( indent % tabDist ); + for ( i = 0; i < nSpaces; i++ ) + outStr[ i ] = ' '; + return nSpaces; + } + + /* Convert control codes to readable character sequences */ + /*... is this safe with international character sets? */ + if ( ( ( unsigned char ) c ) <= 31 ) { + sprintf( outStr, "<%s>", ControlCodeTable[ ( unsigned char ) c ] ); + return strlen( outStr ); + } else if ( c == 127 ) { + sprintf( outStr, "<del>" ); + return 5; + } else if ( c == nullSubsChar ) { + sprintf( outStr, "<nul>" ); + return 5; + } + + /* Otherwise, just return the character */ + *outStr = c; + return 1; +} + +/* +** Return the length in displayed characters of character "c" expanded +** for display (as discussed above in BufGetExpandedChar). If the +** buffer for which the character width is being measured is doing null +** substitution, nullSubsChar should be passed as that character (or nul +** to ignore). +*/ +int Fl_Text_Buffer::character_width( char c, int indent, int tabDist, char nullSubsChar ) { + /* Note, this code must parallel that in Fl_Text_Buffer::ExpandCharacter */ + if ( c == '\t' ) + return tabDist - ( indent % tabDist ); + else if ( ( ( unsigned char ) c ) <= 31 ) + return strlen( ControlCodeTable[ ( unsigned char ) c ] ) + 2; + else if ( c == 127 ) + return 5; + else if ( c == nullSubsChar ) + return 5; + return 1; +} + +/* +** Count the number of displayed characters between buffer position +** "lineStartPos" and "targetPos". (displayed characters are the characters +** shown on the screen to represent characters in the buffer, where tabs and +** control characters are expanded) +*/ +int Fl_Text_Buffer::count_displayed_characters( int lineStartPos, int targetPos ) { + int pos, charCount = 0; + char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ]; + + pos = lineStartPos; + while ( pos < targetPos ) + charCount += expand_character( pos++, charCount, expandedChar ); + return charCount; +} + +/* +** Count forward from buffer position "startPos" in displayed characters +** (displayed characters are the characters shown on the screen to represent +** characters in the buffer, where tabs and control characters are expanded) +*/ +int Fl_Text_Buffer::skip_displayed_characters( int lineStartPos, int nChars ) { + int pos, charCount = 0; + char c; + + pos = lineStartPos; + while ( charCount < nChars && pos < mLength ) { + c = character( pos ); + if ( c == '\n' ) + return pos; + charCount += character_width( c, charCount, mTabDist, mNullSubsChar ); + pos++; + } + return pos; +} + +/* +** Count the number of newlines between startPos and endPos in buffer "buf". +** The character at position "endPos" is not counted. +*/ +int Fl_Text_Buffer::count_lines( int startPos, int endPos ) { + int pos, gapLen = mGapEnd - mGapStart; + int lineCount = 0; + + pos = startPos; + while ( pos < mGapStart ) { + if ( pos == endPos ) + return lineCount; + if ( mBuf[ pos++ ] == '\n' ) + lineCount++; + } + while ( pos < mLength ) { + if ( pos == endPos ) + return lineCount; + if ( mBuf[ pos++ + gapLen ] == '\n' ) + lineCount++; + } + return lineCount; +} + +/* +** Find the first character of the line "nLines" forward from "startPos" +** in "buf" and return its position +*/ +int Fl_Text_Buffer::skip_lines( int startPos, int nLines ) { + int pos, gapLen = mGapEnd - mGapStart; + int lineCount = 0; + + if ( nLines == 0 ) + return startPos; + + pos = startPos; + while ( pos < mGapStart ) { + if ( mBuf[ pos++ ] == '\n' ) { + lineCount++; + if ( lineCount == nLines ) + return pos; + } + } + while ( pos < mLength ) { + if ( mBuf[ pos++ + gapLen ] == '\n' ) { + lineCount++; + if ( lineCount >= nLines ) + return pos; + } + } + return pos; +} + +/* +** Find the position of the first character of the line "nLines" backwards +** from "startPos" (not counting the character pointed to by "startpos" if +** that is a newline) in "buf". nLines == 0 means find the beginning of +** the line +*/ +int Fl_Text_Buffer::rewind_lines( int startPos, int nLines ) { + int pos, gapLen = mGapEnd - mGapStart; + int lineCount = -1; + + pos = startPos - 1; + if ( pos <= 0 ) + return 0; + + while ( pos >= mGapStart ) { + if ( mBuf[ pos + gapLen ] == '\n' ) { + if ( ++lineCount >= nLines ) + return pos + 1; + } + pos--; + } + while ( pos >= 0 ) { + if ( mBuf[ pos ] == '\n' ) { + if ( ++lineCount >= nLines ) + return pos + 1; + } + pos--; + } + return 0; +} + +/* +** Search forwards in buffer for string "searchString", starting with the +** character "startPos", and returning the result in "foundPos" +** returns 1 if found, 0 if not. +*/ +int Fl_Text_Buffer::search_forward( int startPos, const char *searchString, + int *foundPos, int matchCase ) +{ + if (!searchString) return 0; + int bp; + const char* sp; + while (startPos < length()) { + bp = startPos; + sp = searchString; + do { + if (!*sp) { *foundPos = startPos; return 1; } + } while ((matchCase ? character(bp++) == *sp++ : + toupper(character(bp++)) == toupper(*sp++)) + && bp < length()); + startPos++; + } + return 0; +} + +/* +** Search backwards in buffer for string "searchString", starting with the +** character BEFORE "startPos", returning the result in "foundPos" +** returns 1 if found, 0 if not. +*/ +int Fl_Text_Buffer::search_backward( int startPos, const char *searchString, + int *foundPos, int matchCase ) +{ + if (!searchString) return 0; + int bp; + const char* sp; + while (startPos > 0) { + bp = startPos-1; + sp = searchString+strlen(searchString)-1; + do { + if (sp < searchString) { *foundPos = bp+1; return 1; } + } while ((matchCase ? character(bp--) == *sp-- : + toupper(character(bp--)) == toupper(*sp--)) + && bp >= 0); + startPos--; + } + return 0; +} + +/* +** Search forwards in buffer for characters in "searchChars", starting +** with the character "startPos", and returning the result in "foundPos" +** returns 1 if found, 0 if not. +*/ +int Fl_Text_Buffer::findchars_forward( int startPos, const char *searchChars, + int *foundPos ) { + int pos, gapLen = mGapEnd - mGapStart; + const char *c; + + pos = startPos; + while ( pos < mGapStart ) { + for ( c = searchChars; *c != '\0'; c++ ) { + if ( mBuf[ pos ] == *c ) { + *foundPos = pos; + return 1; + } + } + pos++; + } + while ( pos < mLength ) { + for ( c = searchChars; *c != '\0'; c++ ) { + if ( mBuf[ pos + gapLen ] == *c ) { + *foundPos = pos; + return 1; + } + } + pos++; + } + *foundPos = mLength; + return 0; +} + +/* +** Search backwards in buffer for characters in "searchChars", starting +** with the character BEFORE "startPos", returning the result in "foundPos" +** returns 1 if found, 0 if not. +*/ +int Fl_Text_Buffer::findchars_backward( int startPos, const char *searchChars, + int *foundPos ) { + int pos, gapLen = mGapEnd - mGapStart; + const char *c; + + if ( startPos == 0 ) { + *foundPos = 0; + return 0; + } + pos = startPos == 0 ? 0 : startPos - 1; + while ( pos >= mGapStart ) { + for ( c = searchChars; *c != '\0'; c++ ) { + if ( mBuf[ pos + gapLen ] == *c ) { + *foundPos = pos; + return 1; + } + } + pos--; + } + while ( pos >= 0 ) { + for ( c = searchChars; *c != '\0'; c++ ) { + if ( mBuf[ pos ] == *c ) { + *foundPos = pos; + return 1; + } + } + pos--; + } + *foundPos = 0; + return 0; +} + +/* +** A horrible design flaw in NEdit (from the very start, before we knew that +** NEdit would become so popular), is that it uses C NULL terminated strings +** to hold text. This means editing text containing NUL characters is not +** possible without special consideration. Here is the special consideration. +** The routines below maintain a special substitution-character which stands +** in for a null, and translates strings an buffers back and forth from/to +** the substituted form, figure out what to substitute, and figure out +** when we're in over our heads and no translation is possible. +*/ + +/* +** The primary routine for integrating new text into a text buffer with +** substitution of another character for ascii nuls. This substitutes null +** characters in the string in preparation for being copied or replaced +** into the buffer, and if neccessary, adjusts the buffer as well, in the +** event that the string contains the character it is currently using for +** substitution. Returns 0, if substitution is no longer possible +** because all non-printable characters are already in use. +*/ +int Fl_Text_Buffer::substitute_null_characters( char *string, int len ) { + char histogram[ 256 ]; + + /* Find out what characters the string contains */ + histogramCharacters( string, len, histogram, 1 ); + + /* Does the string contain the null-substitute character? If so, re- + histogram the buffer text to find a character which is ok in both the + string and the buffer, and change the buffer's null-substitution + character. If none can be found, give up and return 0 */ + if ( histogram[ ( unsigned char ) mNullSubsChar ] != 0 ) { + char * bufString; + char newSubsChar; + bufString = (char*)text(); + histogramCharacters( bufString, mLength, histogram, 0 ); + newSubsChar = chooseNullSubsChar( histogram ); + if ( newSubsChar == '\0' ) + return 0; + subsChars( bufString, mLength, mNullSubsChar, newSubsChar ); + remove_( 0, mLength ); + insert_( 0, bufString ); + free( (void *) bufString ); + mNullSubsChar = newSubsChar; + } + + /* If the string contains null characters, substitute them with the + buffer's null substitution character */ + if ( histogram[ 0 ] != 0 ) + subsChars( string, len, '\0', mNullSubsChar ); + return 1; +} + +/* +** Convert strings obtained from buffers which contain null characters, which +** have been substituted for by a special substitution character, back to +** a null-containing string. There is no time penalty for calling this +** routine if no substitution has been done. +*/ +void Fl_Text_Buffer::unsubstitute_null_characters( char *string ) { + register char * c, subsChar = mNullSubsChar; + + if ( subsChar == '\0' ) + return; + for ( c = string; *c != '\0'; c++ ) + if ( *c == subsChar ) + * c = '\0'; +} + +/* +** Create a pseudo-histogram of the characters in a string (don't actually +** count, because we don't want overflow, just mark the character's presence +** with a 1). If init is true, initialize the histogram before acumulating. +** if not, add the new data to an existing histogram. +*/ +static void histogramCharacters( const char *string, int length, char hist[ 256 ], + int init ) { + int i; + const char *c; + + if ( init ) + for ( i = 0; i < 256; i++ ) + hist[ i ] = 0; + for ( c = string; c < &string[ length ]; c++ ) + hist[ *( ( unsigned char * ) c ) ] |= 1; +} + +/* +** Substitute fromChar with toChar in string. +*/ +static void subsChars( char *string, int length, char fromChar, char toChar ) { + char * c; + + for ( c = string; c < &string[ length ]; c++ ) + if ( *c == fromChar ) * c = toChar; +} + +/* +** Search through ascii control characters in histogram in order of least +** likelihood of use, find an unused character to use as a stand-in for a +** null. If the character set is full (no available characters outside of +** the printable set, return the null character. +*/ +static char chooseNullSubsChar( char hist[ 256 ] ) { +#define N_REPLACEMENTS 25 + static char replacements[ N_REPLACEMENTS ] = {1, 2, 3, 4, 5, 6, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 28, 29, 30, 31, 11, 7}; + int i; + for ( i = 0; i < N_REPLACEMENTS; i++ ) + if ( hist[ replacements[ i ] ] == 0 ) + return replacements[ i ]; + return '\0'; +} + +/* +** Internal (non-redisplaying) version of BufInsert. Returns the length of +** text inserted (this is just strlen(text), however this calculation can be +** expensive and the length will be required by any caller who will continue +** on to call redisplay). pos must be contiguous with the existing text in +** the buffer (i.e. not past the end). +*/ +int Fl_Text_Buffer::insert_( int pos, const char *s ) { + int insertedLength = strlen( s ); + + /* Prepare the buffer to receive the new text. If the new text fits in + the current buffer, just move the gap (if necessary) to where + the text should be inserted. If the new text is too large, reallocate + the buffer with a gap large enough to accomodate the new text and a + gap of PREFERRED_GAP_SIZE */ + if ( insertedLength > mGapEnd - mGapStart ) + reallocate_with_gap( pos, insertedLength + PREFERRED_GAP_SIZE ); + else if ( pos != mGapStart ) + move_gap( pos ); + + /* Insert the new text (pos now corresponds to the start of the gap) */ + memcpy( &mBuf[ pos ], s, insertedLength ); + mGapStart += insertedLength; + mLength += insertedLength; + update_selections( pos, 0, insertedLength ); + + if (mCanUndo) { + if ( undowidget==this && undoat==pos && undoinsert ) { + undoinsert += insertedLength; + } + else { + undoinsert = insertedLength; + undoyankcut = (undoat==pos) ? undocut : 0 ; + } + undoat = pos+insertedLength; + undocut = 0; + undowidget = this; + } + + return insertedLength; +} + +/* +** Internal (non-redisplaying) version of BufRemove. Removes the contents +** of the buffer between start and end (and moves the gap to the site of +** the delete). +*/ +void Fl_Text_Buffer::remove_( int start, int end ) { + /* if the gap is not contiguous to the area to remove, move it there */ + + if (mCanUndo) { + if ( undowidget==this && undoat==end && undocut ) { + undobuffersize( undocut+end-start+1 ); + memmove( undobuffer+end-start, undobuffer, undocut ); + undocut += end-start; + } + else { + undocut = end-start; + undobuffersize(undocut); + } + undoat = start; + undoinsert = 0; + undoyankcut = 0; + undowidget = this; + } + + if ( start > mGapStart ) { + if (mCanUndo) + memcpy( undobuffer, mBuf+(mGapEnd-mGapStart)+start, end-start ); + move_gap( start ); + } + else if ( end < mGapStart ) { + if (mCanUndo) + memcpy( undobuffer, mBuf+start, end-start ); + move_gap( end ); + } + else { + int prelen = mGapStart - start; + if (mCanUndo) { + memcpy( undobuffer, mBuf+start, prelen ); + memcpy( undobuffer+prelen, mBuf+mGapEnd, end-start-prelen); + } + } + + /* expand the gap to encompass the deleted characters */ + mGapEnd += end - mGapStart; + mGapStart -= mGapStart - start; + + /* update the length */ + mLength -= end - start; + + /* fix up any selections which might be affected by the change */ + update_selections( start, end - start, 0 ); +} + +/* +** Insert a column of text without calling the modify callbacks. Note that +** in some pathological cases, inserting can actually decrease the size of +** the buffer because of spaces being coalesced into tabs. "nDeleted" and +** "nInserted" return the number of characters deleted and inserted beginning +** at the start of the line containing "startPos". "endPos" returns buffer +** position of the lower left edge of the inserted column (as a hint for +** routines which need to set a cursor position). +*/ +void Fl_Text_Buffer::insert_column_( int column, int startPos, const char *insText, + int *nDeleted, int *nInserted, int *endPos ) { + int nLines, start, end, insWidth, lineStart, lineEnd; + int expReplLen, expInsLen, len, endOffset; + char *c, *outStr, *outPtr, *expText, *insLine; + const char *line; + const char *replText; + const char *insPtr; + + if ( column < 0 ) + column = 0; + + /* Allocate a buffer for the replacement string large enough to hold + possibly expanded tabs in both the inserted text and the replaced + area, as well as per line: 1) an additional 2*FL_TEXT_MAX_EXP_CHAR_LEN + characters for padding where tabs and control characters cross the + column of the selection, 2) up to "column" additional spaces per + line for padding out to the position of "column", 3) padding up + to the width of the inserted text if that must be padded to align + the text beyond the inserted column. (Space for additional + newlines if the inserted text extends beyond the end of the buffer + is counted with the length of insText) */ + start = line_start( startPos ); + nLines = countLines( insText ) + 1; + insWidth = textWidth( insText, mTabDist, mNullSubsChar ); + end = line_end( skip_lines( start, nLines - 1 ) ); + replText = text_range( start, end ); + expText = expandTabs( replText, 0, mTabDist, mNullSubsChar, + &expReplLen ); + free( (void *) replText ); + free( (void *) expText ); + expText = expandTabs( insText, 0, mTabDist, mNullSubsChar, + &expInsLen ); + free( (void *) expText ); + outStr = (char *)malloc( expReplLen + expInsLen + + nLines * ( column + insWidth + FL_TEXT_MAX_EXP_CHAR_LEN ) + 1 ); + + /* Loop over all lines in the buffer between start and end removing the + text between rectStart and rectEnd and padding appropriately. Trim + trailing space from line (whitespace at the ends of lines otherwise + tends to multiply, since additional padding is added to maintain it */ + outPtr = outStr; + lineStart = start; + insPtr = insText; + for (;;) { + lineEnd = line_end( lineStart ); + line = text_range( lineStart, lineEnd ); + insLine = copyLine( insPtr, &len ); + insPtr += len; + insertColInLine( line, insLine, column, insWidth, mTabDist, + mUseTabs, mNullSubsChar, outPtr, &len, &endOffset ); + free( (void *) line ); + free( (void *) insLine ); + for ( c = outPtr + len - 1; c > outPtr && isspace( *c ); c-- ) + len--; + outPtr += len; + *outPtr++ = '\n'; + lineStart = lineEnd < mLength ? lineEnd + 1 : mLength; + if ( *insPtr == '\0' ) + break; + insPtr++; + } + if ( outPtr != outStr ) + outPtr--; /* trim back off extra newline */ + *outPtr = '\0'; + + /* replace the text between start and end with the new stuff */ + remove_( start, end ); + insert_( start, outStr ); + *nInserted = outPtr - outStr; + *nDeleted = end - start; + *endPos = start + ( outPtr - outStr ) - len + endOffset; + free( (void *) outStr ); +} + +/* +** Delete a rectangle of text without calling the modify callbacks. Returns +** the number of characters replacing those between start and end. Note that +** in some pathological cases, deleting can actually increase the size of +** the buffer because of tab expansions. "endPos" returns the buffer position +** of the point in the last line where the text was removed (as a hint for +** routines which need to position the cursor after a delete operation) +*/ +void Fl_Text_Buffer::remove_rectangular_( int start, int end, int rectStart, + int rectEnd, int *replaceLen, int *endPos ) { + int nLines, lineStart, lineEnd, len, endOffset; + char *outStr, *outPtr, *expText; + const char *s, *line; + + /* allocate a buffer for the replacement string large enough to hold + possibly expanded tabs as well as an additional FL_TEXT_MAX_EXP_CHAR_LEN * 2 + characters per line for padding where tabs and control characters cross + the edges of the selection */ + start = line_start( start ); + end = line_end( end ); + nLines = count_lines( start, end ) + 1; + s = text_range( start, end ); + expText = expandTabs( s, 0, mTabDist, mNullSubsChar, &len ); + free( (void *) s ); + free( (void *) expText ); + outStr = (char *)malloc( len + nLines * FL_TEXT_MAX_EXP_CHAR_LEN * 2 + 1 ); + + /* loop over all lines in the buffer between start and end removing + the text between rectStart and rectEnd and padding appropriately */ + lineStart = start; + outPtr = outStr; + endOffset = 0; + while ( lineStart <= mLength && lineStart <= end ) { + lineEnd = line_end( lineStart ); + line = text_range( lineStart, lineEnd ); + deleteRectFromLine( line, rectStart, rectEnd, mTabDist, + mUseTabs, mNullSubsChar, outPtr, &len, &endOffset ); + free( (void *) line ); + outPtr += len; + *outPtr++ = '\n'; + lineStart = lineEnd + 1; + } + if ( outPtr != outStr ) + outPtr--; /* trim back off extra newline */ + *outPtr = '\0'; + + /* replace the text between start and end with the newly created string */ + remove_( start, end ); + insert_( start, outStr ); + *replaceLen = outPtr - outStr; + *endPos = start + ( outPtr - outStr ) - len + endOffset; + free( (void *) outStr ); +} + +/* +** Overlay a rectangular area of text without calling the modify callbacks. +** "nDeleted" and "nInserted" return the number of characters deleted and +** inserted beginning at the start of the line containing "startPos". +** "endPos" returns buffer position of the lower left edge of the inserted +** column (as a hint for routines which need to set a cursor position). +*/ +void Fl_Text_Buffer::overlay_rectangular_(int startPos, int rectStart, + int rectEnd, const char *insText, + int *nDeleted, int *nInserted, + int *endPos ) { + int nLines, start, end, lineStart, lineEnd; + int expInsLen, len, endOffset; + char *c, *outStr, *outPtr, *expText, *insLine; + const char *line; + const char *insPtr; + + /* Allocate a buffer for the replacement string large enough to hold + possibly expanded tabs in the inserted text, as well as per line: 1) + an additional 2*FL_TEXT_MAX_EXP_CHAR_LEN characters for padding where tabs + and control characters cross the column of the selection, 2) up to + "column" additional spaces per line for padding out to the position + of "column", 3) padding up to the width of the inserted text if that + must be padded to align the text beyond the inserted column. (Space + for additional newlines if the inserted text extends beyond the end + of the buffer is counted with the length of insText) */ + start = line_start( startPos ); + nLines = countLines( insText ) + 1; + end = line_end( skip_lines( start, nLines - 1 ) ); + expText = expandTabs( insText, 0, mTabDist, mNullSubsChar, + &expInsLen ); + free( (void *) expText ); + outStr = (char *)malloc( end - start + expInsLen + + nLines * ( rectEnd + FL_TEXT_MAX_EXP_CHAR_LEN ) + 1 ); + + /* Loop over all lines in the buffer between start and end overlaying the + text between rectStart and rectEnd and padding appropriately. Trim + trailing space from line (whitespace at the ends of lines otherwise + tends to multiply, since additional padding is added to maintain it */ + outPtr = outStr; + lineStart = start; + insPtr = insText; + for (;;) { + lineEnd = line_end( lineStart ); + line = text_range( lineStart, lineEnd ); + insLine = copyLine( insPtr, &len ); + insPtr += len; + overlayRectInLine( line, insLine, rectStart, rectEnd, mTabDist, + mUseTabs, mNullSubsChar, outPtr, &len, &endOffset ); + free( (void *) line ); + free( (void *) insLine ); + for ( c = outPtr + len - 1; c > outPtr && isspace( *c ); c-- ) + len--; + outPtr += len; + *outPtr++ = '\n'; + lineStart = lineEnd < mLength ? lineEnd + 1 : mLength; + if ( *insPtr == '\0' ) + break; + insPtr++; + } + if ( outPtr != outStr ) + outPtr--; /* trim back off extra newline */ + *outPtr = '\0'; + + /* replace the text between start and end with the new stuff */ + remove_( start, end ); + insert_( start, outStr ); + *nInserted = outPtr - outStr; + *nDeleted = end - start; + *endPos = start + ( outPtr - outStr ) - len + endOffset; + free( (void *) outStr ); +} + +/* +** Insert characters from single-line string "insLine" in single-line string +** "line" at "column", leaving "insWidth" space before continuing line. +** "outLen" returns the number of characters written to "outStr", "endOffset" +** returns the number of characters from the beginning of the string to +** the right edge of the inserted text (as a hint for routines which need +** to position the cursor). +*/ +static void insertColInLine( const char *line, char *insLine, int column, int insWidth, + int tabDist, int useTabs, char nullSubsChar, char *outStr, int *outLen, + int *endOffset ) { + char * c, *outPtr, *retabbedStr; + const char *linePtr; + int indent, toIndent, len, postColIndent; + + /* copy the line up to "column" */ + outPtr = outStr; + indent = 0; + for ( linePtr = line; *linePtr != '\0'; linePtr++ ) { + len = Fl_Text_Buffer::character_width( *linePtr, indent, tabDist, nullSubsChar ); + if ( indent + len > column ) + break; + indent += len; + *outPtr++ = *linePtr; + } + + /* If "column" falls in the middle of a character, and the character is a + tab, leave it off and leave the indent short and it will get padded + later. If it's a control character, insert it and adjust indent + accordingly. */ + if ( indent < column && *linePtr != '\0' ) { + postColIndent = indent + len; + if ( *linePtr == '\t' ) + linePtr++; + else { + *outPtr++ = *linePtr++; + indent += len; + } + } else + postColIndent = indent; + + /* If there's no text after the column and no text to insert, that's all */ + if ( *insLine == '\0' && *linePtr == '\0' ) { + *outLen = *endOffset = outPtr - outStr; + return; + } + + /* pad out to column if text is too short */ + if ( indent < column ) { + addPadding( outPtr, indent, column, tabDist, useTabs, nullSubsChar, &len ); + outPtr += len; + indent = column; + } + + /* Copy the text from "insLine" (if any), recalculating the tabs as if + the inserted string began at column 0 to its new column destination */ + if ( *insLine != '\0' ) { + retabbedStr = realignTabs( insLine, 0, indent, tabDist, useTabs, + nullSubsChar, &len ); + for ( c = retabbedStr; *c != '\0'; c++ ) { + *outPtr++ = *c; + len = Fl_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar ); + indent += len; + } + free( (void *) retabbedStr ); + } + + /* If the original line did not extend past "column", that's all */ + if ( *linePtr == '\0' ) { + *outLen = *endOffset = outPtr - outStr; + return; + } + + /* Pad out to column + width of inserted text + (additional original + offset due to non-breaking character at column) */ + toIndent = column + insWidth + postColIndent - column; + addPadding( outPtr, indent, toIndent, tabDist, useTabs, nullSubsChar, &len ); + outPtr += len; + indent = toIndent; + + /* realign tabs for text beyond "column" and write it out */ + retabbedStr = realignTabs( linePtr, postColIndent, indent, tabDist, + useTabs, nullSubsChar, &len ); + strcpy( outPtr, retabbedStr ); + free( (void *) retabbedStr ); + *endOffset = outPtr - outStr; + *outLen = ( outPtr - outStr ) + len; +} + +/* +** Remove characters in single-line string "line" between displayed positions +** "rectStart" and "rectEnd", and write the result to "outStr", which is +** assumed to be large enough to hold the returned string. Note that in +** certain cases, it is possible for the string to get longer due to +** expansion of tabs. "endOffset" returns the number of characters from +** the beginning of the string to the point where the characters were +** deleted (as a hint for routines which need to position the cursor). +*/ +static void deleteRectFromLine( const char *line, int rectStart, int rectEnd, + int tabDist, int useTabs, char nullSubsChar, char *outStr, int *outLen, + int *endOffset ) { + int indent, preRectIndent, postRectIndent, len; + const char *c; + char *retabbedStr, *outPtr; + + /* copy the line up to rectStart */ + outPtr = outStr; + indent = 0; + for ( c = line; *c != '\0'; c++ ) { + if ( indent > rectStart ) + break; + len = Fl_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar ); + if ( indent + len > rectStart && ( indent == rectStart || *c == '\t' ) ) + break; + indent += len; + *outPtr++ = *c; + } + preRectIndent = indent; + + /* skip the characters between rectStart and rectEnd */ + for ( ; *c != '\0' && indent < rectEnd; c++ ) + indent += Fl_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar ); + postRectIndent = indent; + + /* If the line ended before rectEnd, there's nothing more to do */ + if ( *c == '\0' ) { + *outPtr = '\0'; + *outLen = *endOffset = outPtr - outStr; + return; + } + + /* fill in any space left by removed tabs or control characters + which straddled the boundaries */ + indent = max( rectStart + postRectIndent - rectEnd, preRectIndent ); + addPadding( outPtr, preRectIndent, indent, tabDist, useTabs, nullSubsChar, + &len ); + outPtr += len; + + /* Copy the rest of the line. If the indentation has changed, preserve + the position of non-whitespace characters by converting tabs to + spaces, then back to tabs with the correct offset */ + retabbedStr = realignTabs( c, postRectIndent, indent, tabDist, useTabs, + nullSubsChar, &len ); + strcpy( outPtr, retabbedStr ); + free( (void *) retabbedStr ); + *endOffset = outPtr - outStr; + *outLen = ( outPtr - outStr ) + len; +} + +/* +** Overlay characters from single-line string "insLine" on single-line string +** "line" between displayed character offsets "rectStart" and "rectEnd". +** "outLen" returns the number of characters written to "outStr", "endOffset" +** returns the number of characters from the beginning of the string to +** the right edge of the inserted text (as a hint for routines which need +** to position the cursor). +*/ +static void overlayRectInLine( const char *line, char *insLine, int rectStart, + int rectEnd, int tabDist, int useTabs, char nullSubsChar, char *outStr, + int *outLen, int *endOffset ) { + char * c, *outPtr, *retabbedStr; + int inIndent, outIndent, len, postRectIndent; + const char *linePtr; + + /* copy the line up to "rectStart" */ + outPtr = outStr; + inIndent = outIndent = 0; + for ( linePtr = line; *linePtr != '\0'; linePtr++ ) { + len = Fl_Text_Buffer::character_width( *linePtr, inIndent, tabDist, nullSubsChar ); + if ( inIndent + len > rectStart ) + break; + inIndent += len; + outIndent += len; + *outPtr++ = *linePtr; + } + + /* If "rectStart" falls in the middle of a character, and the character + is a tab, leave it off and leave the outIndent short and it will get + padded later. If it's a control character, insert it and adjust + outIndent accordingly. */ + if ( inIndent < rectStart && *linePtr != '\0' ) { + if ( *linePtr == '\t' ) { + linePtr++; + inIndent += len; + } else { + *outPtr++ = *linePtr++; + outIndent += len; + inIndent += len; + } + } + + /* skip the characters between rectStart and rectEnd */ + postRectIndent = rectEnd; + for ( ; *linePtr != '\0'; linePtr++ ) { + inIndent += Fl_Text_Buffer::character_width( *linePtr, inIndent, tabDist, nullSubsChar ); + if ( inIndent >= rectEnd ) { + linePtr++; + postRectIndent = inIndent; + break; + } + } + + /* If there's no text after rectStart and no text to insert, that's all */ + if ( *insLine == '\0' && *linePtr == '\0' ) { + *outLen = *endOffset = outPtr - outStr; + return; + } + + /* pad out to rectStart if text is too short */ + if ( outIndent < rectStart ) { + addPadding( outPtr, outIndent, rectStart, tabDist, useTabs, nullSubsChar, + &len ); + outPtr += len; + } + outIndent = rectStart; + + /* Copy the text from "insLine" (if any), recalculating the tabs as if + the inserted string began at column 0 to its new column destination */ + if ( *insLine != '\0' ) { + retabbedStr = realignTabs( insLine, 0, rectStart, tabDist, useTabs, + nullSubsChar, &len ); + for ( c = retabbedStr; *c != '\0'; c++ ) { + *outPtr++ = *c; + len = Fl_Text_Buffer::character_width( *c, outIndent, tabDist, nullSubsChar ); + outIndent += len; + } + free( (void *) retabbedStr ); + } + + /* If the original line did not extend past "rectStart", that's all */ + if ( *linePtr == '\0' ) { + *outLen = *endOffset = outPtr - outStr; + return; + } + + /* Pad out to rectEnd + (additional original offset + due to non-breaking character at right boundary) */ + addPadding( outPtr, outIndent, postRectIndent, tabDist, useTabs, + nullSubsChar, &len ); + outPtr += len; + outIndent = postRectIndent; + + /* copy the text beyond "rectEnd" */ + strcpy( outPtr, linePtr ); + *endOffset = outPtr - outStr; + *outLen = ( outPtr - outStr ) + strlen( linePtr ); +} + +void Fl_Text_Selection::set( int startpos, int endpos ) { + mSelected = startpos != endpos; + mRectangular = 0; + mStart = min( startpos, endpos ); + mEnd = max( startpos, endpos ); +} + +void Fl_Text_Selection::set_rectangular( int startpos, int endpos, + int rectStart, int rectEnd ) { + mSelected = rectStart < rectEnd; + mRectangular = 1; + mStart = startpos; + mEnd = endpos; + mRectStart = rectStart; + mRectEnd = rectEnd; +} + +int Fl_Text_Selection::position( int *startpos, int *endpos ) { + if ( !mSelected ) + return 0; + *startpos = mStart; + *endpos = mEnd; + + return 1; +} + +int Fl_Text_Selection::position( int *startpos, int *endpos, + int *isRect, int *rectStart, int *rectEnd ) { + if ( !mSelected ) + return 0; + *isRect = mRectangular; + *startpos = mStart; + *endpos = mEnd; + if ( mRectangular ) { + *rectStart = mRectStart; + *rectEnd = mRectEnd; + } + return 1; +} + +/* +** Return true if position "pos" with indentation "dispIndex" is in +** the Fl_Text_Selection. +*/ +int Fl_Text_Selection::includes(int pos, int lineStartPos, int dispIndex) { + return selected() && + ( (!rectangular() && pos >= start() && pos < end()) || + (rectangular() && pos >= start() && lineStartPos <= end() && + dispIndex >= rect_start() && dispIndex < rect_end()) + ); +} + + + +char * Fl_Text_Buffer::selection_text_( Fl_Text_Selection *sel ) { + int start, end, isRect, rectStart, rectEnd; + char *s; + + /* If there's no selection, return an allocated empty string */ + if ( !sel->position( &start, &end, &isRect, &rectStart, &rectEnd ) ) { + s = (char *)malloc( 1 ); + *s = '\0'; + return s; + } + + /* If the selection is not rectangular, return the selected range */ + if ( isRect ) + return text_in_rectangle( start, end, rectStart, rectEnd ); + else + return text_range( start, end ); +} + +void Fl_Text_Buffer::remove_selection_( Fl_Text_Selection *sel ) { + int start, end; + int isRect, rectStart, rectEnd; + + if ( !sel->position( &start, &end, &isRect, &rectStart, &rectEnd ) ) + return; + if ( isRect ) + remove_rectangular( start, end, rectStart, rectEnd ); + else { + remove( start, end ); + //undoyankcut = undocut; + } +} + +void Fl_Text_Buffer::replace_selection_( Fl_Text_Selection *sel, const char *s ) { + int start, end, isRect, rectStart, rectEnd; + Fl_Text_Selection oldSelection = *sel; + + /* If there's no selection, return */ + if ( !sel->position( &start, &end, &isRect, &rectStart, &rectEnd ) ) + return; + + /* Do the appropriate type of replace */ + if ( isRect ) + replace_rectangular( start, end, rectStart, rectEnd, s ); + else + replace( start, end, s ); + + /* Unselect (happens automatically in BufReplace, but BufReplaceRect + can't detect when the contents of a selection goes away) */ + sel->mSelected = 0; + redisplay_selection( &oldSelection, sel ); +} + +static void addPadding( char *string, int startIndent, int toIndent, + int tabDist, int useTabs, char nullSubsChar, int *charsAdded ) { + char * outPtr; + int len, indent; + + indent = startIndent; + outPtr = string; + if ( useTabs ) { + while ( indent < toIndent ) { + len = Fl_Text_Buffer::character_width( '\t', indent, tabDist, nullSubsChar ); + if ( len > 1 && indent + len <= toIndent ) { + *outPtr++ = '\t'; + indent += len; + } else { + *outPtr++ = ' '; + indent++; + } + } + } else { + while ( indent < toIndent ) { + *outPtr++ = ' '; + indent++; + } + } + *charsAdded = outPtr - string; +} + +/* +** Call the stored modify callback procedure(s) for this buffer to update the +** changed area(s) on the screen and any other listeners. +*/ +void Fl_Text_Buffer::call_modify_callbacks( int pos, int nDeleted, + int nInserted, int nRestyled, const char *deletedText ) { + int i; + + for ( i = 0; i < mNModifyProcs; i++ ) + ( *mNodifyProcs[ i ] ) ( pos, nInserted, nDeleted, nRestyled, + deletedText, mCbArgs[ i ] ); +} + +/* +** Call the stored pre-delete callback procedure(s) for this buffer to update +** the changed area(s) on the screen and any other listeners. +*/ +void Fl_Text_Buffer::call_predelete_callbacks(int pos, int nDeleted) { + int i; + + for (i=0; i<mNPredeleteProcs; i++) + (*mPredeleteProcs[i])(pos, nDeleted, mPredeleteCbArgs[i]); +} + +/* +** Call the stored redisplay procedure(s) for this buffer to update the +** screen for a change in a selection. +*/ +void Fl_Text_Buffer::redisplay_selection( Fl_Text_Selection *oldSelection, + Fl_Text_Selection *newSelection ) { + int oldStart, oldEnd, newStart, newEnd, ch1Start, ch1End, ch2Start, ch2End; + + /* If either selection is rectangular, add an additional character to + the end of the selection to request the redraw routines to wipe out + the parts of the selection beyond the end of the line */ + oldStart = oldSelection->mStart; + newStart = newSelection->mStart; + oldEnd = oldSelection->mEnd; + newEnd = newSelection->mEnd; + if ( oldSelection->mRectangular ) + oldEnd++; + if ( newSelection->mRectangular ) + newEnd++; + + /* If the old or new selection is unselected, just redisplay the + single area that is (was) selected and return */ + if ( !oldSelection->mSelected && !newSelection->mSelected ) + return; + if ( !oldSelection->mSelected ) { + call_modify_callbacks( newStart, 0, 0, newEnd - newStart, NULL ); + return; + } + if ( !newSelection->mSelected ) { + call_modify_callbacks( oldStart, 0, 0, oldEnd - oldStart, NULL ); + return; + } + + /* If the selection changed from normal to rectangular or visa versa, or + if a rectangular selection changed boundaries, redisplay everything */ + if ( ( oldSelection->mRectangular && !newSelection->mRectangular ) || + ( !oldSelection->mRectangular && newSelection->mRectangular ) || + ( oldSelection->mRectangular && ( + ( oldSelection->mRectStart != newSelection->mRectStart ) || + ( oldSelection->mRectEnd != newSelection->mRectEnd ) ) ) ) { + call_modify_callbacks( min( oldStart, newStart ), 0, 0, + max( oldEnd, newEnd ) - min( oldStart, newStart ), NULL ); + return; + } + + /* If the selections are non-contiguous, do two separate updates + and return */ + if ( oldEnd < newStart || newEnd < oldStart ) { + call_modify_callbacks( oldStart, 0, 0, oldEnd - oldStart, NULL ); + call_modify_callbacks( newStart, 0, 0, newEnd - newStart, NULL ); + return; + } + + /* Otherwise, separate into 3 separate regions: ch1, and ch2 (the two + changed areas), and the unchanged area of their intersection, + and update only the changed area(s) */ + ch1Start = min( oldStart, newStart ); + ch2End = max( oldEnd, newEnd ); + ch1End = max( oldStart, newStart ); + ch2Start = min( oldEnd, newEnd ); + if ( ch1Start != ch1End ) + call_modify_callbacks( ch1Start, 0, 0, ch1End - ch1Start, NULL ); + if ( ch2Start != ch2End ) + call_modify_callbacks( ch2Start, 0, 0, ch2End - ch2Start, NULL ); +} + +void Fl_Text_Buffer::move_gap( int pos ) { + int gapLen = mGapEnd - mGapStart; + + if ( pos > mGapStart ) + memmove( &mBuf[ mGapStart ], &mBuf[ mGapEnd ], + pos - mGapStart ); + else + memmove( &mBuf[ pos + gapLen ], &mBuf[ pos ], mGapStart - pos ); + mGapEnd += pos - mGapStart; + mGapStart += pos - mGapStart; +} + +/* +** reallocate the text storage in "buf" to have a gap starting at "newGapStart" +** and a gap size of "newGapLen", preserving the buffer's current contents. +*/ +void Fl_Text_Buffer::reallocate_with_gap( int newGapStart, int newGapLen ) { + char * newBuf; + int newGapEnd; + + newBuf = (char *)malloc( mLength + newGapLen ); + newGapEnd = newGapStart + newGapLen; + if ( newGapStart <= mGapStart ) { + memcpy( newBuf, mBuf, newGapStart ); + memcpy( &newBuf[ newGapEnd ], &mBuf[ newGapStart ], + mGapStart - newGapStart ); + memcpy( &newBuf[ newGapEnd + mGapStart - newGapStart ], + &mBuf[ mGapEnd ], mLength - mGapStart ); + } else { /* newGapStart > mGapStart */ + memcpy( newBuf, mBuf, mGapStart ); + memcpy( &newBuf[ mGapStart ], &mBuf[ mGapEnd ], + newGapStart - mGapStart ); + memcpy( &newBuf[ newGapEnd ], + &mBuf[ mGapEnd + newGapStart - mGapStart ], + mLength - newGapStart ); + } + free( (void *) mBuf ); + mBuf = newBuf; + mGapStart = newGapStart; + mGapEnd = newGapEnd; +#ifdef PURIFY +{int i; for ( i = mGapStart; i < mGapEnd; i++ ) mBuf[ i ] = '.'; } +#endif +} + +/* +** Update all of the selections in "buf" for changes in the buffer's text +*/ +void Fl_Text_Buffer::update_selections( int pos, int nDeleted, + int nInserted ) { + mPrimary.update( pos, nDeleted, nInserted ); + mSecondary.update( pos, nDeleted, nInserted ); + mHighlight.update( pos, nDeleted, nInserted ); +} + +/* +** Update an individual selection for changes in the corresponding text +*/ +void Fl_Text_Selection::update( int pos, int nDeleted, + int nInserted ) { + if ( !mSelected || pos > mEnd ) + return; + if ( pos + nDeleted <= mStart ) { + mStart += nInserted - nDeleted; + mEnd += nInserted - nDeleted; + } else if ( pos <= mStart && pos + nDeleted >= mEnd ) { + mStart = pos; + mEnd = pos; + mSelected = 0; + } else if ( pos <= mStart && pos + nDeleted < mEnd ) { + mStart = pos; + mEnd = nInserted + mEnd - nDeleted; + } else if ( pos < mEnd ) { + mEnd += nInserted - nDeleted; + if ( mEnd <= mStart ) + mSelected = 0; + } +} + +/* +** Search forwards in buffer "buf" for character "searchChar", starting +** with the character "startPos", and returning the result in "foundPos" +** returns 1 if found, 0 if not. (The difference between this and +** BufSearchForward is that it's optimized for single characters. The +** overall performance of the text widget is dependent on its ability to +** count lines quickly, hence searching for a single character: newline) +*/ +int Fl_Text_Buffer::findchar_forward( int startPos, char searchChar, + int *foundPos ) { + int pos, gapLen = mGapEnd - mGapStart; + + if (startPos < 0 || startPos >= mLength) { + *foundPos = mLength; + return 0; + } + + pos = startPos; + while ( pos < mGapStart ) { + if ( mBuf[ pos ] == searchChar ) { + *foundPos = pos; + return 1; + } + pos++; + } + while ( pos < mLength ) { + if ( mBuf[ pos + gapLen ] == searchChar ) { + *foundPos = pos; + return 1; + } + pos++; + } + *foundPos = mLength; + return 0; +} + +/* +** Search backwards in buffer "buf" for character "searchChar", starting +** with the character BEFORE "startPos", returning the result in "foundPos" +** returns 1 if found, 0 if not. (The difference between this and +** BufSearchBackward is that it's optimized for single characters. The +** overall performance of the text widget is dependent on its ability to +** count lines quickly, hence searching for a single character: newline) +*/ +int Fl_Text_Buffer::findchar_backward( int startPos, char searchChar, + int *foundPos ) { + int pos, gapLen = mGapEnd - mGapStart; + + if ( startPos <= 0 || startPos > mLength ) { + *foundPos = 0; + return 0; + } + pos = startPos - 1; + while ( pos >= mGapStart ) { + if ( mBuf[ pos + gapLen ] == searchChar ) { + *foundPos = pos; + return 1; + } + pos--; + } + while ( pos >= 0 ) { + if ( mBuf[ pos ] == searchChar ) { + *foundPos = pos; + return 1; + } + pos--; + } + *foundPos = 0; + return 0; +} + +/* +** Copy from "text" to end up to but not including newline (or end of "text") +** and return the copy as the function value, and the length of the line in +** "lineLen" +*/ +static char *copyLine( const char *text, int *lineLen ) { + int len = 0; + const char *c; + char *outStr; + + for ( c = text; *c != '\0' && *c != '\n'; c++ ) + len++; + outStr = (char *)malloc( len + 1 ); + strlcpy( outStr, text, len + 1); + *lineLen = len; + return outStr; +} + +/* +** Count the number of newlines in a null-terminated text string; +*/ +static int countLines( const char *string ) { + const char * c; + int lineCount = 0; + + for ( c = string; *c != '\0'; c++ ) + if ( *c == '\n' ) lineCount++; + return lineCount; +} + +/* +** Measure the width in displayed characters of string "text" +*/ +static int textWidth( const char *text, int tabDist, char nullSubsChar ) { + int width = 0, maxWidth = 0; + const char *c; + + for ( c = text; *c != '\0'; c++ ) { + if ( *c == '\n' ) { + if ( width > maxWidth ) + maxWidth = width; + width = 0; + } else + width += Fl_Text_Buffer::character_width( *c, width, tabDist, nullSubsChar ); + } + if ( width > maxWidth ) + return width; + return maxWidth; +} + +/* +** Find the first and last character position in a line within a rectangular +** selection (for copying). Includes tabs which cross rectStart, but not +** control characters which do so. Leaves off tabs which cross rectEnd. +** +** Technically, the calling routine should convert tab characters which +** cross the right boundary of the selection to spaces which line up with +** the edge of the selection. Unfortunately, the additional memory +** management required in the parent routine to allow for the changes +** in string size is not worth all the extra work just for a couple of +** shifted characters, so if a tab protrudes, just lop it off and hope +** that there are other characters in the selection to establish the right +** margin for subsequent columnar pastes of this data. +*/ +void Fl_Text_Buffer::rectangular_selection_boundaries( int lineStartPos, + int rectStart, int rectEnd, int *selStart, int *selEnd ) { + int pos, width, indent = 0; + char c; + + /* find the start of the selection */ + for ( pos = lineStartPos; pos < mLength; pos++ ) { + c = character( pos ); + if ( c == '\n' ) + break; + width = Fl_Text_Buffer::character_width( c, indent, mTabDist, mNullSubsChar ); + if ( indent + width > rectStart ) { + if ( indent != rectStart && c != '\t' ) { + pos++; + indent += width; + } + break; + } + indent += width; + } + *selStart = pos; + + /* find the end */ + for ( ; pos < mLength; pos++ ) { + c = character( pos ); + if ( c == '\n' ) + break; + width = Fl_Text_Buffer::character_width( c, indent, mTabDist, mNullSubsChar ); + indent += width; + if ( indent > rectEnd ) { + if ( indent - width != rectEnd && c != '\t' ) + pos++; + break; + } + } + *selEnd = pos; +} + +/* +** Adjust the space and tab characters from string "text" so that non-white +** characters remain stationary when the text is shifted from starting at +** "origIndent" to starting at "newIndent". Returns an allocated string +** which must be freed by the caller with XtFree. +*/ +static char *realignTabs( const char *text, int origIndent, int newIndent, + int tabDist, int useTabs, char nullSubsChar, int *newLength ) { + char * expStr, *outStr; + int len; + + /* If the tabs settings are the same, retain original tabs */ + if ( origIndent % tabDist == newIndent % tabDist ) { + len = strlen( text ); + outStr = (char *)malloc( len + 1 ); + strcpy( outStr, text ); + *newLength = len; + return outStr; + } + + /* If the tab settings are not the same, brutally convert tabs to + spaces, then back to tabs in the new position */ + expStr = expandTabs( text, origIndent, tabDist, nullSubsChar, &len ); + if ( !useTabs ) { + *newLength = len; + return expStr; + } + outStr = unexpandTabs( expStr, newIndent, tabDist, nullSubsChar, newLength ); + free( (void *) expStr ); + return outStr; +} + +/* +** Expand tabs to spaces for a block of text. The additional parameter +** "startIndent" if nonzero, indicates that the text is a rectangular selection +** beginning at column "startIndent" +*/ +static char *expandTabs( const char *text, int startIndent, int tabDist, + char nullSubsChar, int *newLen ) { + char * outStr, *outPtr; + const char *c; + int indent, len, outLen = 0; + + /* rehearse the expansion to figure out length for output string */ + indent = startIndent; + for ( c = text; *c != '\0'; c++ ) { + if ( *c == '\t' ) { + len = Fl_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar ); + outLen += len; + indent += len; + } else if ( *c == '\n' ) { + indent = startIndent; + outLen++; + } else { + indent += Fl_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar ); + outLen++; + } + } + + /* do the expansion */ + outStr = (char *)malloc( outLen + 1 ); + outPtr = outStr; + indent = startIndent; + for ( c = text; *c != '\0'; c++ ) { + if ( *c == '\t' ) { + len = Fl_Text_Buffer::expand_character( *c, indent, outPtr, tabDist, nullSubsChar ); + outPtr += len; + indent += len; + } else if ( *c == '\n' ) { + indent = startIndent; + *outPtr++ = *c; + } else { + indent += Fl_Text_Buffer::character_width( *c, indent, tabDist, nullSubsChar ); + *outPtr++ = *c; + } + } + outStr[ outLen ] = '\0'; + *newLen = outLen; + return outStr; +} + +/* +** Convert sequences of spaces into tabs. The threshold for conversion is +** when 3 or more spaces can be converted into a single tab, this avoids +** converting double spaces after a period withing a block of text. +*/ +static char *unexpandTabs( char *text, int startIndent, int tabDist, + char nullSubsChar, int *newLen ) { + char * outStr, *outPtr, *c, expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ]; + int indent, len; + + outStr = (char *)malloc( strlen( text ) + 1 ); + outPtr = outStr; + indent = startIndent; + for ( c = text; *c != '\0'; ) { + if ( *c == ' ' ) { + len = Fl_Text_Buffer::expand_character( '\t', indent, expandedChar, tabDist, + nullSubsChar ); + if ( len >= 3 && !strncmp( c, expandedChar, len ) ) { + c += len; + *outPtr++ = '\t'; + indent += len; + } else { + *outPtr++ = *c++; + indent++; + } + } else if ( *c == '\n' ) { + indent = startIndent; + *outPtr++ = *c++; + } else { + *outPtr++ = *c++; + indent++; + } + } + *outPtr = '\0'; + *newLen = outPtr - outStr; + return outStr; +} + +static int max( int i1, int i2 ) { + return i1 >= i2 ? i1 : i2; +} + +static int min( int i1, int i2 ) { + return i1 <= i2 ? i1 : i2; +} + +int +Fl_Text_Buffer::insertfile(const char *file, int pos, int buflen) { + FILE *fp; int r; + if (!(fp = fopen(file, "r"))) return 1; + char *buffer = new char[buflen]; + for (; (r = fread(buffer, 1, buflen - 1, fp)) > 0; pos += r) { + buffer[r] = (char)0; + insert(pos, buffer); + } + + int e = ferror(fp) ? 2 : 0; + fclose(fp); + delete[] buffer; + return e; +} + +int +Fl_Text_Buffer::outputfile(const char *file, int start, int end, int buflen) { + FILE *fp; + if (!(fp = fopen(file, "w"))) return 1; + for (int n; (n = min(end - start, buflen)); start += n) { + const char *p = text_range(start, start + n); + int r = fwrite(p, 1, n, fp); + free((void *)p); + if (r != n) break; + } + + int e = ferror(fp) ? 2 : 0; + fclose(fp); + return e; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Text_Display.cxx b/Utilities/FLTK/src/Fl_Text_Display.cxx new file mode 100644 index 0000000000..74e7aebc46 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Text_Display.cxx @@ -0,0 +1,3239 @@ +// +// "$Id$" +// +// Copyright 2001-2005 by Bill Spitzak and others. +// Original code Copyright Mark Edel. Permission to distribute under +// the LGPL for the FLTK library granted by Mark Edel. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <stdio.h> +#include <stdlib.h> +#include "flstring.h" +#include <limits.h> +#include <ctype.h> +#include <FL/Fl.H> +#include <FL/Fl_Text_Buffer.H> +#include <FL/Fl_Text_Display.H> +#include <FL/Fl_Window.H> + +#undef min +#undef max + +// Text area margins. Left & right margins should be at least 3 so that +// there is some room for the overhanging parts of the cursor! +#define TOP_MARGIN 1 +#define BOTTOM_MARGIN 1 +#define LEFT_MARGIN 3 +#define RIGHT_MARGIN 3 + +#define NO_HINT -1 + +/* Masks for text drawing methods. These are or'd together to form an + integer which describes what drawing calls to use to draw a string */ +#define FILL_MASK 0x0100 +#define SECONDARY_MASK 0x0200 +#define PRIMARY_MASK 0x0400 +#define HIGHLIGHT_MASK 0x0800 +#define BG_ONLY_MASK 0x1000 +#define TEXT_ONLY_MASK 0x2000 +#define STYLE_LOOKUP_MASK 0xff + +/* Maximum displayable line length (how many characters will fit across the + widest window). This amount of memory is temporarily allocated from the + stack in the draw_vline() method for drawing strings */ +#define MAX_DISP_LINE_LEN 1000 + +static int max( int i1, int i2 ); +static int min( int i1, int i2 ); +static int countlines( const char *string ); + +/* The variables below are used in a timer event to allow smooth + scrolling of the text area when the pointer has left the area. */ +static int scroll_direction = 0; +static int scroll_amount = 0; +static int scroll_y = 0; +static int scroll_x = 0; + +// CET - FIXME +#define TMPFONTWIDTH 6 + +Fl_Text_Display::Fl_Text_Display(int X, int Y, int W, int H, const char* l) + : Fl_Group(X, Y, W, H, l) { + int i; + + mMaxsize = 0; + damage_range1_start = damage_range1_end = -1; + damage_range2_start = damage_range2_end = -1; + dragPos = dragType = dragging = 0; + display_insert_position_hint = 0; + + color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR); + box(FL_DOWN_FRAME); + textsize((uchar)FL_NORMAL_SIZE); + textcolor(FL_FOREGROUND_COLOR); + textfont(FL_HELVETICA); + + text_area.x = 0; + text_area.y = 0; + text_area.w = 0; + text_area.h = 0; + + mVScrollBar = new Fl_Scrollbar(0,0,1,1); + mVScrollBar->callback((Fl_Callback*)v_scrollbar_cb, this); + mHScrollBar = new Fl_Scrollbar(0,0,1,1); + mHScrollBar->callback((Fl_Callback*)h_scrollbar_cb, this); + mHScrollBar->type(FL_HORIZONTAL); + + end(); + + scrollbar_width(16); + scrollbar_align(FL_ALIGN_BOTTOM_RIGHT); + + mCursorOn = 0; + mCursorPos = 0; + mCursorOldY = -100; + mCursorToHint = NO_HINT; + mCursorStyle = NORMAL_CURSOR; + mCursorPreferredCol = -1; + mBuffer = 0; + mFirstChar = 0; + mLastChar = 0; + mNBufferLines = 0; + mTopLineNum = mTopLineNumHint = 1; + mAbsTopLineNum = 1; + mNeedAbsTopLineNum = 0; + mHorizOffset = mHorizOffsetHint = 0; + + mCursor_color = FL_FOREGROUND_COLOR; + + mFixedFontWidth = -1; + mStyleBuffer = 0; + mStyleTable = 0; + mNStyles = 0; + mNVisibleLines = 1; + mLineStarts = new int[mNVisibleLines]; + mLineStarts[0] = 0; + for (i=1; i<mNVisibleLines; i++) + mLineStarts[i] = -1; + mSuppressResync = 0; + mNLinesDeleted = 0; + mModifyingTabDistance = 0; + + mUnfinishedStyle = 0; + mUnfinishedHighlightCB = 0; + mHighlightCBArg = 0; + + mLineNumLeft = mLineNumWidth = 0; + mContinuousWrap = 0; + mWrapMargin = 0; + mSuppressResync = mNLinesDeleted = mModifyingTabDistance = 0; +} + +/* +** Free a text display and release its associated memory. Note, the text +** BUFFER that the text display displays is a separate entity and is not +** freed, nor are the style buffer or style table. +*/ +Fl_Text_Display::~Fl_Text_Display() { + if (scroll_direction) { + Fl::remove_timeout(scroll_timer_cb, this); + scroll_direction = 0; + } + if (mBuffer) { + mBuffer->remove_modify_callback(buffer_modified_cb, this); + mBuffer->remove_predelete_callback(buffer_predelete_cb, this); + } + if (mLineStarts) delete[] mLineStarts; +} + +/* +** Attach a text buffer to display, replacing the current buffer (if any) +*/ +void Fl_Text_Display::buffer( Fl_Text_Buffer *buf ) { + /* If the text display is already displaying a buffer, clear it off + of the display and remove our callback from it */ + if ( buf == mBuffer) return; + if ( mBuffer != 0 ) { + buffer_modified_cb( 0, 0, mBuffer->length(), 0, 0, this ); + mBuffer->remove_modify_callback( buffer_modified_cb, this ); + mBuffer->remove_predelete_callback( buffer_predelete_cb, this ); + } + + /* Add the buffer to the display, and attach a callback to the buffer for + receiving modification information when the buffer contents change */ + mBuffer = buf; + if (mBuffer) { + mBuffer->add_modify_callback( buffer_modified_cb, this ); + mBuffer->add_predelete_callback( buffer_predelete_cb, this ); + + /* Update the display */ + buffer_modified_cb( 0, buf->length(), 0, 0, 0, this ); + } + + /* Resize the widget to update the screen... */ + resize(x(), y(), w(), h()); +} + +/* +** Attach (or remove) highlight information in text display and redisplay. +** Highlighting information consists of a style buffer which parallels the +** normal text buffer, but codes font and color information for the display; +** a style table which translates style buffer codes (indexed by buffer +** character - 'A') into fonts and colors; and a callback mechanism for +** as-needed highlighting, triggered by a style buffer entry of +** "unfinishedStyle". Style buffer can trigger additional redisplay during +** a normal buffer modification if the buffer contains a primary Fl_Text_Selection +** (see extendRangeForStyleMods for more information on this protocol). +** +** Style buffers, tables and their associated memory are managed by the caller. +*/ +void +Fl_Text_Display::highlight_data(Fl_Text_Buffer *styleBuffer, + const Style_Table_Entry *styleTable, + int nStyles, char unfinishedStyle, + Unfinished_Style_Cb unfinishedHighlightCB, + void *cbArg ) { + mStyleBuffer = styleBuffer; + mStyleTable = styleTable; + mNStyles = nStyles; + mUnfinishedStyle = unfinishedStyle; + mUnfinishedHighlightCB = unfinishedHighlightCB; + mHighlightCBArg = cbArg; + + mStyleBuffer->canUndo(0); +#if 0 + // FIXME: this is in nedit code -- is it needed? + /* Call TextDSetFont to combine font information from style table and + primary font, adjust font-related parameters, and then redisplay */ + TextDSetFont(textD, textD->fontStruct); +#endif + damage(FL_DAMAGE_EXPOSE); +} + +#if 0 + // FIXME: this is in nedit code -- is it needed? +/* +** Change the (non highlight) font +*/ +void TextDSetFont(textDisp *textD, XFontStruct *fontStruct) { + Display *display = XtDisplay(textD->w); + int i, maxAscent = fontStruct->ascent, maxDescent = fontStruct->descent; + int width, height, fontWidth; + Pixel bgPixel, fgPixel, selectFGPixel, selectBGPixel; + Pixel highlightFGPixel, highlightBGPixel; + XGCValues values; + XFontStruct *styleFont; + + /* If font size changes, cursor will be redrawn in a new position */ + blankCursorProtrusions(textD); + + /* If there is a (syntax highlighting) style table in use, find the new + maximum font height for this text display */ + for (i=0; i<textD->nStyles; i++) { + styleFont = textD->styleTable[i].font; + if (styleFont != NULL && styleFont->ascent > maxAscent) + maxAscent = styleFont->ascent; + if (styleFont != NULL && styleFont->descent > maxDescent) + maxDescent = styleFont->descent; + } + textD->ascent = maxAscent; + textD->descent = maxDescent; + + /* If all of the current fonts are fixed and match in width, compute */ + fontWidth = fontStruct->max_bounds.width; + if (fontWidth != fontStruct->min_bounds.width) + fontWidth = -1; + else { + for (i=0; i<textD->nStyles; i++) { + styleFont = textD->styleTable[i].font; + if (styleFont != NULL && (styleFont->max_bounds.width != fontWidth || + styleFont->max_bounds.width != styleFont->min_bounds.width)) + fontWidth = -1; + } + } + textD->fixedFontWidth = fontWidth; + + /* Don't let the height dip below one line, or bad things can happen */ + if (textD->height < maxAscent + maxDescent) + textD->height = maxAscent + maxDescent; + + /* Change the font. In most cases, this means re-allocating the + affected GCs (they are shared with other widgets, and if the primary + font changes, must be re-allocated to change it). Unfortunately, + this requres recovering all of the colors from the existing GCs */ + textD->fontStruct = fontStruct; + XGetGCValues(display, textD->gc, GCForeground|GCBackground, &values); + fgPixel = values.foreground; + bgPixel = values.background; + XGetGCValues(display, textD->selectGC, GCForeground|GCBackground, &values); + selectFGPixel = values.foreground; + selectBGPixel = values.background; + XGetGCValues(display, textD->highlightGC,GCForeground|GCBackground,&values); + highlightFGPixel = values.foreground; + highlightBGPixel = values.background; + releaseGC(textD->w, textD->gc); + releaseGC(textD->w, textD->selectGC); + releaseGC(textD->w, textD->highlightGC); + releaseGC(textD->w, textD->selectBGGC); + releaseGC(textD->w, textD->highlightBGGC); + if (textD->lineNumGC != NULL) + releaseGC(textD->w, textD->lineNumGC); + textD->lineNumGC = NULL; + allocateFixedFontGCs(textD, fontStruct, bgPixel, fgPixel, selectFGPixel, + selectBGPixel, highlightFGPixel, highlightBGPixel); + XSetFont(display, textD->styleGC, fontStruct->fid); + + /* Do a full resize to force recalculation of font related parameters */ + width = textD->width; + height = textD->height; + textD->width = textD->height = 0; + TextDResize(textD, width, height); + + /* Redisplay */ + TextDRedisplayRect(textD, textD->left, textD->top, textD->width, + textD->height); + + /* Clean up line number area in case spacing has changed */ + draw_line_numbers(textD, True); +} + +int TextDMinFontWidth(textDisp *textD, Boolean considerStyles) { + int fontWidth = textD->fontStruct->max_bounds.width; + int i; + + if (considerStyles) { + for (i = 0; i < textD->nStyles; ++i) { + int thisWidth = (textD->styleTable[i].font)->min_bounds.width; + if (thisWidth < fontWidth) { + fontWidth = thisWidth; + } + } + } + return(fontWidth); +} + +int TextDMaxFontWidth(textDisp *textD, Boolean considerStyles) { + int fontWidth = textD->fontStruct->max_bounds.width; + int i; + + if (considerStyles) { + for (i = 0; i < textD->nStyles; ++i) { + int thisWidth = (textD->styleTable[i].font)->max_bounds.width; + if (thisWidth > fontWidth) { + fontWidth = thisWidth; + } + } + } + return(fontWidth); +} +#endif + +int Fl_Text_Display::longest_vline() { + int longest = 0; + for (int i = 0; i < mNVisibleLines; i++) + longest = max(longest, measure_vline(i)); + return longest; +} + +/* +** Change the size of the displayed text area +*/ +void Fl_Text_Display::resize(int X, int Y, int W, int H) { +#ifdef DEBUG + printf("Fl_Text_Display::resize(X=%d, Y=%d, W=%d, H=%d)\n", X, Y, W, H); +#endif // DEBUG + const int oldWidth = w(); +#ifdef DEBUG + printf(" oldWidth=%d, mContinuousWrap=%d, mWrapMargin=%d\n", oldWidth, + mContinuousWrap, mWrapMargin); +#endif // DEBUG + Fl_Widget::resize(X,Y,W,H); + if (!buffer()) return; + X += Fl::box_dx(box()); + Y += Fl::box_dy(box()); + W -= Fl::box_dw(box()); + H -= Fl::box_dh(box()); + + text_area.x = X+LEFT_MARGIN; + text_area.y = Y+BOTTOM_MARGIN; + text_area.w = W-LEFT_MARGIN-RIGHT_MARGIN; + text_area.h = H-TOP_MARGIN-BOTTOM_MARGIN; + int i; + + /* Find the new maximum font height for this text display */ + for (i = 0, mMaxsize = fl_height(textfont(), textsize()); i < mNStyles; i++) + mMaxsize = max(mMaxsize, fl_height(mStyleTable[i].font, mStyleTable[i].size)); + + // did we have scrollbars initially? + int hscrollbarvisible = mHScrollBar->visible(); + int vscrollbarvisible = mVScrollBar->visible(); + + // try without scrollbars first + mVScrollBar->clear_visible(); + mHScrollBar->clear_visible(); + + for (int again = 1; again;) { + again = 0; + /* In continuous wrap mode, a change in width affects the total number of + lines in the buffer, and can leave the top line number incorrect, and + the top character no longer pointing at a valid line start */ + if (mContinuousWrap && !mWrapMargin && W!=oldWidth) { + int oldFirstChar = mFirstChar; + mNBufferLines = count_lines(0, buffer()->length(), true); + mFirstChar = line_start(mFirstChar); + mTopLineNum = count_lines(0, mFirstChar, true)+1; + absolute_top_line_number(oldFirstChar); + +#ifdef DEBUG + printf(" mNBufferLines=%d\n", mNBufferLines); +#endif // DEBUG + } + + /* reallocate and update the line starts array, which may have changed + size and / or contents. */ + int nvlines = (text_area.h + mMaxsize - 1) / mMaxsize; + if (nvlines < 1) nvlines = 1; + if (mNVisibleLines != nvlines) { + mNVisibleLines = nvlines; + if (mLineStarts) delete[] mLineStarts; + mLineStarts = new int [mNVisibleLines]; + } + + calc_line_starts(0, mNVisibleLines); + calc_last_char(); + + // figure the scrollbars + if (scrollbar_width()) { + /* Decide if the vertical scroll bar needs to be visible */ + if (scrollbar_align() & (FL_ALIGN_LEFT|FL_ALIGN_RIGHT) && + mNBufferLines >= mNVisibleLines - 1) + { + mVScrollBar->set_visible(); + if (scrollbar_align() & FL_ALIGN_LEFT) { + text_area.x = X+scrollbar_width()+LEFT_MARGIN; + text_area.w = W-scrollbar_width()-LEFT_MARGIN-RIGHT_MARGIN; + mVScrollBar->resize(X, text_area.y-TOP_MARGIN, scrollbar_width(), + text_area.h+TOP_MARGIN+BOTTOM_MARGIN); + } else { + text_area.x = X+LEFT_MARGIN; + text_area.w = W-scrollbar_width()-LEFT_MARGIN-RIGHT_MARGIN; + mVScrollBar->resize(X+W-scrollbar_width(), text_area.y-TOP_MARGIN, + scrollbar_width(), text_area.h+TOP_MARGIN+BOTTOM_MARGIN); + } + } + + /* + Decide if the horizontal scroll bar needs to be visible. If there + is a vertical scrollbar, a horizontal is always created too. This + is because the alternatives are unatractive: + * Dynamically creating a horizontal scrollbar based on the currently + visible lines is what the original nedit does, but it always wastes + space for the scrollbar even when it's not used. Since the FLTK + widget dynamically allocates the space for the scrollbar and + rearranges the widget to make room for it, this would create a very + visually displeasing "bounce" effect when the vertical scrollbar is + dragged. Trust me, I tried it and it looks really bad. + * The other alternative would be to keep track of what the longest + line in the entire buffer is and base the scrollbar on that. I + didn't do this because I didn't see any easy way to do that using + the nedit code and this could involve a lengthy calculation for + large buffers. If an efficient and non-costly way of doing this + can be found, this might be a way to go. + */ + /* WAS: Suggestion: Try turning the horizontal scrollbar on when + you first see a line that is too wide in the window, but then + don't turn it off (ie mix both of your solutions). */ + if (scrollbar_align() & (FL_ALIGN_TOP|FL_ALIGN_BOTTOM) && + (mVScrollBar->visible() || longest_vline() > text_area.w)) + { + if (!mHScrollBar->visible()) { + mHScrollBar->set_visible(); + again = 1; // loop again to see if we now need vert. & recalc sizes + } + if (scrollbar_align() & FL_ALIGN_TOP) { + text_area.y = Y + scrollbar_width()+TOP_MARGIN; + text_area.h = H - scrollbar_width()-TOP_MARGIN-BOTTOM_MARGIN; + mHScrollBar->resize(text_area.x-LEFT_MARGIN, Y, + text_area.w+LEFT_MARGIN+RIGHT_MARGIN, scrollbar_width()); + } else { + text_area.y = Y+TOP_MARGIN; + text_area.h = H - scrollbar_width()-TOP_MARGIN-BOTTOM_MARGIN; + mHScrollBar->resize(text_area.x-LEFT_MARGIN, Y+H-scrollbar_width(), + text_area.w+LEFT_MARGIN+RIGHT_MARGIN, scrollbar_width()); + } + } + } + } + + // user request to change viewport + if (mTopLineNumHint != mTopLineNum || mHorizOffsetHint != mHorizOffset) + scroll_(mTopLineNumHint, mHorizOffsetHint); + + // everything will fit in the viewport + if (mNBufferLines < mNVisibleLines || mBuffer == NULL || mBuffer->length() == 0) + scroll_(1, mHorizOffset); + /* if empty lines become visible, there may be an opportunity to + display more text by scrolling down */ + else while (mLineStarts[mNVisibleLines-2] == -1) + scroll_(mTopLineNum-1, mHorizOffset); + + // user request to display insert position + if (display_insert_position_hint) + display_insert(); + + // in case horizontal offset is now greater than longest line + int maxhoffset = max(0, longest_vline()-text_area.w); + if (mHorizOffset > maxhoffset) + scroll_(mTopLineNumHint, maxhoffset); + + mTopLineNumHint = mTopLineNum; + mHorizOffsetHint = mHorizOffset; + display_insert_position_hint = 0; + + if (mContinuousWrap || + hscrollbarvisible != mHScrollBar->visible() || + vscrollbarvisible != mVScrollBar->visible()) + redraw(); + + update_v_scrollbar(); + update_h_scrollbar(); +} + +/* +** Refresh a rectangle of the text display. left and top are in coordinates of +** the text drawing window +*/ +void Fl_Text_Display::draw_text( int left, int top, int width, int height ) { + int fontHeight, firstLine, lastLine, line; + + /* find the line number range of the display */ + fontHeight = mMaxsize ? mMaxsize : textsize_; + firstLine = ( top - text_area.y - fontHeight + 1 ) / fontHeight; + lastLine = ( top + height - text_area.y ) / fontHeight + 1; + + fl_push_clip( left, top, width, height ); + + /* draw the lines */ + for ( line = firstLine; line <= lastLine; line++ ) + draw_vline( line, left, left + width, 0, INT_MAX ); + + /* draw the line numbers if exposed area includes them */ + if (mLineNumWidth != 0 && left <= mLineNumLeft + mLineNumWidth) + draw_line_numbers(false); + + fl_pop_clip(); +} + +void Fl_Text_Display::redisplay_range(int startpos, int endpos) { + if (damage_range1_start == -1 && damage_range1_end == -1) { + damage_range1_start = startpos; + damage_range1_end = endpos; + } else if ((startpos >= damage_range1_start && startpos <= damage_range1_end) || + (endpos >= damage_range1_start && endpos <= damage_range1_end)) { + damage_range1_start = min(damage_range1_start, startpos); + damage_range1_end = max(damage_range1_end, endpos); + } else if (damage_range2_start == -1 && damage_range2_end == -1) { + damage_range2_start = startpos; + damage_range2_end = endpos; + } else { + damage_range2_start = min(damage_range2_start, startpos); + damage_range2_end = max(damage_range2_end, endpos); + } + damage(FL_DAMAGE_SCROLL); +} +/* +** Refresh all of the text between buffer positions "start" and "end" +** not including the character at the position "end". +** If end points beyond the end of the buffer, refresh the whole display +** after pos, including blank lines which are not technically part of +** any range of characters. +*/ +void Fl_Text_Display::draw_range(int startpos, int endpos) { + int i, startLine, lastLine, startIndex, endIndex; + + /* If the range is outside of the displayed text, just return */ + if ( endpos < mFirstChar || ( startpos > mLastChar && + !empty_vlines() ) ) return; + + /* Clean up the starting and ending values */ + if ( startpos < 0 ) startpos = 0; + if ( startpos > mBuffer->length() ) startpos = mBuffer->length(); + if ( endpos < 0 ) endpos = 0; + if ( endpos > mBuffer->length() ) endpos = mBuffer->length(); + + /* Get the starting and ending lines */ + if ( startpos < mFirstChar ) + startpos = mFirstChar; + if ( !position_to_line( startpos, &startLine ) ) + startLine = mNVisibleLines - 1; + if ( endpos >= mLastChar ) { + lastLine = mNVisibleLines - 1; + } else { + if ( !position_to_line( endpos, &lastLine ) ) { + /* shouldn't happen */ + lastLine = mNVisibleLines - 1; + } + } + + /* Get the starting and ending positions within the lines */ + startIndex = mLineStarts[ startLine ] == -1 ? 0 : + startpos - mLineStarts[ startLine ]; + if ( endpos >= mLastChar ) + endIndex = INT_MAX; + else if ( mLineStarts[ lastLine ] == -1 ) + endIndex = 0; + else + endIndex = endpos - mLineStarts[ lastLine ]; + + /* If the starting and ending lines are the same, redisplay the single + line between "start" and "end" */ + if ( startLine == lastLine ) { + draw_vline( startLine, 0, INT_MAX, startIndex, endIndex ); + return; + } + + /* Redisplay the first line from "start" */ + draw_vline( startLine, 0, INT_MAX, startIndex, INT_MAX ); + + /* Redisplay the lines in between at their full width */ + for ( i = startLine + 1; i < lastLine; i++ ) + draw_vline( i, 0, INT_MAX, 0, INT_MAX ); + + /* Redisplay the last line to "end" */ + draw_vline( lastLine, 0, INT_MAX, 0, endIndex ); +} + +/* +** Set the position of the text insertion cursor for text display +*/ +void Fl_Text_Display::insert_position( int newPos ) { + /* make sure new position is ok, do nothing if it hasn't changed */ + if ( newPos == mCursorPos ) + return; + if ( newPos < 0 ) newPos = 0; + if ( newPos > mBuffer->length() ) newPos = mBuffer->length(); + + /* cursor movement cancels vertical cursor motion column */ + mCursorPreferredCol = -1; + + /* erase the cursor at it's previous position */ + redisplay_range(mCursorPos - 1, mCursorPos + 1); + + mCursorPos = newPos; + + /* draw cursor at its new position */ + redisplay_range(mCursorPos - 1, mCursorPos + 1); +} + +void Fl_Text_Display::show_cursor(int b) { + mCursorOn = b; + redisplay_range(mCursorPos - 1, mCursorPos + 1); +} + +void Fl_Text_Display::cursor_style(int style) { + mCursorStyle = style; + if (mCursorOn) show_cursor(); +} + +void Fl_Text_Display::wrap_mode(int wrap, int wrapMargin) { + mWrapMargin = wrapMargin; + mContinuousWrap = wrap; + + if (buffer()) { + /* wrapping can change change the total number of lines, re-count */ + mNBufferLines = count_lines(0, buffer()->length(), true); + + /* changing wrap margins wrap or changing from wrapped mode to non-wrapped + can leave the character at the top no longer at a line start, and/or + change the line number */ + mFirstChar = line_start(mFirstChar); + mTopLineNum = count_lines(0, mFirstChar, true) + 1; + + reset_absolute_top_line_number(); + + /* update the line starts array */ + calc_line_starts(0, mNVisibleLines); + calc_last_char(); + } else { + // No buffer, so just clear the state info for later... + mNBufferLines = 0; + mFirstChar = 0; + mTopLineNum = 1; + mAbsTopLineNum = 0; + } + + resize(x(), y(), w(), h()); +} + +/* +** Insert "text" at the current cursor location. This has the same +** effect as inserting the text into the buffer using BufInsert and +** then moving the insert position after the newly inserted text, except +** that it's optimized to do less redrawing. +*/ +void Fl_Text_Display::insert(const char* text) { + int pos = mCursorPos; + + mCursorToHint = pos + strlen( text ); + mBuffer->insert( pos, text ); + mCursorToHint = NO_HINT; +} + +/* +** Insert "text" (which must not contain newlines), overstriking the current +** cursor location. +*/ +void Fl_Text_Display::overstrike(const char* text) { + int startPos = mCursorPos; + Fl_Text_Buffer *buf = mBuffer; + int lineStart = buf->line_start( startPos ); + int textLen = strlen( text ); + int i, p, endPos, indent, startIndent, endIndent; + const char *c; + char ch, *paddedText = NULL; + + /* determine how many displayed character positions are covered */ + startIndent = mBuffer->count_displayed_characters( lineStart, startPos ); + indent = startIndent; + for ( c = text; *c != '\0'; c++ ) + indent += Fl_Text_Buffer::character_width( *c, indent, buf->tab_distance(), buf->null_substitution_character() ); + endIndent = indent; + + /* find which characters to remove, and if necessary generate additional + padding to make up for removed control characters at the end */ + indent = startIndent; + for ( p = startPos; ; p++ ) { + if ( p == buf->length() ) + break; + ch = buf->character( p ); + if ( ch == '\n' ) + break; + indent += Fl_Text_Buffer::character_width( ch, indent, buf->tab_distance(), buf->null_substitution_character() ); + if ( indent == endIndent ) { + p++; + break; + } else if ( indent > endIndent ) { + if ( ch != '\t' ) { + p++; + paddedText = new char [ textLen + FL_TEXT_MAX_EXP_CHAR_LEN + 1 ]; + strcpy( paddedText, text ); + for ( i = 0; i < indent - endIndent; i++ ) + paddedText[ textLen + i ] = ' '; + paddedText[ textLen + i ] = '\0'; + } + break; + } + } + endPos = p; + + mCursorToHint = startPos + textLen; + buf->replace( startPos, endPos, paddedText == NULL ? text : paddedText ); + mCursorToHint = NO_HINT; + if ( paddedText != NULL ) + delete [] paddedText; +} + +/* +** Translate a buffer text position to the XY location where the top left +** of the cursor would be positioned to point to that character. Returns +** 0 if the position is not displayed because it is VERTICALLY out +** of view. If the position is horizontally out of view, returns the +** X coordinate where the position would be if it were visible. +*/ + +int Fl_Text_Display::position_to_xy( int pos, int* X, int* Y ) { + int charIndex, lineStartPos, fontHeight, lineLen; + int visLineNum, charLen, outIndex, xStep, charStyle; + char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ]; + const char *lineStr; + +// printf("position_to_xy(pos=%d, X=%p, Y=%p)\n", pos, X, Y); + + /* If position is not displayed, return false */ + if (pos < mFirstChar || (pos > mLastChar && !empty_vlines())) { +// printf(" returning 0\n" +// " mFirstChar=%d, mLastChar=%d, empty_vlines()=0\n", +// mFirstChar, mLastChar); + return 0; + } + + /* Calculate Y coordinate */ + if (!position_to_line(pos, &visLineNum)) { +// puts(" returning 0\n" +// " position_to_line()=0"); + return 0; + } + + if (visLineNum < 0 || visLineNum > mNBufferLines) { +// printf(" returning 0\n" +// " visLineNum=%d, mNBufferLines=%d\n", +// visLineNum, mNBufferLines); + return 0; + } + + fontHeight = mMaxsize; + *Y = text_area.y + visLineNum * fontHeight; + + /* Get the text, length, and buffer position of the line. If the position + is beyond the end of the buffer and should be at the first position on + the first empty line, don't try to get or scan the text */ + lineStartPos = mLineStarts[visLineNum]; + if ( lineStartPos == -1 ) { + *X = text_area.x - mHorizOffset; + return 1; + } + lineLen = vline_length( visLineNum ); + lineStr = mBuffer->text_range( lineStartPos, lineStartPos + lineLen ); + + /* Step through character positions from the beginning of the line + to "pos" to calculate the X coordinate */ + xStep = text_area.x - mHorizOffset; + outIndex = 0; + for ( charIndex = 0; charIndex < lineLen && charIndex < pos - lineStartPos; charIndex++ ) { + charLen = Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar, + mBuffer->tab_distance(), mBuffer->null_substitution_character() ); + charStyle = position_style( lineStartPos, lineLen, charIndex, + outIndex ); + xStep += string_width( expandedChar, charLen, charStyle ); + outIndex += charLen; + } + *X = xStep; + free((char *)lineStr); + return 1; +} + +/* +** Find the line number of position "pos". Note: this only works for +** displayed lines. If the line is not displayed, the function returns +** 0 (without the mLineStarts array it could turn in to very long +** calculation involving scanning large amounts of text in the buffer). +** If continuous wrap mode is on, returns the absolute line number (as opposed +** to the wrapped line number which is used for scrolling). +*/ +int Fl_Text_Display::position_to_linecol( int pos, int* lineNum, int* column ) { + int retVal; + + /* In continuous wrap mode, the absolute (non-wrapped) line count is + maintained separately, as needed. Only return it if we're actually + keeping track of it and pos is in the displayed text */ + if (mContinuousWrap) { + if (!maintaining_absolute_top_line_number() || + pos < mFirstChar || pos > mLastChar) + return 0; + *lineNum = mAbsTopLineNum + buffer()->count_lines(mFirstChar, pos); + *column + = buffer()->count_displayed_characters(buffer()->line_start(pos), pos); + return 1; + } + + retVal = position_to_line( pos, lineNum ); + if ( retVal ) { + *column = mBuffer->count_displayed_characters( + mLineStarts[ *lineNum ], pos ); + *lineNum += mTopLineNum; + } + return retVal; +} + +/* +** Return 1 if position (X, Y) is inside of the primary Fl_Text_Selection +*/ +int Fl_Text_Display::in_selection( int X, int Y ) { + int row, column, pos = xy_to_position( X, Y, CHARACTER_POS ); + Fl_Text_Buffer *buf = mBuffer; + + xy_to_rowcol( X, Y, &row, &column, CHARACTER_POS ); + if (range_touches_selection(buf->primary_selection(), mFirstChar, mLastChar)) + column = wrapped_column(row, column); + return buf->primary_selection()->includes(pos, buf->line_start( pos ), column); +} + +/* +** Correct a column number based on an unconstrained position (as returned by +** TextDXYToUnconstrainedPosition) to be relative to the last actual newline +** in the buffer before the row and column position given, rather than the +** last line start created by line wrapping. This is an adapter +** for rectangular selections and code written before continuous wrap mode, +** which thinks that the unconstrained column is the number of characters +** from the last newline. Obviously this is time consuming, because it +** invloves character re-counting. +*/ +int Fl_Text_Display::wrapped_column(int row, int column) { + int lineStart, dispLineStart; + + if (!mContinuousWrap || row < 0 || row > mNVisibleLines) + return column; + dispLineStart = mLineStarts[row]; + if (dispLineStart == -1) + return column; + lineStart = buffer()->line_start(dispLineStart); + return column + + buffer()->count_displayed_characters(lineStart, dispLineStart); +} + +/* +** Correct a row number from an unconstrained position (as returned by +** TextDXYToUnconstrainedPosition) to a straight number of newlines from the +** top line of the display. Because rectangular selections are based on +** newlines, rather than display wrapping, and anywhere a rectangular selection +** needs a row, it needs it in terms of un-wrapped lines. +*/ +int Fl_Text_Display::wrapped_row(int row) { + if (!mContinuousWrap || row < 0 || row > mNVisibleLines) + return row; + return buffer()->count_lines(mFirstChar, mLineStarts[row]); +} + +/* +** Scroll the display to bring insertion cursor into view. +** +** Note: it would be nice to be able to do this without counting lines twice +** (scroll_() counts them too) and/or to count from the most efficient +** starting point, but the efficiency of this routine is not as important to +** the overall performance of the text display. +*/ +void Fl_Text_Display::display_insert() { + int hOffset, topLine, X, Y; + hOffset = mHorizOffset; + topLine = mTopLineNum; + +// FIXME: I don't understand this well enough to know if it is correct +// it is different than nedit 5.3 + if (insert_position() < mFirstChar) { + topLine -= count_lines(insert_position(), mFirstChar, false); + } else if (mLineStarts[mNVisibleLines-2] != -1) { + int lastChar = buffer()->line_end(mLineStarts[mNVisibleLines-2]); + if (insert_position() >= lastChar) + topLine + += count_lines(lastChar - (wrap_uses_character(mLastChar) ? 0 : 1), + insert_position(), false); + } + + /* Find the new setting for horizontal offset (this is a bit ungraceful). + If the line is visible, just use PositionToXY to get the position + to scroll to, otherwise, do the vertical scrolling first, then the + horizontal */ + if (!position_to_xy( mCursorPos, &X, &Y )) { + scroll_(topLine, hOffset); + if (!position_to_xy( mCursorPos, &X, &Y )) + return; /* Give up, it's not worth it (but why does it fail?) */ + } + if (X > text_area.x + text_area.w) + hOffset += X-(text_area.x + text_area.w); + else if (X < text_area.x) + hOffset += X-text_area.x; + + /* Do the scroll */ + if (topLine != mTopLineNum || hOffset != mHorizOffset) + scroll_(topLine, hOffset); +} + +void Fl_Text_Display::show_insert_position() { + display_insert_position_hint = 1; + resize(x(), y(), w(), h()); +} + +/* +** Cursor movement functions +*/ +int Fl_Text_Display::move_right() { + if ( mCursorPos >= mBuffer->length() ) + return 0; + insert_position( mCursorPos + 1 ); + return 1; +} + +int Fl_Text_Display::move_left() { + if ( mCursorPos <= 0 ) + return 0; + insert_position( mCursorPos - 1 ); + return 1; +} + +int Fl_Text_Display::move_up() { + int lineStartPos, column, prevLineStartPos, newPos, visLineNum; + + /* Find the position of the start of the line. Use the line starts array + if possible */ + if ( position_to_line( mCursorPos, &visLineNum ) ) + lineStartPos = mLineStarts[ visLineNum ]; + else { + lineStartPos = buffer()->line_start( mCursorPos ); + visLineNum = -1; + } + if ( lineStartPos == 0 ) + return 0; + + /* Decide what column to move to, if there's a preferred column use that */ + column = mCursorPreferredCol >= 0 ? mCursorPreferredCol : + mBuffer->count_displayed_characters( lineStartPos, mCursorPos ); + + /* count forward from the start of the previous line to reach the column */ + if ( visLineNum != -1 && visLineNum != 0 ) + prevLineStartPos = mLineStarts[ visLineNum - 1 ]; + else + prevLineStartPos = buffer()->rewind_lines( lineStartPos, 1 ); + newPos = mBuffer->skip_displayed_characters( prevLineStartPos, column ); + if (mContinuousWrap) + newPos = min(newPos, line_end(prevLineStartPos, true)); + + /* move the cursor */ + insert_position( newPos ); + + /* if a preferred column wasn't aleady established, establish it */ + mCursorPreferredCol = column; + return 1; +} + +int Fl_Text_Display::move_down() { + int lineStartPos, column, nextLineStartPos, newPos, visLineNum; + + if ( mCursorPos == mBuffer->length() ) + return 0; + if ( position_to_line( mCursorPos, &visLineNum ) ) + lineStartPos = mLineStarts[ visLineNum ]; + else { + lineStartPos = buffer()->line_start( mCursorPos ); + visLineNum = -1; + } + column = mCursorPreferredCol >= 0 ? mCursorPreferredCol : + mBuffer->count_displayed_characters( lineStartPos, mCursorPos ); + nextLineStartPos = skip_lines( lineStartPos, 1, true ); + newPos = mBuffer->skip_displayed_characters( nextLineStartPos, column ); + if (mContinuousWrap) + newPos = min(newPos, line_end(nextLineStartPos, true)); + + insert_position( newPos ); + mCursorPreferredCol = column; + return 1; +} + +/* +** Same as BufCountLines, but takes in to account wrapping if wrapping is +** turned on. If the caller knows that startPos is at a line start, it +** can pass "startPosIsLineStart" as True to make the call more efficient +** by avoiding the additional step of scanning back to the last newline. +*/ +int Fl_Text_Display::count_lines(int startPos, int endPos, + bool startPosIsLineStart) { + int retLines, retPos, retLineStart, retLineEnd; + +#ifdef DEBUG + printf("Fl_Text_Display::count_line(startPos=%d, endPos=%d, startPosIsLineStart=%d\n", + startPos, endPos, startPosIsLineStart); +#endif // DEBUG + + /* If we're not wrapping use simple (and more efficient) BufCountLines */ + if (!mContinuousWrap) + return buffer()->count_lines(startPos, endPos); + + wrapped_line_counter(buffer(), startPos, endPos, INT_MAX, + startPosIsLineStart, 0, &retPos, &retLines, &retLineStart, + &retLineEnd); + +#ifdef DEBUG + printf("retPos=%d, retLines=%d, retLineStart=%d, retLineEnd=%d\n", + retPos, retLines, retLineStart, retLineEnd); +#endif // DEBUG + + return retLines; +} + +/* +** Same as BufCountForwardNLines, but takes in to account line breaks when +** wrapping is turned on. If the caller knows that startPos is at a line start, +** it can pass "startPosIsLineStart" as True to make the call more efficient +** by avoiding the additional step of scanning back to the last newline. +*/ +int Fl_Text_Display::skip_lines(int startPos, int nLines, + bool startPosIsLineStart) { + int retLines, retPos, retLineStart, retLineEnd; + + /* if we're not wrapping use more efficient BufCountForwardNLines */ + if (!mContinuousWrap) + return buffer()->skip_lines(startPos, nLines); + + /* wrappedLineCounter can't handle the 0 lines case */ + if (nLines == 0) + return startPos; + + /* use the common line counting routine to count forward */ + wrapped_line_counter(buffer(), startPos, buffer()->length(), + nLines, startPosIsLineStart, 0, &retPos, &retLines, &retLineStart, + &retLineEnd); + return retPos; +} + +/* +** Same as BufEndOfLine, but takes in to account line breaks when wrapping +** is turned on. If the caller knows that startPos is at a line start, it +** can pass "startPosIsLineStart" as True to make the call more efficient +** by avoiding the additional step of scanning back to the last newline. +** +** Note that the definition of the end of a line is less clear when continuous +** wrap is on. With continuous wrap off, it's just a pointer to the newline +** that ends the line. When it's on, it's the character beyond the last +** DISPLAYABLE character on the line, where a whitespace character which has +** been "converted" to a newline for wrapping is not considered displayable. +** Also note that, a line can be wrapped at a non-whitespace character if the +** line had no whitespace. In this case, this routine returns a pointer to +** the start of the next line. This is also consistent with the model used by +** visLineLength. +*/ +int Fl_Text_Display::line_end(int pos, bool startPosIsLineStart) { + int retLines, retPos, retLineStart, retLineEnd; + + /* If we're not wrapping use more efficien BufEndOfLine */ + if (!mContinuousWrap) + return buffer()->line_end(pos); + + if (pos == buffer()->length()) + return pos; + wrapped_line_counter(buffer(), pos, buffer()->length(), 1, + startPosIsLineStart, 0, &retPos, &retLines, &retLineStart, + &retLineEnd); + return retLineEnd; +} + +/* +** Same as BufStartOfLine, but returns the character after last wrap point +** rather than the last newline. +*/ +int Fl_Text_Display::line_start(int pos) { + int retLines, retPos, retLineStart, retLineEnd; + + /* If we're not wrapping, use the more efficient BufStartOfLine */ + if (!mContinuousWrap) + return buffer()->line_start(pos); + + wrapped_line_counter(buffer(), buffer()->line_start(pos), pos, INT_MAX, true, 0, + &retPos, &retLines, &retLineStart, &retLineEnd); + return retLineStart; +} + +/* +** Same as BufCountBackwardNLines, but takes in to account line breaks when +** wrapping is turned on. +*/ +int Fl_Text_Display::rewind_lines(int startPos, int nLines) { + Fl_Text_Buffer *buf = buffer(); + int pos, lineStart, retLines, retPos, retLineStart, retLineEnd; + + /* If we're not wrapping, use the more efficient BufCountBackwardNLines */ + if (!mContinuousWrap) + return buf->rewind_lines(startPos, nLines); + + pos = startPos; + while (true) { + lineStart = buf->line_start(pos); + wrapped_line_counter(buf, lineStart, pos, INT_MAX, + true, 0, &retPos, &retLines, &retLineStart, &retLineEnd); + if (retLines > nLines) + return skip_lines(lineStart, retLines-nLines, + true); + nLines -= retLines; + pos = lineStart - 1; + if (pos < 0) + return 0; + nLines -= 1; + } +} + +static inline int fl_isseparator(int c) { + return c != '$' && c != '_' && (isspace(c) || ispunct(c)); +} + +void Fl_Text_Display::next_word() { + int pos = insert_position(); + while (pos < buffer()->length() && !fl_isseparator(buffer()->character(pos))) { + pos++; + } + while (pos < buffer()->length() && fl_isseparator(buffer()->character(pos))) { + pos++; + } + + insert_position( pos ); +} + +void Fl_Text_Display::previous_word() { + int pos = insert_position(); + if (pos==0) return; + pos--; + while (pos && fl_isseparator(buffer()->character(pos))) { + pos--; + } + while (pos && !fl_isseparator(buffer()->character(pos))) { + pos--; + } + if (fl_isseparator(buffer()->character(pos))) pos++; + + insert_position( pos ); +} + +/* +** Callback attached to the text buffer to receive delete information before +** the modifications are actually made. +*/ +void Fl_Text_Display::buffer_predelete_cb(int pos, int nDeleted, void *cbArg) { + Fl_Text_Display *textD = (Fl_Text_Display *)cbArg; + if (textD->mContinuousWrap && + (textD->mFixedFontWidth == -1 || textD->mModifyingTabDistance)) + /* Note: we must perform this measurement, even if there is not a + single character deleted; the number of "deleted" lines is the + number of visual lines spanned by the real line in which the + modification takes place. + Also, a modification of the tab distance requires the same + kind of calculations in advance, even if the font width is "fixed", + because when the width of the tab characters changes, the layout + of the text may be completely different. */ + textD->measure_deleted_lines(pos, nDeleted); + else + textD->mSuppressResync = 0; /* Probably not needed, but just in case */ +} + +/* +** Callback attached to the text buffer to receive modification information +*/ +void Fl_Text_Display::buffer_modified_cb( int pos, int nInserted, int nDeleted, + int nRestyled, const char *deletedText, void *cbArg ) { + int linesInserted, linesDeleted, startDispPos, endDispPos; + Fl_Text_Display *textD = ( Fl_Text_Display * ) cbArg; + Fl_Text_Buffer *buf = textD->mBuffer; + int oldFirstChar = textD->mFirstChar; + int scrolled, origCursorPos = textD->mCursorPos; + int wrapModStart, wrapModEnd; + + /* buffer modification cancels vertical cursor motion column */ + if ( nInserted != 0 || nDeleted != 0 ) + textD->mCursorPreferredCol = -1; + + /* Count the number of lines inserted and deleted, and in the case + of continuous wrap mode, how much has changed */ + if (textD->mContinuousWrap) { + textD->find_wrap_range(deletedText, pos, nInserted, nDeleted, + &wrapModStart, &wrapModEnd, &linesInserted, &linesDeleted); + } else { + linesInserted = nInserted == 0 ? 0 : + buf->count_lines( pos, pos + nInserted ); + linesDeleted = nDeleted == 0 ? 0 : countlines( deletedText ); + } + + /* Update the line starts and mTopLineNum */ + if ( nInserted != 0 || nDeleted != 0 ) { + if (textD->mContinuousWrap) { + textD->update_line_starts( wrapModStart, wrapModEnd-wrapModStart, + nDeleted + pos-wrapModStart + (wrapModEnd-(pos+nInserted)), + linesInserted, linesDeleted, &scrolled ); + } else { + textD->update_line_starts( pos, nInserted, nDeleted, linesInserted, + linesDeleted, &scrolled ); + } + } else + scrolled = 0; + + /* If we're counting non-wrapped lines as well, maintain the absolute + (non-wrapped) line number of the text displayed */ + if (textD->maintaining_absolute_top_line_number() && + (nInserted != 0 || nDeleted != 0)) { + if (pos + nDeleted < oldFirstChar) + textD->mAbsTopLineNum += buf->count_lines(pos, pos + nInserted) - + countlines(deletedText); + else if (pos < oldFirstChar) + textD->reset_absolute_top_line_number(); + } + + /* Update the line count for the whole buffer */ + textD->mNBufferLines += linesInserted - linesDeleted; + + /* Update the cursor position */ + if ( textD->mCursorToHint != NO_HINT ) { + textD->mCursorPos = textD->mCursorToHint; + textD->mCursorToHint = NO_HINT; + } else if ( textD->mCursorPos > pos ) { + if ( textD->mCursorPos < pos + nDeleted ) + textD->mCursorPos = pos; + else + textD->mCursorPos += nInserted - nDeleted; + } + + // refigure scrollbars & stuff + textD->resize(textD->x(), textD->y(), textD->w(), textD->h()); + + // don't need to do anything else if not visible? + if (!textD->visible_r()) return; + + /* If the changes caused scrolling, re-paint everything and we're done. */ + if ( scrolled ) { + textD->damage(FL_DAMAGE_EXPOSE); + if ( textD->mStyleBuffer ) /* See comments in extendRangeForStyleMods */ + textD->mStyleBuffer->primary_selection()->selected(0); + return; + } + + /* If the changes didn't cause scrolling, decide the range of characters + that need to be re-painted. Also if the cursor position moved, be + sure that the redisplay range covers the old cursor position so the + old cursor gets erased, and erase the bits of the cursor which extend + beyond the left and right edges of the text. */ + startDispPos = textD->mContinuousWrap ? wrapModStart : pos; + if ( origCursorPos == startDispPos && textD->mCursorPos != startDispPos ) + startDispPos = min( startDispPos, origCursorPos - 1 ); + if ( linesInserted == linesDeleted ) { + if ( nInserted == 0 && nDeleted == 0 ) + endDispPos = pos + nRestyled; + else { + endDispPos = textD->mContinuousWrap ? wrapModEnd : + buf->line_end( pos + nInserted ) + 1; + // CET - FIXME if ( origCursorPos >= startDispPos && + // ( origCursorPos <= endDispPos || endDispPos == buf->length() ) ) + } + + if (linesInserted > 1) textD->draw_line_numbers(false); + } else { + endDispPos = textD->mLastChar + 1; + // CET - FIXME if ( origCursorPos >= pos ) + /* If more than one line is inserted/deleted, a line break may have + been inserted or removed in between, and the line numbers may + have changed. If only one line is altered, line numbers cannot + be affected (the insertion or removal of a line break always + results in at least two lines being redrawn). */ + textD->draw_line_numbers(false); + } + + /* If there is a style buffer, check if the modification caused additional + changes that need to be redisplayed. (Redisplaying separately would + cause double-redraw on almost every modification involving styled + text). Extend the redraw range to incorporate style changes */ + if ( textD->mStyleBuffer ) + textD->extend_range_for_styles( &startDispPos, &endDispPos ); + + /* Redisplay computed range */ + textD->redisplay_range( startDispPos, endDispPos ); +} + +/* +** In continuous wrap mode, internal line numbers are calculated after +** wrapping. A separate non-wrapped line count is maintained when line +** numbering is turned on. There is some performance cost to maintaining this +** line count, so normally absolute line numbers are not tracked if line +** numbering is off. This routine allows callers to specify that they still +** want this line count maintained (for use via TextDPosToLineAndCol). +** More specifically, this allows the line number reported in the statistics +** line to be calibrated in absolute lines, rather than post-wrapped lines. +*/ +void Fl_Text_Display::maintain_absolute_top_line_number(int state) { + mNeedAbsTopLineNum = state; + reset_absolute_top_line_number(); +} + +/* +** Returns the absolute (non-wrapped) line number of the first line displayed. +** Returns 0 if the absolute top line number is not being maintained. +*/ +int Fl_Text_Display::get_absolute_top_line_number() { + if (!mContinuousWrap) + return mTopLineNum; + if (maintaining_absolute_top_line_number()) + return mAbsTopLineNum; + return 0; +} + +/* +** Re-calculate absolute top line number for a change in scroll position. +*/ +void Fl_Text_Display::absolute_top_line_number(int oldFirstChar) { + if (maintaining_absolute_top_line_number()) { + if (mFirstChar < oldFirstChar) + mAbsTopLineNum -= buffer()->count_lines(mFirstChar, oldFirstChar); + else + mAbsTopLineNum += buffer()->count_lines(oldFirstChar, mFirstChar); + } +} + +/* +** Return true if a separate absolute top line number is being maintained +** (for displaying line numbers or showing in the statistics line). +*/ +int Fl_Text_Display::maintaining_absolute_top_line_number() { + return mContinuousWrap && + (mLineNumWidth != 0 || mNeedAbsTopLineNum); +} + +/* +** Count lines from the beginning of the buffer to reestablish the +** absolute (non-wrapped) top line number. If mode is not continuous wrap, +** or the number is not being maintained, does nothing. +*/ +void Fl_Text_Display::reset_absolute_top_line_number() { + mAbsTopLineNum = 1; + absolute_top_line_number(0); +} + +/* +** Find the line number of position "pos" relative to the first line of +** displayed text. Returns 0 if the line is not displayed. +*/ +int Fl_Text_Display::position_to_line( int pos, int *lineNum ) { + int i; + + *lineNum = 0; + if ( pos < mFirstChar ) return 0; + if ( pos > mLastChar ) { + if ( empty_vlines() ) { + if ( mLastChar < mBuffer->length() ) { + if ( !position_to_line( mLastChar, lineNum ) ) { + Fl::error("Fl_Text_Display::position_to_line(): Consistency check ptvl failed"); + return 0; + } + return ++( *lineNum ) <= mNVisibleLines - 1; + } else { + position_to_line( mLastChar - 1, lineNum ); + return 1; + } + } + return 0; + } + + for ( i = mNVisibleLines - 1; i >= 0; i-- ) { + if ( mLineStarts[ i ] != -1 && pos >= mLineStarts[ i ] ) { + *lineNum = i; + return 1; + } + } + return 0; /* probably never be reached */ +} + +/* +** Draw the text on a single line represented by "visLineNum" (the +** number of lines down from the top of the display), limited by +** "leftClip" and "rightClip" window coordinates and "leftCharIndex" and +** "rightCharIndex" character positions (not including the character at +** position "rightCharIndex"). +*/ +void Fl_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip, + int leftCharIndex, int rightCharIndex) { + Fl_Text_Buffer * buf = mBuffer; + int i, X, Y, startX, charIndex, lineStartPos, lineLen, fontHeight; + int stdCharWidth, charWidth, startIndex, charStyle, style; + int charLen, outStartIndex, outIndex; + int dispIndexOffset; + char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ], outStr[ MAX_DISP_LINE_LEN ]; + char *outPtr; + const char *lineStr; + +// printf("draw_vline(visLineNum=%d, leftClip=%d, rightClip=%d, leftCharIndex=%d, rightCharIndex=%d)\n", +// visLineNum, leftClip, rightClip, leftCharIndex, rightCharIndex); +// printf("nNVisibleLines=%d\n", mNVisibleLines); + + /* If line is not displayed, skip it */ + if ( visLineNum < 0 || visLineNum >= mNVisibleLines ) + return; + + /* Calculate Y coordinate of the string to draw */ + fontHeight = mMaxsize; + Y = text_area.y + visLineNum * fontHeight; + + /* Get the text, length, and buffer position of the line to display */ + lineStartPos = mLineStarts[ visLineNum ]; +// printf("lineStartPos=%d\n", lineStartPos); + if ( lineStartPos == -1 ) { + lineLen = 0; + lineStr = NULL; + } else { + lineLen = vline_length( visLineNum ); + lineStr = buf->text_range( lineStartPos, lineStartPos + lineLen ); + } + + /* Space beyond the end of the line is still counted in units of characters + of a standardized character width (this is done mostly because style + changes based on character position can still occur in this region due + to rectangular Fl_Text_Selections). stdCharWidth must be non-zero to + prevent a potential infinite loop if X does not advance */ + stdCharWidth = TMPFONTWIDTH; //mFontStruct->max_bounds.width; + if ( stdCharWidth <= 0 ) { + Fl::error("Fl_Text_Display::draw_vline(): bad font measurement"); + free((void *)lineStr); + return; + } + + /* Shrink the clipping range to the active display area */ + leftClip = max( text_area.x, leftClip ); + rightClip = min( rightClip, text_area.x + text_area.w ); + + /* Rectangular Fl_Text_Selections are based on "real" line starts (after + a newline or start of buffer). Calculate the difference between the + last newline position and the line start we're using. Since scanning + back to find a newline is expensive, only do so if there's actually a + rectangular Fl_Text_Selection which needs it */ + if (mContinuousWrap && (range_touches_selection(buf->primary_selection(), + lineStartPos, lineStartPos + lineLen) || range_touches_selection( + buf->secondary_selection(), lineStartPos, lineStartPos + lineLen) || + range_touches_selection(buf->highlight_selection(), lineStartPos, + lineStartPos + lineLen))) { + dispIndexOffset = buf->count_displayed_characters( + buf->line_start(lineStartPos), lineStartPos); + } else + dispIndexOffset = 0; + + /* Step through character positions from the beginning of the line (even if + that's off the left edge of the displayed area) to find the first + character position that's not clipped, and the X coordinate for drawing + that character */ + X = text_area.x - mHorizOffset; + outIndex = 0; + for ( charIndex = 0; ; charIndex++ ) { + charLen = charIndex >= lineLen ? 1 : + Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, + expandedChar, buf->tab_distance(), buf->null_substitution_character() ); + style = position_style( lineStartPos, lineLen, charIndex, + outIndex + dispIndexOffset ); + charWidth = charIndex >= lineLen ? stdCharWidth : + string_width( expandedChar, charLen, style ); + if ( X + charWidth >= leftClip && charIndex >= leftCharIndex ) { + startIndex = charIndex; + outStartIndex = outIndex; + startX = X; + break; + } + X += charWidth; + outIndex += charLen; + } + + /* Scan character positions from the beginning of the clipping range, and + draw parts whenever the style changes (also note if the cursor is on + this line, and where it should be drawn to take advantage of the x + position which we've gone to so much trouble to calculate) */ + /* since characters between style may overlap, we draw the full + background first */ + int sX = startX; + outPtr = outStr; + outIndex = outStartIndex; + X = startX; + for ( charIndex = startIndex; charIndex < rightCharIndex; charIndex++ ) { + charLen = charIndex >= lineLen ? 1 : + Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar, + buf->tab_distance(), buf->null_substitution_character() ); + charStyle = position_style( lineStartPos, lineLen, charIndex, + outIndex + dispIndexOffset ); + for ( i = 0; i < charLen; i++ ) { + if ( i != 0 && charIndex < lineLen && lineStr[ charIndex ] == '\t' ) + charStyle = position_style( lineStartPos, lineLen, + charIndex, outIndex + dispIndexOffset ); + if ( charStyle != style ) { + draw_string( style|BG_ONLY_MASK, sX, Y, X, outStr, outPtr - outStr ); + outPtr = outStr; + sX = X; + style = charStyle; + } + if ( charIndex < lineLen ) { + *outPtr = expandedChar[ i ]; + charWidth = string_width( &expandedChar[ i ], 1, charStyle ); + } else + charWidth = stdCharWidth; + outPtr++; + X += charWidth; + outIndex++; + } + if ( outPtr - outStr + FL_TEXT_MAX_EXP_CHAR_LEN >= MAX_DISP_LINE_LEN || X >= rightClip ) + break; + } + draw_string( style|BG_ONLY_MASK, sX, Y, X, outStr, outPtr - outStr ); + + /* now draw the text over the previously erased background */ + outPtr = outStr; + outIndex = outStartIndex; + X = startX; + for ( charIndex = startIndex; charIndex < rightCharIndex; charIndex++ ) { + charLen = charIndex >= lineLen ? 1 : + Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar, + buf->tab_distance(), buf->null_substitution_character() ); + charStyle = position_style( lineStartPos, lineLen, charIndex, + outIndex + dispIndexOffset ); + for ( i = 0; i < charLen; i++ ) { + if ( i != 0 && charIndex < lineLen && lineStr[ charIndex ] == '\t' ) + charStyle = position_style( lineStartPos, lineLen, + charIndex, outIndex + dispIndexOffset ); + if ( charStyle != style ) { + draw_string( style|TEXT_ONLY_MASK, startX, Y, X, outStr, outPtr - outStr ); + outPtr = outStr; + startX = X; + style = charStyle; + } + if ( charIndex < lineLen ) { + *outPtr = expandedChar[ i ]; + charWidth = string_width( &expandedChar[ i ], 1, charStyle ); + } else + charWidth = stdCharWidth; + outPtr++; + X += charWidth; + outIndex++; + } + if ( outPtr - outStr + FL_TEXT_MAX_EXP_CHAR_LEN >= MAX_DISP_LINE_LEN || X >= rightClip ) + break; + } + + /* Draw the remaining style segment */ + draw_string( style|TEXT_ONLY_MASK, startX, Y, X, outStr, outPtr - outStr ); + + /* Draw the cursor if part of it appeared on the redisplayed part of + this line. Also check for the cases which are not caught as the + line is scanned above: when the cursor appears at the very end + of the redisplayed section. */ + /* CET - FIXME + if ( mCursorOn ) + { + if ( hasCursor ) + draw_cursor( cursorX, Y ); + else if ( charIndex < lineLen && ( lineStartPos + charIndex + 1 == cursorPos ) + && X == rightClip ) + { + if ( cursorPos >= buf->length() ) + draw_cursor( X - 1, Y ); + else + { + draw_cursor( X - 1, Y ); + } + } + } + */ + if ( lineStr != NULL ) + free((void *)lineStr); +} + +/* +** Draw a string or blank area according to parameter "style", using the +** appropriate colors and drawing method for that style, with top left +** corner at X, y. If style says to draw text, use "string" as source of +** characters, and draw "nChars", if style is FILL, erase +** rectangle where text would have drawn from X to toX and from Y to +** the maximum Y extent of the current font(s). +*/ +void Fl_Text_Display::draw_string( int style, int X, int Y, int toX, + const char *string, int nChars ) { + const Style_Table_Entry * styleRec; + + /* Draw blank area rather than text, if that was the request */ + if ( style & FILL_MASK ) { + if (style & TEXT_ONLY_MASK) return; + clear_rect( style, X, Y, toX - X, mMaxsize ); + return; + } + + /* Set font, color, and gc depending on style. For normal text, GCs + for normal drawing, or drawing within a Fl_Text_Selection or highlight are + pre-allocated and pre-configured. For syntax highlighting, GCs are + configured here, on the fly. */ + + Fl_Font font = textfont(); + int fsize = textsize(); + Fl_Color foreground; + Fl_Color background; + + if ( style & STYLE_LOOKUP_MASK ) { + int si = (style & STYLE_LOOKUP_MASK) - 'A'; + if (si < 0) si = 0; + else if (si >= mNStyles) si = mNStyles - 1; + + styleRec = mStyleTable + si; + font = styleRec->font; + fsize = styleRec->size; + + if (style & (HIGHLIGHT_MASK | PRIMARY_MASK)) { + if (Fl::focus() == this) background = selection_color(); + else background = fl_color_average(color(), selection_color(), 0.5f); + } else background = color(); + + foreground = fl_contrast(styleRec->color, background); + } else if (style & (HIGHLIGHT_MASK | PRIMARY_MASK)) { + if (Fl::focus() == this) background = selection_color(); + else background = fl_color_average(color(), selection_color(), 0.5f); + foreground = fl_contrast(textcolor(), background); + } else { + foreground = textcolor(); + background = color(); + } + + if (!(style & TEXT_ONLY_MASK)) { + fl_color( background ); + fl_rectf( X, Y, toX - X, mMaxsize ); + } + if (!(style & BG_ONLY_MASK)) { + fl_color( foreground ); + fl_font( font, fsize ); + fl_draw( string, nChars, X, Y + mMaxsize - fl_descent()); + } + + // CET - FIXME + /* If any space around the character remains unfilled (due to use of + different sized fonts for highlighting), fill in above or below + to erase previously drawn characters */ + /* + if (fs->ascent < mAscent) + clear_rect( style, X, Y, toX - X, mAscent - fs->ascent); + if (fs->descent < mDescent) + clear_rect( style, X, Y + mAscent + fs->descent, toX - x, + mDescent - fs->descent); + */ + /* Underline if style is secondary Fl_Text_Selection */ + + /* + if (style & SECONDARY_MASK) + XDrawLine(XtDisplay(mW), XtWindow(mW), gc, x, + y + mAscent, toX - 1, Y + fs->ascent); + */ +} + +/* +** Clear a rectangle with the appropriate background color for "style" +*/ +void Fl_Text_Display::clear_rect( int style, int X, int Y, + int width, int height ) { + /* A width of zero means "clear to end of window" to XClearArea */ + if ( width == 0 ) + return; + + if ( Fl::focus() != this ) { + if (style & (HIGHLIGHT_MASK | PRIMARY_MASK)) { + fl_color(fl_color_average(color(), selection_color(), 0.5f)); + } else { + fl_color( color() ); + } + fl_rectf( X, Y, width, height ); + } else if ( style & HIGHLIGHT_MASK ) { + fl_color( fl_contrast(textcolor(), color()) ); + fl_rectf( X, Y, width, height ); + } else if ( style & PRIMARY_MASK ) { + fl_color( selection_color() ); + fl_rectf( X, Y, width, height ); + } else { + fl_color( color() ); + fl_rectf( X, Y, width, height ); + } +} + + + +/* +** Draw a cursor with top center at X, y. +*/ +void Fl_Text_Display::draw_cursor( int X, int Y ) { + typedef struct { + int x1, y1, x2, y2; + } + Segment; + + Segment segs[ 5 ]; + int left, right, cursorWidth, midY; + // int fontWidth = mFontStruct->min_bounds.width, nSegs = 0; + int fontWidth = TMPFONTWIDTH; // CET - FIXME + int nSegs = 0; + int fontHeight = mMaxsize; + int bot = Y + fontHeight - 1; + + if ( X < text_area.x - 1 || X > text_area.x + text_area.w ) + return; + + /* For cursors other than the block, make them around 2/3 of a character + width, rounded to an even number of pixels so that X will draw an + odd number centered on the stem at x. */ + cursorWidth = 4; //(fontWidth/3) * 2; + left = X - cursorWidth / 2; + right = left + cursorWidth; + + /* Create segments and draw cursor */ + if ( mCursorStyle == CARET_CURSOR ) { + midY = bot - fontHeight / 5; + segs[ 0 ].x1 = left; segs[ 0 ].y1 = bot; segs[ 0 ].x2 = X; segs[ 0 ].y2 = midY; + segs[ 1 ].x1 = X; segs[ 1 ].y1 = midY; segs[ 1 ].x2 = right; segs[ 1 ].y2 = bot; + segs[ 2 ].x1 = left; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = X; segs[ 2 ].y2 = midY - 1; + segs[ 3 ].x1 = X; segs[ 3 ].y1 = midY - 1; segs[ 3 ].x2 = right; segs[ 3 ].y2 = bot; + nSegs = 4; + } else if ( mCursorStyle == NORMAL_CURSOR ) { + segs[ 0 ].x1 = left; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = right; segs[ 0 ].y2 = Y; + segs[ 1 ].x1 = X; segs[ 1 ].y1 = Y; segs[ 1 ].x2 = X; segs[ 1 ].y2 = bot; + segs[ 2 ].x1 = left; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = right; segs[ 2 ].y2 = bot; + nSegs = 3; + } else if ( mCursorStyle == HEAVY_CURSOR ) { + segs[ 0 ].x1 = X - 1; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = X - 1; segs[ 0 ].y2 = bot; + segs[ 1 ].x1 = X; segs[ 1 ].y1 = Y; segs[ 1 ].x2 = X; segs[ 1 ].y2 = bot; + segs[ 2 ].x1 = X + 1; segs[ 2 ].y1 = Y; segs[ 2 ].x2 = X + 1; segs[ 2 ].y2 = bot; + segs[ 3 ].x1 = left; segs[ 3 ].y1 = Y; segs[ 3 ].x2 = right; segs[ 3 ].y2 = Y; + segs[ 4 ].x1 = left; segs[ 4 ].y1 = bot; segs[ 4 ].x2 = right; segs[ 4 ].y2 = bot; + nSegs = 5; + } else if ( mCursorStyle == DIM_CURSOR ) { + midY = Y + fontHeight / 2; + segs[ 0 ].x1 = X; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = X; segs[ 0 ].y2 = Y; + segs[ 1 ].x1 = X; segs[ 1 ].y1 = midY; segs[ 1 ].x2 = X; segs[ 1 ].y2 = midY; + segs[ 2 ].x1 = X; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = X; segs[ 2 ].y2 = bot; + nSegs = 3; + } else if ( mCursorStyle == BLOCK_CURSOR ) { + right = X + fontWidth; + segs[ 0 ].x1 = X; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = right; segs[ 0 ].y2 = Y; + segs[ 1 ].x1 = right; segs[ 1 ].y1 = Y; segs[ 1 ].x2 = right; segs[ 1 ].y2 = bot; + segs[ 2 ].x1 = right; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = X; segs[ 2 ].y2 = bot; + segs[ 3 ].x1 = X; segs[ 3 ].y1 = bot; segs[ 3 ].x2 = X; segs[ 3 ].y2 = Y; + nSegs = 4; + } + fl_color( mCursor_color ); + + for ( int k = 0; k < nSegs; k++ ) { + fl_line( segs[ k ].x1, segs[ k ].y1, segs[ k ].x2, segs[ k ].y2 ); + } +} + +/* +** Determine the drawing method to use to draw a specific character from "buf". +** "lineStartPos" gives the character index where the line begins, "lineIndex", +** the number of characters past the beginning of the line, and "dispIndex", +** the number of displayed characters past the beginning of the line. Passing +** lineStartPos of -1 returns the drawing style for "no text". +** +** Why not just: position_style(pos)? Because style applies to blank areas +** of the window beyond the text boundaries, and because this routine must also +** decide whether a position is inside of a rectangular Fl_Text_Selection, and do +** so efficiently, without re-counting character positions from the start of the +** line. +** +** Note that style is a somewhat incorrect name, drawing method would +** be more appropriate. +*/ +int Fl_Text_Display::position_style( int lineStartPos, + int lineLen, int lineIndex, int dispIndex ) { + Fl_Text_Buffer * buf = mBuffer; + Fl_Text_Buffer *styleBuf = mStyleBuffer; + int pos, style = 0; + + if ( lineStartPos == -1 || buf == NULL ) + return FILL_MASK; + + pos = lineStartPos + min( lineIndex, lineLen ); + + if ( lineIndex >= lineLen ) + style = FILL_MASK; + else if ( styleBuf != NULL ) { + style = ( unsigned char ) styleBuf->character( pos ); + if (style == mUnfinishedStyle && mUnfinishedHighlightCB) { + /* encountered "unfinished" style, trigger parsing */ + (mUnfinishedHighlightCB)( pos, mHighlightCBArg); + style = (unsigned char) styleBuf->character( pos); + } + } + if (buf->primary_selection()->includes(pos, lineStartPos, dispIndex)) + style |= PRIMARY_MASK; + if (buf->highlight_selection()->includes(pos, lineStartPos, dispIndex)) + style |= HIGHLIGHT_MASK; + if (buf->secondary_selection()->includes(pos, lineStartPos, dispIndex)) + style |= SECONDARY_MASK; + return style; +} + +/* +** Find the width of a string in the font of a particular style +*/ +int Fl_Text_Display::string_width( const char *string, int length, int style ) { + Fl_Font font; + int fsize; + + if ( style & STYLE_LOOKUP_MASK ) { + int si = (style & STYLE_LOOKUP_MASK) - 'A'; + if (si < 0) si = 0; + else if (si >= mNStyles) si = mNStyles - 1; + + font = mStyleTable[si].font; + fsize = mStyleTable[si].size; + } else { + font = textfont(); + fsize = textsize(); + } + fl_font( font, fsize ); + + return ( int ) ( fl_width( string, length ) ); +} + +/* +** Translate window coordinates to the nearest (insert cursor or character +** cell) text position. The parameter posType specifies how to interpret the +** position: CURSOR_POS means translate the coordinates to the nearest cursor +** position, and CHARACTER_POS means return the position of the character +** closest to (X, Y). +*/ +int Fl_Text_Display::xy_to_position( int X, int Y, int posType ) { + int charIndex, lineStart, lineLen, fontHeight; + int charWidth, charLen, charStyle, visLineNum, xStep, outIndex; + char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ]; + const char *lineStr; + + /* Find the visible line number corresponding to the Y coordinate */ + fontHeight = mMaxsize; + visLineNum = ( Y - text_area.y ) / fontHeight; + if ( visLineNum < 0 ) + return mFirstChar; + if ( visLineNum >= mNVisibleLines ) + visLineNum = mNVisibleLines - 1; + + /* Find the position at the start of the line */ + lineStart = mLineStarts[ visLineNum ]; + + /* If the line start was empty, return the last position in the buffer */ + if ( lineStart == -1 ) + return mBuffer->length(); + + /* Get the line text and its length */ + lineLen = vline_length( visLineNum ); + lineStr = mBuffer->text_range( lineStart, lineStart + lineLen ); + + /* Step through character positions from the beginning of the line + to find the character position corresponding to the X coordinate */ + xStep = text_area.x - mHorizOffset; + outIndex = 0; + for ( charIndex = 0; charIndex < lineLen; charIndex++ ) { + charLen = Fl_Text_Buffer::expand_character( lineStr[ charIndex ], outIndex, expandedChar, + mBuffer->tab_distance(), mBuffer->null_substitution_character() ); + charStyle = position_style( lineStart, lineLen, charIndex, outIndex ); + charWidth = string_width( expandedChar, charLen, charStyle ); + if ( X < xStep + ( posType == CURSOR_POS ? charWidth / 2 : charWidth ) ) { + free((char *)lineStr); + return lineStart + charIndex; + } + xStep += charWidth; + outIndex += charLen; + } + + /* If the X position was beyond the end of the line, return the position + of the newline at the end of the line */ + free((char *)lineStr); + return lineStart + lineLen; +} + +/* +** Translate window coordinates to the nearest row and column number for +** positioning the cursor. This, of course, makes no sense when the font is +** proportional, since there are no absolute columns. The parameter posType +** specifies how to interpret the position: CURSOR_POS means translate the +** coordinates to the nearest position between characters, and CHARACTER_POS +** means translate the position to the nearest character cell. +*/ +void Fl_Text_Display::xy_to_rowcol( int X, int Y, int *row, + int *column, int posType ) { + int fontHeight = mMaxsize; + int fontWidth = TMPFONTWIDTH; //mFontStruct->max_bounds.width; + + /* Find the visible line number corresponding to the Y coordinate */ + *row = ( Y - text_area.y ) / fontHeight; + if ( *row < 0 ) * row = 0; + if ( *row >= mNVisibleLines ) * row = mNVisibleLines - 1; + *column = ( ( X - text_area.x ) + mHorizOffset + + ( posType == CURSOR_POS ? fontWidth / 2 : 0 ) ) / fontWidth; + if ( *column < 0 ) * column = 0; +} + +/* +** Offset the line starts array, mTopLineNum, mFirstChar and lastChar, for a new +** vertical scroll position given by newTopLineNum. If any currently displayed +** lines will still be visible, salvage the line starts values, otherwise, +** count lines from the nearest known line start (start or end of buffer, or +** the closest value in the mLineStarts array) +*/ +void Fl_Text_Display::offset_line_starts( int newTopLineNum ) { + int oldTopLineNum = mTopLineNum; + int oldFirstChar = mFirstChar; + int lineDelta = newTopLineNum - oldTopLineNum; + int nVisLines = mNVisibleLines; + int *lineStarts = mLineStarts; + int i, lastLineNum; + Fl_Text_Buffer *buf = mBuffer; + + /* If there was no offset, nothing needs to be changed */ + if ( lineDelta == 0 ) + return; + + /* Find the new value for mFirstChar by counting lines from the nearest + known line start (start or end of buffer, or the closest value in the + lineStarts array) */ + lastLineNum = oldTopLineNum + nVisLines - 1; + if ( newTopLineNum < oldTopLineNum && newTopLineNum < -lineDelta ) { + mFirstChar = skip_lines( 0, newTopLineNum - 1, true ); + } else if ( newTopLineNum < oldTopLineNum ) { + mFirstChar = buffer()->rewind_lines( mFirstChar, -lineDelta ); + } else if ( newTopLineNum < lastLineNum ) { + mFirstChar = lineStarts[ newTopLineNum - oldTopLineNum ]; + } else if ( newTopLineNum - lastLineNum < mNBufferLines - newTopLineNum ) { + mFirstChar = skip_lines( lineStarts[ nVisLines - 1 ], + newTopLineNum - lastLineNum, true ); + } else { + mFirstChar = buffer()->rewind_lines( buf->length(), mNBufferLines - newTopLineNum + 1 ); + } + + /* Fill in the line starts array */ + if ( lineDelta < 0 && -lineDelta < nVisLines ) { + for ( i = nVisLines - 1; i >= -lineDelta; i-- ) + lineStarts[ i ] = lineStarts[ i + lineDelta ]; + calc_line_starts( 0, -lineDelta ); + } else if ( lineDelta > 0 && lineDelta < nVisLines ) { + for ( i = 0; i < nVisLines - lineDelta; i++ ) + lineStarts[ i ] = lineStarts[ i + lineDelta ]; + calc_line_starts( nVisLines - lineDelta, nVisLines - 1 ); + } else + calc_line_starts( 0, nVisLines ); + + /* Set lastChar and mTopLineNum */ + calc_last_char(); + mTopLineNum = newTopLineNum; + + /* If we're numbering lines or being asked to maintain an absolute line + number, re-calculate the absolute line number */ + absolute_top_line_number(oldFirstChar); +} + +/* +** Update the line starts array, mTopLineNum, mFirstChar and lastChar for text +** display "textD" after a modification to the text buffer, given by the +** position where the change began "pos", and the nmubers of characters +** and lines inserted and deleted. +*/ +void Fl_Text_Display::update_line_starts( int pos, int charsInserted, + int charsDeleted, int linesInserted, int linesDeleted, int *scrolled ) { + int * lineStarts = mLineStarts; + int i, lineOfPos, lineOfEnd, nVisLines = mNVisibleLines; + int charDelta = charsInserted - charsDeleted; + int lineDelta = linesInserted - linesDeleted; + + /* If all of the changes were before the displayed text, the display + doesn't change, just update the top line num and offset the line + start entries and first and last characters */ + if ( pos + charsDeleted < mFirstChar ) { + mTopLineNum += lineDelta; + for ( i = 0; i < nVisLines && lineStarts[i] != -1; i++ ) + lineStarts[ i ] += charDelta; + mFirstChar += charDelta; + mLastChar += charDelta; + *scrolled = 0; + return; + } + + /* The change began before the beginning of the displayed text, but + part or all of the displayed text was deleted */ + if ( pos < mFirstChar ) { + /* If some text remains in the window, anchor on that */ + if ( position_to_line( pos + charsDeleted, &lineOfEnd ) && + ++lineOfEnd < nVisLines && lineStarts[ lineOfEnd ] != -1 ) { + mTopLineNum = max( 1, mTopLineNum + lineDelta ); + mFirstChar = buffer()->rewind_lines( + lineStarts[ lineOfEnd ] + charDelta, lineOfEnd ); + /* Otherwise anchor on original line number and recount everything */ + } else { + if ( mTopLineNum > mNBufferLines + lineDelta ) { + mTopLineNum = 1; + mFirstChar = 0; + } else + mFirstChar = skip_lines( 0, mTopLineNum - 1, true ); + } + calc_line_starts( 0, nVisLines - 1 ); + /* calculate lastChar by finding the end of the last displayed line */ + calc_last_char(); + *scrolled = 1; + return; + } + + /* If the change was in the middle of the displayed text (it usually is), + salvage as much of the line starts array as possible by moving and + offsetting the entries after the changed area, and re-counting the + added lines or the lines beyond the salvaged part of the line starts + array */ + if ( pos <= mLastChar ) { + /* find line on which the change began */ + position_to_line( pos, &lineOfPos ); + /* salvage line starts after the changed area */ + if ( lineDelta == 0 ) { + for ( i = lineOfPos + 1; i < nVisLines && lineStarts[ i ] != -1; i++ ) + lineStarts[ i ] += charDelta; + } else if ( lineDelta > 0 ) { + for ( i = nVisLines - 1; i >= lineOfPos + lineDelta + 1; i-- ) + lineStarts[ i ] = lineStarts[ i - lineDelta ] + + ( lineStarts[ i - lineDelta ] == -1 ? 0 : charDelta ); + } else /* (lineDelta < 0) */ { + for ( i = max( 0, lineOfPos + 1 ); i < nVisLines + lineDelta; i++ ) + lineStarts[ i ] = lineStarts[ i - lineDelta ] + + ( lineStarts[ i - lineDelta ] == -1 ? 0 : charDelta ); + } + /* fill in the missing line starts */ + if ( linesInserted >= 0 ) + calc_line_starts( lineOfPos + 1, lineOfPos + linesInserted ); + if ( lineDelta < 0 ) + calc_line_starts( nVisLines + lineDelta, nVisLines ); + /* calculate lastChar by finding the end of the last displayed line */ + calc_last_char(); + *scrolled = 0; + return; + } + + /* Change was past the end of the displayed text, but displayable by virtue + of being an insert at the end of the buffer into visible blank lines */ + if ( empty_vlines() ) { + position_to_line( pos, &lineOfPos ); + calc_line_starts( lineOfPos, lineOfPos + linesInserted ); + calc_last_char(); + *scrolled = 0; + return; + } + + /* Change was beyond the end of the buffer and not visible, do nothing */ + *scrolled = 0; +} + +/* +** Scan through the text in the "textD"'s buffer and recalculate the line +** starts array values beginning at index "startLine" and continuing through +** (including) "endLine". It assumes that the line starts entry preceding +** "startLine" (or mFirstChar if startLine is 0) is good, and re-counts +** newlines to fill in the requested entries. Out of range values for +** "startLine" and "endLine" are acceptable. +*/ +void Fl_Text_Display::calc_line_starts( int startLine, int endLine ) { + int startPos, bufLen = mBuffer->length(); + int line, lineEnd, nextLineStart, nVis = mNVisibleLines; + int *lineStarts = mLineStarts; + + /* Clean up (possibly) messy input parameters */ + if ( endLine < 0 ) endLine = 0; + if ( endLine >= nVis ) endLine = nVis - 1; + if ( startLine < 0 ) startLine = 0; + if ( startLine >= nVis ) startLine = nVis - 1; + if ( startLine > endLine ) + return; + + /* Find the last known good line number -> position mapping */ + if ( startLine == 0 ) { + lineStarts[ 0 ] = mFirstChar; + startLine = 1; + } + startPos = lineStarts[ startLine - 1 ]; + + /* If the starting position is already past the end of the text, + fill in -1's (means no text on line) and return */ + if ( startPos == -1 ) { + for ( line = startLine; line <= endLine; line++ ) + lineStarts[ line ] = -1; + return; + } + + /* Loop searching for ends of lines and storing the positions of the + start of the next line in lineStarts */ + for ( line = startLine; line <= endLine; line++ ) { + find_line_end(startPos, true, &lineEnd, &nextLineStart); + startPos = nextLineStart; + if ( startPos >= bufLen ) { + /* If the buffer ends with a newline or line break, put + buf->length() in the next line start position (instead of + a -1 which is the normal marker for an empty line) to + indicate that the cursor may safely be displayed there */ + if ( line == 0 || ( lineStarts[ line - 1 ] != bufLen && + lineEnd != nextLineStart ) ) { + lineStarts[ line ] = bufLen; + line++; + } + break; + } + lineStarts[ line ] = startPos; + } + + /* Set any entries beyond the end of the text to -1 */ + for ( ; line <= endLine; line++ ) + lineStarts[ line ] = -1; +} + +/* +** Given a Fl_Text_Display with a complete, up-to-date lineStarts array, update +** the lastChar entry to point to the last buffer position displayed. +*/ +void Fl_Text_Display::calc_last_char() { + int i; + for (i = mNVisibleLines - 1; i >= 0 && mLineStarts[i] == -1; i--) ; + mLastChar = i < 0 ? 0 : line_end(mLineStarts[i], true); +} + +void Fl_Text_Display::scroll(int topLineNum, int horizOffset) { + mTopLineNumHint = topLineNum; + mHorizOffsetHint = horizOffset; + resize(x(), y(), w(), h()); +} + +void Fl_Text_Display::scroll_(int topLineNum, int horizOffset) { + /* Limit the requested scroll position to allowable values */ + if (topLineNum > mNBufferLines + 3 - mNVisibleLines) + topLineNum = mNBufferLines + 3 - mNVisibleLines; + if (topLineNum < 1) topLineNum = 1; + + if (horizOffset > longest_vline() - text_area.w) + horizOffset = longest_vline() - text_area.w; + if (horizOffset < 0) horizOffset = 0; + + /* Do nothing if scroll position hasn't actually changed or there's no + window to draw in yet */ + if (mHorizOffset == horizOffset && mTopLineNum == topLineNum) + return; + + /* If the vertical scroll position has changed, update the line + starts array and related counters in the text display */ + offset_line_starts(topLineNum); + + /* Just setting mHorizOffset is enough information for redisplay */ + mHorizOffset = horizOffset; + + // redraw all text + damage(FL_DAMAGE_EXPOSE); +} + +/* +** Update the minimum, maximum, slider size, page increment, and value +** for vertical scroll bar. +*/ +void Fl_Text_Display::update_v_scrollbar() { + /* The Vert. scroll bar value and slider size directly represent the top + line number, and the number of visible lines respectively. The scroll + bar maximum value is chosen to generally represent the size of the whole + buffer, with minor adjustments to keep the scroll bar widget happy */ +#ifdef DEBUG + printf("Fl_Text_Display::update_v_scrollbar():\n" + " mTopLineNum=%d, mNVisibleLines=%d, mNBufferLines=%d\n", + mTopLineNum, mNVisibleLines, mNBufferLines); +#endif // DEBUG + + mVScrollBar->value(mTopLineNum, mNVisibleLines, 1, mNBufferLines+2); + mVScrollBar->linesize(3); +} + +/* +** Update the minimum, maximum, slider size, page increment, and value +** for the horizontal scroll bar. +*/ +void Fl_Text_Display::update_h_scrollbar() { + int sliderMax = max(longest_vline(), text_area.w + mHorizOffset); + mHScrollBar->value( mHorizOffset, text_area.w, 0, sliderMax ); +} + +/* +** Callbacks for drag or valueChanged on scroll bars +*/ +void Fl_Text_Display::v_scrollbar_cb(Fl_Scrollbar* b, Fl_Text_Display* textD) { + if (b->value() == textD->mTopLineNum) return; + textD->scroll(b->value(), textD->mHorizOffset); +} + +void Fl_Text_Display::h_scrollbar_cb(Fl_Scrollbar* b, Fl_Text_Display* textD) { + if (b->value() == textD->mHorizOffset) return; + textD->scroll(textD->mTopLineNum, b->value()); +} + +/* +** Refresh the line number area. If clearAll is False, writes only over +** the character cell areas. Setting clearAll to True will clear out any +** stray marks outside of the character cell area, which might have been +** left from before a resize or font change. +*/ +void Fl_Text_Display::draw_line_numbers(bool clearAll) { +#if 0 + // FIXME: don't want this yet, so will leave for another time + + int y, line, visLine, nCols, lineStart; + char lineNumString[12]; + int lineHeight = mMaxsize ? mMaxsize : textsize_; + int charWidth = TMPFONTWIDTH; //mFontStruct->max_bounds.width; + + /* Don't draw if mLineNumWidth == 0 (line numbers are hidden), or widget is + not yet realized */ + if (mLineNumWidth == 0 || visible_r()) + return; + + /* GC is allocated on demand, since not everyone will use line numbering */ + if (textD->lineNumGC == NULL) { + XGCValues values; + values.foreground = textD->lineNumFGPixel; + values.background = textD->bgPixel; + values.font = textD->fontStruct->fid; + textD->lineNumGC = XtGetGC(textD->w, + GCFont| GCForeground | GCBackground, &values); + } + + /* Erase the previous contents of the line number area, if requested */ + if (clearAll) + XClearArea(XtDisplay(textD->w), XtWindow(textD->w), textD->lineNumLeft, + textD->top, textD->lineNumWidth, textD->height, False); + + /* Draw the line numbers, aligned to the text */ + nCols = min(11, textD->lineNumWidth / charWidth); + y = textD->top; + line = getAbsTopLineNum(textD); + for (visLine=0; visLine < textD->nVisibleLines; visLine++) { + lineStart = textD->lineStarts[visLine]; + if (lineStart != -1 && (lineStart==0 || + BufGetCharacter(textD->buffer, lineStart-1)=='\n')) { + sprintf(lineNumString, "%*d", nCols, line); + XDrawImageString(XtDisplay(textD->w), XtWindow(textD->w), + textD->lineNumGC, textD->lineNumLeft, y + textD->ascent, + lineNumString, strlen(lineNumString)); + line++; + } else { + XClearArea(XtDisplay(textD->w), XtWindow(textD->w), + textD->lineNumLeft, y, textD->lineNumWidth, + textD->ascent + textD->descent, False); + if (visLine == 0) + line++; + } + y += lineHeight; + } +#endif +} + +static int max( int i1, int i2 ) { + return i1 >= i2 ? i1 : i2; +} + +static int min( int i1, int i2 ) { + return i1 <= i2 ? i1 : i2; +} + +/* +** Count the number of newlines in a null-terminated text string; +*/ +static int countlines( const char *string ) { + const char * c; + int lineCount = 0; + + if (!string) return 0; + + for ( c = string; *c != '\0'; c++ ) + if ( *c == '\n' ) lineCount++; + return lineCount; +} + +/* +** Return the width in pixels of the displayed line pointed to by "visLineNum" +*/ +int Fl_Text_Display::measure_vline( int visLineNum ) { + int i, width = 0, len, style, lineLen = vline_length( visLineNum ); + int charCount = 0, lineStartPos = mLineStarts[ visLineNum ]; + char expandedChar[ FL_TEXT_MAX_EXP_CHAR_LEN ]; + + if (lineStartPos < 0 || lineLen == 0) return 0; + if ( mStyleBuffer == NULL ) { + for ( i = 0; i < lineLen; i++ ) { + len = mBuffer->expand_character( lineStartPos + i, + charCount, expandedChar ); + + fl_font( textfont(), textsize() ); + + width += ( int ) fl_width( expandedChar, len ); + + charCount += len; + } + } else { + for ( i = 0; i < lineLen; i++ ) { + len = mBuffer->expand_character( lineStartPos + i, + charCount, expandedChar ); + style = ( unsigned char ) mStyleBuffer->character( + lineStartPos + i ) - 'A'; + + if (style < 0) style = 0; + else if (style >= mNStyles) style = mNStyles - 1; + + fl_font( mStyleTable[ style ].font, mStyleTable[ style ].size ); + + width += ( int ) fl_width( expandedChar, len ); + + charCount += len; + } + } + return width; +} + +/* +** Return true if there are lines visible with no corresponding buffer text +*/ +int Fl_Text_Display::empty_vlines() { + return mNVisibleLines > 0 && + mLineStarts[ mNVisibleLines - 1 ] == -1; +} + +/* +** Return the length of a line (number of displayable characters) by examining +** entries in the line starts array rather than by scanning for newlines +*/ +int Fl_Text_Display::vline_length( int visLineNum ) { + int nextLineStart, lineStartPos; + + if (visLineNum < 0 || visLineNum >= mNVisibleLines) + return (0); + + lineStartPos = mLineStarts[ visLineNum ]; + + if ( lineStartPos == -1 ) + return 0; + if ( visLineNum + 1 >= mNVisibleLines ) + return mLastChar - lineStartPos; + nextLineStart = mLineStarts[ visLineNum + 1 ]; + if ( nextLineStart == -1 ) + return mLastChar - lineStartPos; + if (wrap_uses_character(nextLineStart-1)) + return nextLineStart-1 - lineStartPos; + return nextLineStart - lineStartPos; +} + +/* +** When continuous wrap is on, and the user inserts or deletes characters, +** wrapping can happen before and beyond the changed position. This routine +** finds the extent of the changes, and counts the deleted and inserted lines +** over that range. It also attempts to minimize the size of the range to +** what has to be counted and re-displayed, so the results can be useful +** both for delimiting where the line starts need to be recalculated, and +** for deciding what part of the text to redisplay. +*/ +void Fl_Text_Display::find_wrap_range(const char *deletedText, int pos, + int nInserted, int nDeleted, int *modRangeStart, int *modRangeEnd, + int *linesInserted, int *linesDeleted) { + int length, retPos, retLines, retLineStart, retLineEnd; + Fl_Text_Buffer *deletedTextBuf, *buf = buffer(); + int nVisLines = mNVisibleLines; + int *lineStarts = mLineStarts; + int countFrom, countTo, lineStart, adjLineStart, i; + int visLineNum = 0, nLines = 0; + + /* + ** Determine where to begin searching: either the previous newline, or + ** if possible, limit to the start of the (original) previous displayed + ** line, using information from the existing line starts array + */ + if (pos >= mFirstChar && pos <= mLastChar) { + for (i=nVisLines-1; i>0; i--) + if (lineStarts[i] != -1 && pos >= lineStarts[i]) + break; + if (i > 0) { + countFrom = lineStarts[i-1]; + visLineNum = i-1; + } else + countFrom = buf->line_start(pos); + } else + countFrom = buf->line_start(pos); + + + /* + ** Move forward through the (new) text one line at a time, counting + ** displayed lines, and looking for either a real newline, or for the + ** line starts to re-sync with the original line starts array + */ + lineStart = countFrom; + *modRangeStart = countFrom; + while (true) { + + /* advance to the next line. If the line ended in a real newline + or the end of the buffer, that's far enough */ + wrapped_line_counter(buf, lineStart, buf->length(), 1, true, 0, + &retPos, &retLines, &retLineStart, &retLineEnd); + if (retPos >= buf->length()) { + countTo = buf->length(); + *modRangeEnd = countTo; + if (retPos != retLineEnd) + nLines++; + break; + } else + lineStart = retPos; + nLines++; + if (lineStart > pos + nInserted && + buf->character(lineStart-1) == '\n') { + countTo = lineStart; + *modRangeEnd = lineStart; + break; + } + + /* Don't try to resync in continuous wrap mode with non-fixed font + sizes; it would result in a chicken-and-egg dependency between + the calculations for the inserted and the deleted lines. + If we're in that mode, the number of deleted lines is calculated in + advance, without resynchronization, so we shouldn't resynchronize + for the inserted lines either. */ + if (mSuppressResync) + continue; + + /* check for synchronization with the original line starts array + before pos, if so, the modified range can begin later */ + if (lineStart <= pos) { + while (visLineNum<nVisLines && lineStarts[visLineNum] < lineStart) + visLineNum++; + if (visLineNum < nVisLines && lineStarts[visLineNum] == lineStart) { + countFrom = lineStart; + nLines = 0; + if (visLineNum+1 < nVisLines && lineStarts[visLineNum+1] != -1) + *modRangeStart = min(pos, lineStarts[visLineNum+1]-1); + else + *modRangeStart = countFrom; + } else + *modRangeStart = min(*modRangeStart, lineStart-1); + } + + /* check for synchronization with the original line starts array + after pos, if so, the modified range can end early */ + else if (lineStart > pos + nInserted) { + adjLineStart = lineStart - nInserted + nDeleted; + while (visLineNum<nVisLines && lineStarts[visLineNum]<adjLineStart) + visLineNum++; + if (visLineNum < nVisLines && lineStarts[visLineNum] != -1 && + lineStarts[visLineNum] == adjLineStart) { + countTo = line_end(lineStart, true); + *modRangeEnd = lineStart; + break; + } + } + } + *linesInserted = nLines; + + + /* Count deleted lines between countFrom and countTo as the text existed + before the modification (that is, as if the text between pos and + pos+nInserted were replaced by "deletedText"). This extra context is + necessary because wrapping can occur outside of the modified region + as a result of adding or deleting text in the region. This is done by + creating a textBuffer containing the deleted text and the necessary + additional context, and calling the wrappedLineCounter on it. + + NOTE: This must not be done in continuous wrap mode when the font + width is not fixed. In that case, the calculation would try + to access style information that is no longer available (deleted + text), or out of date (updated highlighting), possibly leading + to completely wrong calculations and/or even crashes eventually. + (This is not theoretical; it really happened.) + + In that case, the calculation of the number of deleted lines + has happened before the buffer was modified (only in that case, + because resynchronization of the line starts is impossible + in that case, which makes the whole calculation less efficient). + */ + if (mSuppressResync) { + *linesDeleted = mNLinesDeleted; + mSuppressResync = 0; + return; + } + + length = (pos-countFrom) + nDeleted +(countTo-(pos+nInserted)); + deletedTextBuf = new Fl_Text_Buffer(length); + deletedTextBuf->copy(buffer(), countFrom, pos, 0); + if (nDeleted != 0) + deletedTextBuf->insert(pos-countFrom, deletedText); + deletedTextBuf->copy(buffer(), + pos+nInserted, countTo, pos-countFrom+nDeleted); + /* Note that we need to take into account an offset for the style buffer: + the deletedTextBuf can be out of sync with the style buffer. */ + wrapped_line_counter(deletedTextBuf, 0, length, INT_MAX, true, + countFrom, &retPos, &retLines, &retLineStart, &retLineEnd, false); + delete deletedTextBuf; + *linesDeleted = retLines; + mSuppressResync = 0; +} + +/* +** This is a stripped-down version of the findWrapRange() function above, +** intended to be used to calculate the number of "deleted" lines during +** a buffer modification. It is called _before_ the modification takes place. +** +** This function should only be called in continuous wrap mode with a +** non-fixed font width. In that case, it is impossible to calculate +** the number of deleted lines, because the necessary style information +** is no longer available _after_ the modification. In other cases, we +** can still perform the calculation afterwards (possibly even more +** efficiently). +*/ +void Fl_Text_Display::measure_deleted_lines(int pos, int nDeleted) { + int retPos, retLines, retLineStart, retLineEnd; + Fl_Text_Buffer *buf = buffer(); + int nVisLines = mNVisibleLines; + int *lineStarts = mLineStarts; + int countFrom, lineStart; + int visLineNum = 0, nLines = 0, i; + /* + ** Determine where to begin searching: either the previous newline, or + ** if possible, limit to the start of the (original) previous displayed + ** line, using information from the existing line starts array + */ + if (pos >= mFirstChar && pos <= mLastChar) { + for (i=nVisLines-1; i>0; i--) + if (lineStarts[i] != -1 && pos >= lineStarts[i]) + break; + if (i > 0) { + countFrom = lineStarts[i-1]; + visLineNum = i-1; + } else + countFrom = buf->line_start(pos); + } else + countFrom = buf->line_start(pos); + + /* + ** Move forward through the (new) text one line at a time, counting + ** displayed lines, and looking for either a real newline, or for the + ** line starts to re-sync with the original line starts array + */ + lineStart = countFrom; + while (true) { + /* advance to the next line. If the line ended in a real newline + or the end of the buffer, that's far enough */ + wrapped_line_counter(buf, lineStart, buf->length(), 1, true, 0, + &retPos, &retLines, &retLineStart, &retLineEnd); + if (retPos >= buf->length()) { + if (retPos != retLineEnd) + nLines++; + break; + } else + lineStart = retPos; + nLines++; + if (lineStart > pos + nDeleted && + buf->character(lineStart-1) == '\n') { + break; + } + + /* Unlike in the findWrapRange() function above, we don't try to + resync with the line starts, because we don't know the length + of the inserted text yet, nor the updated style information. + + Because of that, we also shouldn't resync with the line starts + after the modification either, because we must perform the + calculations for the deleted and inserted lines in the same way. + + This can result in some unnecessary recalculation and redrawing + overhead, and therefore we should only use this two-phase mode + of calculation when it's really needed (continuous wrap + variable + font width). */ + } + mNLinesDeleted = nLines; + mSuppressResync = 1; +} + +/* +** Count forward from startPos to either maxPos or maxLines (whichever is +** reached first), and return all relevant positions and line count. +** The provided textBuffer may differ from the actual text buffer of the +** widget. In that case it must be a (partial) copy of the actual text buffer +** and the styleBufOffset argument must indicate the starting position of the +** copy, to take into account the correct style information. +** +** Returned values: +** +** retPos: Position where counting ended. When counting lines, the +** position returned is the start of the line "maxLines" +** lines beyond "startPos". +** retLines: Number of line breaks counted +** retLineStart: Start of the line where counting ended +** retLineEnd: End position of the last line traversed +*/ +void Fl_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos, + int maxPos, int maxLines, bool startPosIsLineStart, int styleBufOffset, + int *retPos, int *retLines, int *retLineStart, int *retLineEnd, + bool countLastLineMissingNewLine) { + int lineStart, newLineStart = 0, b, p, colNum, wrapMargin; + int maxWidth, i, foundBreak, width; + bool countPixels; + int nLines = 0, tabDist = buffer()->tab_distance(); + unsigned char c; + char nullSubsChar = buffer()->null_substitution_character(); + + /* If the font is fixed, or there's a wrap margin set, it's more efficient + to measure in columns, than to count pixels. Determine if we can count + in columns (countPixels == False) or must count pixels (countPixels == + True), and set the wrap target for either pixels or columns */ + if (mFixedFontWidth != -1 || mWrapMargin != 0) { + countPixels = false; + wrapMargin = mWrapMargin ? mWrapMargin : text_area.w / (mFixedFontWidth + 1); + maxWidth = INT_MAX; + } else { + countPixels = true; + wrapMargin = INT_MAX; + maxWidth = text_area.w; + } + + /* Find the start of the line if the start pos is not marked as a + line start. */ + if (startPosIsLineStart) + lineStart = startPos; + else + lineStart = line_start(startPos); + + /* + ** Loop until position exceeds maxPos or line count exceeds maxLines. + ** (actually, contines beyond maxPos to end of line containing maxPos, + ** in case later characters cause a word wrap back before maxPos) + */ + colNum = 0; + width = 0; + for (p=lineStart; p<buf->length(); p++) { + c = (unsigned char)buf->character(p); + + /* If the character was a newline, count the line and start over, + otherwise, add it to the width and column counts */ + if (c == '\n') { + if (p >= maxPos) { + *retPos = maxPos; + *retLines = nLines; + *retLineStart = lineStart; + *retLineEnd = maxPos; + return; + } + nLines++; + if (nLines >= maxLines) { + *retPos = p + 1; + *retLines = nLines; + *retLineStart = p + 1; + *retLineEnd = p; + return; + } + lineStart = p + 1; + colNum = 0; + width = 0; + } else { + colNum += Fl_Text_Buffer::character_width(c, colNum, tabDist, nullSubsChar); + if (countPixels) + width += measure_proportional_character(c, colNum, p+styleBufOffset); + } + + /* If character exceeded wrap margin, find the break point + and wrap there */ + if (colNum > wrapMargin || width > maxWidth) { + foundBreak = false; + for (b=p; b>=lineStart; b--) { + c = (unsigned char)buf->character(b); + if (c == '\t' || c == ' ') { + newLineStart = b + 1; + if (countPixels) { + colNum = 0; + width = 0; + for (i=b+1; i<p+1; i++) { + width += measure_proportional_character( + buf->character(i), colNum, + i+styleBufOffset); + colNum++; + } + } else + colNum = buf->count_displayed_characters(b+1, p+1); + foundBreak = true; + break; + } + } + if (!foundBreak) { /* no whitespace, just break at margin */ + newLineStart = max(p, lineStart+1); + colNum = Fl_Text_Buffer::character_width(c, colNum, tabDist, nullSubsChar); + if (countPixels) + width = measure_proportional_character(c, colNum, p+styleBufOffset); + } + if (p >= maxPos) { + *retPos = maxPos; + *retLines = maxPos < newLineStart ? nLines : nLines + 1; + *retLineStart = maxPos < newLineStart ? lineStart : + newLineStart; + *retLineEnd = maxPos; + return; + } + nLines++; + if (nLines >= maxLines) { + *retPos = foundBreak ? b + 1 : max(p, lineStart+1); + *retLines = nLines; + *retLineStart = lineStart; + *retLineEnd = foundBreak ? b : p; + return; + } + lineStart = newLineStart; + } + } + + /* reached end of buffer before reaching pos or line target */ + *retPos = buf->length(); + *retLines = nLines; + if (countLastLineMissingNewLine && colNum > 0) + ++(*retLines); + *retLineStart = lineStart; + *retLineEnd = buf->length(); +} + +/* +** Measure the width in pixels of a character "c" at a particular column +** "colNum" and buffer position "pos". This is for measuring characters in +** proportional or mixed-width highlighting fonts. +** +** A note about proportional and mixed-width fonts: the mixed width and +** proportional font code in nedit does not get much use in general editing, +** because nedit doesn't allow per-language-mode fonts, and editing programs +** in a proportional font is usually a bad idea, so very few users would +** choose a proportional font as a default. There are still probably mixed- +** width syntax highlighting cases where things don't redraw properly for +** insertion/deletion, though static display and wrapping and resizing +** should now be solid because they are now used for online help display. +*/ +int Fl_Text_Display::measure_proportional_character(char c, int colNum, int pos) { + int charLen, style; + char expChar[ FL_TEXT_MAX_EXP_CHAR_LEN ]; + Fl_Text_Buffer *styleBuf = mStyleBuffer; + + charLen = Fl_Text_Buffer::expand_character(c, colNum, expChar, + buffer()->tab_distance(), buffer()->null_substitution_character()); + if (styleBuf == 0) { + style = 0; + } else { + style = (unsigned char)styleBuf->character(pos); + if (style == mUnfinishedStyle && mUnfinishedHighlightCB) { + /* encountered "unfinished" style, trigger parsing */ + (mUnfinishedHighlightCB)(pos, mHighlightCBArg); + style = (unsigned char)styleBuf->character(pos); + } + } + return string_width(expChar, charLen, style); +} + +/* +** Finds both the end of the current line and the start of the next line. Why? +** In continuous wrap mode, if you need to know both, figuring out one from the +** other can be expensive or error prone. The problem comes when there's a +** trailing space or tab just before the end of the buffer. To translate an +** end of line value to or from the next lines start value, you need to know +** whether the trailing space or tab is being used as a line break or just a +** normal character, and to find that out would otherwise require counting all +** the way back to the beginning of the line. +*/ +void Fl_Text_Display::find_line_end(int startPos, bool startPosIsLineStart, + int *lineEnd, int *nextLineStart) { + int retLines, retLineStart; + + /* if we're not wrapping use more efficient BufEndOfLine */ + if (!mContinuousWrap) { + *lineEnd = buffer()->line_end(startPos); + *nextLineStart = min(buffer()->length(), *lineEnd + 1); + return; + } + + /* use the wrapped line counter routine to count forward one line */ + wrapped_line_counter(buffer(), startPos, buffer()->length(), + 1, startPosIsLineStart, 0, nextLineStart, &retLines, + &retLineStart, lineEnd); + return; +} + +/* +** Line breaks in continuous wrap mode usually happen at newlines or +** whitespace. This line-terminating character is not included in line +** width measurements and has a special status as a non-visible character. +** However, lines with no whitespace are wrapped without the benefit of a +** line terminating character, and this distinction causes endless trouble +** with all of the text display code which was originally written without +** continuous wrap mode and always expects to wrap at a newline character. +** +** Given the position of the end of the line, as returned by TextDEndOfLine +** or BufEndOfLine, this returns true if there is a line terminating +** character, and false if there's not. On the last character in the +** buffer, this function can't tell for certain whether a trailing space was +** used as a wrap point, and just guesses that it wasn't. So if an exact +** accounting is necessary, don't use this function. +*/ +int Fl_Text_Display::wrap_uses_character(int lineEndPos) { + char c; + + if (!mContinuousWrap || lineEndPos == buffer()->length()) + return 1; + + c = buffer()->character(lineEndPos); + return c == '\n' || ((c == '\t' || c == ' ') && + lineEndPos + 1 != buffer()->length()); +} + +/* +** Return true if the selection "sel" is rectangular, and touches a +** buffer position withing "rangeStart" to "rangeEnd" +*/ +int Fl_Text_Display::range_touches_selection(Fl_Text_Selection *sel, + int rangeStart, int rangeEnd) { + return sel->selected() && sel->rectangular() && sel->end() >= rangeStart && + sel->start() <= rangeEnd; +} + +/* +** Extend the range of a redraw request (from *start to *end) with additional +** redraw requests resulting from changes to the attached style buffer (which +** contains auxiliary information for coloring or styling text). +*/ +void Fl_Text_Display::extend_range_for_styles( int *startpos, int *endpos ) { + Fl_Text_Selection * sel = mStyleBuffer->primary_selection(); + int extended = 0; + + /* The peculiar protocol used here is that modifications to the style + buffer are marked by selecting them with the buffer's primary Fl_Text_Selection. + The style buffer is usually modified in response to a modify callback on + the text buffer BEFORE Fl_Text_Display.c's modify callback, so that it can keep + the style buffer in step with the text buffer. The style-update + callback can't just call for a redraw, because Fl_Text_Display hasn't processed + the original text changes yet. Anyhow, to minimize redrawing and to + avoid the complexity of scheduling redraws later, this simple protocol + tells the text display's buffer modify callback to extend it's redraw + range to show the text color/and font changes as well. */ + if ( sel->selected() ) { + if ( sel->start() < *startpos ) { + *startpos = sel->start(); + extended = 1; + } + if ( sel->end() > *endpos ) { + *endpos = sel->end(); + extended = 1; + } + } + + /* If the Fl_Text_Selection was extended due to a style change, and some of the + fonts don't match in spacing, extend redraw area to end of line to + redraw characters exposed by possible font size changes */ + if ( mFixedFontWidth == -1 && extended ) + *endpos = mBuffer->line_end( *endpos ) + 1; +} + +// The draw() method. It tries to minimize what is draw as much as possible. +void Fl_Text_Display::draw(void) { + // don't even try if there is no associated text buffer! + if (!buffer()) { draw_box(); return; } + + fl_push_clip(x(),y(),w(),h()); // prevent drawing outside widget area + + // draw the non-text, non-scrollbar areas. + if (damage() & FL_DAMAGE_ALL) { +// printf("drawing all (box = %d)\n", box()); + // draw the box() + int W = w(), H = h(); + draw_box(box(), x(), y(), W, H, color()); + + if (mHScrollBar->visible()) + W -= scrollbar_width(); + if (mVScrollBar->visible()) + H -= scrollbar_width(); + + // left margin + fl_rectf(text_area.x-LEFT_MARGIN, text_area.y-TOP_MARGIN, + LEFT_MARGIN, text_area.h+TOP_MARGIN+BOTTOM_MARGIN, + color()); + + // right margin + fl_rectf(text_area.x+text_area.w, text_area.y-TOP_MARGIN, + RIGHT_MARGIN, text_area.h+TOP_MARGIN+BOTTOM_MARGIN, + color()); + + // top margin + fl_rectf(text_area.x, text_area.y-TOP_MARGIN, + text_area.w, TOP_MARGIN, color()); + + // bottom margin + fl_rectf(text_area.x, text_area.y+text_area.h, + text_area.w, BOTTOM_MARGIN, color()); + + // draw that little box in the corner of the scrollbars + if (mVScrollBar->visible() && mHScrollBar->visible()) + fl_rectf(mVScrollBar->x(), mHScrollBar->y(), + mVScrollBar->w(), mHScrollBar->h(), + FL_GRAY); + + // blank the previous cursor protrusions + } + else if (damage() & (FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE)) { +// printf("blanking previous cursor extrusions at Y: %d\n", mCursorOldY); + // CET - FIXME - save old cursor position instead and just draw side needed? + fl_push_clip(text_area.x-LEFT_MARGIN, + text_area.y, + text_area.w+LEFT_MARGIN+RIGHT_MARGIN, + text_area.h); + fl_rectf(text_area.x-LEFT_MARGIN, mCursorOldY, + LEFT_MARGIN, mMaxsize, color()); + fl_rectf(text_area.x+text_area.w, mCursorOldY, + RIGHT_MARGIN, mMaxsize, color()); + fl_pop_clip(); + } + + // draw the scrollbars + if (damage() & (FL_DAMAGE_ALL | FL_DAMAGE_CHILD)) { + mVScrollBar->damage(FL_DAMAGE_ALL); + mHScrollBar->damage(FL_DAMAGE_ALL); + } + update_child(*mVScrollBar); + update_child(*mHScrollBar); + + // draw all of the text + if (damage() & (FL_DAMAGE_ALL | FL_DAMAGE_EXPOSE)) { + //printf("drawing all text\n"); + int X, Y, W, H; + if (fl_clip_box(text_area.x, text_area.y, text_area.w, text_area.h, + X, Y, W, H)) { + // Draw text using the intersected clipping box... + // (this sets the clipping internally) + draw_text(X, Y, W, H); + } else { + // Draw the whole area... + draw_text(text_area.x, text_area.y, text_area.w, text_area.h); + } + } + else if (damage() & FL_DAMAGE_SCROLL) { + // draw some lines of text + fl_push_clip(text_area.x, text_area.y, + text_area.w, text_area.h); + //printf("drawing text from %d to %d\n", damage_range1_start, damage_range1_end); + draw_range(damage_range1_start, damage_range1_end); + if (damage_range2_end != -1) { + //printf("drawing text from %d to %d\n", damage_range2_start, damage_range2_end); + draw_range(damage_range2_start, damage_range2_end); + } + damage_range1_start = damage_range1_end = -1; + damage_range2_start = damage_range2_end = -1; + fl_pop_clip(); + } + + // draw the text cursor + if (damage() & (FL_DAMAGE_ALL | FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE) + && !buffer()->primary_selection()->selected() && + mCursorOn && Fl::focus() == this ) { + fl_push_clip(text_area.x-LEFT_MARGIN, + text_area.y, + text_area.w+LEFT_MARGIN+RIGHT_MARGIN, + text_area.h); + + int X, Y; + if (position_to_xy(mCursorPos, &X, &Y)) draw_cursor(X, Y); +// else puts("position_to_xy() failed - unable to draw cursor!"); + //printf("drew cursor at pos: %d (%d,%d)\n", mCursorPos, X, Y); + mCursorOldY = Y; + fl_pop_clip(); + } + fl_pop_clip(); +} + +// this processes drag events due to mouse for Fl_Text_Display and +// also drags due to cursor movement with shift held down for +// Fl_Text_Editor +void fl_text_drag_me(int pos, Fl_Text_Display* d) { + if (d->dragType == Fl_Text_Display::DRAG_CHAR) { + if (pos >= d->dragPos) { + d->buffer()->select(d->dragPos, pos); + } else { + d->buffer()->select(pos, d->dragPos); + } + d->insert_position(pos); + } else if (d->dragType == Fl_Text_Display::DRAG_WORD) { + if (pos >= d->dragPos) { + d->insert_position(d->word_end(pos)); + d->buffer()->select(d->word_start(d->dragPos), d->word_end(pos)); + } else { + d->insert_position(d->word_start(pos)); + d->buffer()->select(d->word_start(pos), d->word_end(d->dragPos)); + } + } else if (d->dragType == Fl_Text_Display::DRAG_LINE) { + if (pos >= d->dragPos) { + d->insert_position(d->buffer()->line_end(pos)+1); + d->buffer()->select(d->buffer()->line_start(d->dragPos), + d->buffer()->line_end(pos)+1); + } else { + d->insert_position(d->buffer()->line_start(pos)); + d->buffer()->select(d->buffer()->line_start(pos), + d->buffer()->line_end(d->dragPos)+1); + } + } +} + +// This timer event scrolls the text view proportionally to +// how far the mouse pointer has left the text area. This +// allows for smooth scrolling without "wiggeling" the mouse. +void Fl_Text_Display::scroll_timer_cb(void *user_data) { + Fl_Text_Display *w = (Fl_Text_Display*)user_data; + int pos; + switch (scroll_direction) { + case 1: // mouse is to the right, scroll left + w->scroll(w->mTopLineNum, w->mHorizOffset + scroll_amount); + pos = w->xy_to_position(w->text_area.x + w->text_area.w, scroll_y, CURSOR_POS); + break; + case 2: // mouse is to the left, scroll right + w->scroll(w->mTopLineNum, w->mHorizOffset + scroll_amount); + pos = w->xy_to_position(w->text_area.x, scroll_y, CURSOR_POS); + break; + case 3: // mouse is above, scroll down + w->scroll(w->mTopLineNum + scroll_amount, w->mHorizOffset); + pos = w->xy_to_position(scroll_x, w->text_area.y, CURSOR_POS); + break; + case 4: // mouse is below, scroll up + w->scroll(w->mTopLineNum + scroll_amount, w->mHorizOffset); + pos = w->xy_to_position(scroll_x, w->text_area.y + w->text_area.h, CURSOR_POS); + break; + default: + return; + } + fl_text_drag_me(pos, w); + Fl::repeat_timeout(.1, scroll_timer_cb, user_data); +} + + +int Fl_Text_Display::handle(int event) { + if (!buffer()) return 0; + // This isn't very elegant! + if (!Fl::event_inside(text_area.x, text_area.y, text_area.w, text_area.h) && + !dragging && event != FL_LEAVE && event != FL_ENTER && + event != FL_MOVE && event != FL_FOCUS && event != FL_UNFOCUS && + event != FL_KEYBOARD && event != FL_KEYUP) { + return Fl_Group::handle(event); + } + + switch (event) { + case FL_ENTER: + case FL_MOVE: + if (active_r()) { + if (Fl::event_inside(text_area.x, text_area.y, text_area.w, text_area.h)) window()->cursor(FL_CURSOR_INSERT); + else window()->cursor(FL_CURSOR_DEFAULT); + return 1; + } else { + return 0; + } + + case FL_LEAVE: + case FL_HIDE: + if (active_r() && window()) { + window()->cursor(FL_CURSOR_DEFAULT); + + return 1; + } else { + return 0; + } + + case FL_PUSH: { + if (Fl::focus() != this) { + Fl::focus(this); + handle(FL_FOCUS); + } + if (Fl::event_state()&FL_SHIFT) return handle(FL_DRAG); + dragging = 1; + int pos = xy_to_position(Fl::event_x(), Fl::event_y(), CURSOR_POS); + dragType = Fl::event_clicks(); + dragPos = pos; + if (dragType == DRAG_CHAR) + buffer()->unselect(); + else if (dragType == DRAG_WORD) + buffer()->select(word_start(pos), word_end(pos)); + else if (dragType == DRAG_LINE) + buffer()->select(buffer()->line_start(pos), buffer()->line_end(pos)+1); + + if (buffer()->primary_selection()->selected()) + insert_position(buffer()->primary_selection()->end()); + else + insert_position(pos); + show_insert_position(); + return 1; + } + + case FL_DRAG: { + if (dragType < 0) return 1; + int X = Fl::event_x(), Y = Fl::event_y(), pos; + // if we leave the text_area, we start a timer event + // that will take care of scrolling and selecting + if (Y < text_area.y) { + scroll_x = X; + scroll_amount = (Y - text_area.y) / 5 - 1; + if (!scroll_direction) { + Fl::add_timeout(.01, scroll_timer_cb, this); + } + scroll_direction = 3; + } else if (Y >= text_area.y+text_area.h) { + scroll_x = X; + scroll_amount = (Y - text_area.y - text_area.h) / 5 + 1; + if (!scroll_direction) { + Fl::add_timeout(.01, scroll_timer_cb, this); + } + scroll_direction = 4; + } else if (X < text_area.x) { + scroll_y = Y; + scroll_amount = (X - text_area.x) / 2 - 1; + if (!scroll_direction) { + Fl::add_timeout(.01, scroll_timer_cb, this); + } + scroll_direction = 2; + } else if (X >= text_area.x+text_area.w) { + scroll_y = Y; + scroll_amount = (X - text_area.x - text_area.w) / 2 + 1; + if (!scroll_direction) { + Fl::add_timeout(.01, scroll_timer_cb, this); + } + scroll_direction = 1; + } else { + if (scroll_direction) { + Fl::remove_timeout(scroll_timer_cb, this); + scroll_direction = 0; + } + pos = xy_to_position(X, Y, CURSOR_POS); + fl_text_drag_me(pos, this); + } + return 1; + } + + case FL_RELEASE: { + dragging = 0; + if (scroll_direction) { + Fl::remove_timeout(scroll_timer_cb, this); + scroll_direction = 0; + } + + // convert from WORD or LINE selection to CHAR + if (insert_position() >= dragPos) + dragPos = buffer()->primary_selection()->start(); + else + dragPos = buffer()->primary_selection()->end(); + dragType = DRAG_CHAR; + + const char* copy = buffer()->selection_text(); + if (*copy) Fl::copy(copy, strlen(copy), 0); + free((void*)copy); + return 1; + } + + case FL_MOUSEWHEEL: + if (Fl::event_dy()) return mVScrollBar->handle(event); + else return mHScrollBar->handle(event); + + case FL_FOCUS: + case FL_UNFOCUS: + if (buffer()->selected()) redraw(); + + return 1; + + case FL_KEYBOARD: + // Copy? + if ((Fl::event_state()&(FL_CTRL|FL_COMMAND)) && Fl::event_key()=='c') { + if (!buffer()->selected()) return 1; + const char *copy = buffer()->selection_text(); + if (*copy) Fl::copy(copy, strlen(copy), 1); + free((void*)copy); + return 1; + } + + // Select all ? + if ((Fl::event_state()&(FL_CTRL|FL_COMMAND)) && Fl::event_key()=='a') { + buffer()->select(0,buffer()->length()); + return 1; + } + break; + } + + return 0; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Text_Editor.cxx b/Utilities/FLTK/src/Fl_Text_Editor.cxx new file mode 100644 index 0000000000..cea3bb1991 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Text_Editor.cxx @@ -0,0 +1,485 @@ +// +// "$Id$" +// +// Copyright 2001-2005 by Bill Spitzak and others. +// Original code Copyright Mark Edel. Permission to distribute under +// the LGPL for the FLTK library granted by Mark Edel. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <stdio.h> +#include <stdlib.h> +#include "flstring.h" +#include <ctype.h> +#include <FL/Fl.H> +#include <FL/Fl_Text_Editor.H> +#include <FL/fl_ask.H> + + +Fl_Text_Editor::Fl_Text_Editor(int X, int Y, int W, int H, const char* l) + : Fl_Text_Display(X, Y, W, H, l) { + mCursorOn = 1; + insert_mode_ = 1; + key_bindings = 0; + + // handle the default key bindings + add_default_key_bindings(&key_bindings); + + // handle everything else + default_key_function(kf_default); +} + +Fl_Text_Editor::Key_Binding* Fl_Text_Editor::global_key_bindings = 0; + +// These are the default key bindings every widget should start with +static struct { + int key; + int state; + Fl_Text_Editor::Key_Func func; +} default_key_bindings[] = { + { FL_Escape, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_ignore }, + { FL_Enter, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_enter }, + { FL_KP_Enter, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_enter }, + { FL_BackSpace, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_backspace }, + { FL_Insert, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_insert }, + { FL_Delete, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_delete }, + { FL_Home, 0, Fl_Text_Editor::kf_move }, + { FL_End, 0, Fl_Text_Editor::kf_move }, + { FL_Left, 0, Fl_Text_Editor::kf_move }, + { FL_Up, 0, Fl_Text_Editor::kf_move }, + { FL_Right, 0, Fl_Text_Editor::kf_move }, + { FL_Down, 0, Fl_Text_Editor::kf_move }, + { FL_Page_Up, 0, Fl_Text_Editor::kf_move }, + { FL_Page_Down, 0, Fl_Text_Editor::kf_move }, + { FL_Home, FL_SHIFT, Fl_Text_Editor::kf_shift_move }, + { FL_End, FL_SHIFT, Fl_Text_Editor::kf_shift_move }, + { FL_Left, FL_SHIFT, Fl_Text_Editor::kf_shift_move }, + { FL_Up, FL_SHIFT, Fl_Text_Editor::kf_shift_move }, + { FL_Right, FL_SHIFT, Fl_Text_Editor::kf_shift_move }, + { FL_Down, FL_SHIFT, Fl_Text_Editor::kf_shift_move }, + { FL_Page_Up, FL_SHIFT, Fl_Text_Editor::kf_shift_move }, + { FL_Page_Down, FL_SHIFT, Fl_Text_Editor::kf_shift_move }, + { FL_Home, FL_CTRL, Fl_Text_Editor::kf_ctrl_move }, + { FL_End, FL_CTRL, Fl_Text_Editor::kf_ctrl_move }, + { FL_Left, FL_CTRL, Fl_Text_Editor::kf_ctrl_move }, + { FL_Up, FL_CTRL, Fl_Text_Editor::kf_ctrl_move }, + { FL_Right, FL_CTRL, Fl_Text_Editor::kf_ctrl_move }, + { FL_Down, FL_CTRL, Fl_Text_Editor::kf_ctrl_move }, + { FL_Page_Up, FL_CTRL, Fl_Text_Editor::kf_ctrl_move }, + { FL_Page_Down, FL_CTRL, Fl_Text_Editor::kf_ctrl_move }, + { FL_Home, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, + { FL_End, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, + { FL_Left, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, + { FL_Up, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, + { FL_Right, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, + { FL_Down, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, + { FL_Page_Up, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, + { FL_Page_Down, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, +//{ FL_Clear, 0, Fl_Text_Editor::delete_to_eol }, + { 'z', FL_CTRL, Fl_Text_Editor::kf_undo }, + { '/', FL_CTRL, Fl_Text_Editor::kf_undo }, + { 'x', FL_CTRL, Fl_Text_Editor::kf_cut }, + { FL_Delete, FL_SHIFT, Fl_Text_Editor::kf_cut }, + { 'c', FL_CTRL, Fl_Text_Editor::kf_copy }, + { FL_Insert, FL_CTRL, Fl_Text_Editor::kf_copy }, + { 'v', FL_CTRL, Fl_Text_Editor::kf_paste }, + { FL_Insert, FL_SHIFT, Fl_Text_Editor::kf_paste }, + { 'a', FL_CTRL, Fl_Text_Editor::kf_select_all }, + +#ifdef __APPLE__ + // Define CMD+key accelerators... + { 'z', FL_COMMAND, Fl_Text_Editor::kf_undo }, + { 'x', FL_COMMAND, Fl_Text_Editor::kf_cut }, + { 'c', FL_COMMAND, Fl_Text_Editor::kf_copy }, + { 'v', FL_COMMAND, Fl_Text_Editor::kf_paste }, + { 'a', FL_COMMAND, Fl_Text_Editor::kf_select_all }, +#endif // __APPLE__ + + { 0, 0, 0 } +}; + +void Fl_Text_Editor::add_default_key_bindings(Key_Binding** list) { + for (int i = 0; default_key_bindings[i].key; i++) { + add_key_binding(default_key_bindings[i].key, + default_key_bindings[i].state, + default_key_bindings[i].func, + list); + } +} + +Fl_Text_Editor::Key_Func +Fl_Text_Editor::bound_key_function(int key, int state, Key_Binding* list) { + Key_Binding* cur; + for (cur = list; cur; cur = cur->next) + if (cur->key == key) + if (cur->state == FL_TEXT_EDITOR_ANY_STATE || cur->state == state) + break; + if (!cur) return 0; + return cur->function; +} + +void +Fl_Text_Editor::remove_all_key_bindings(Key_Binding** list) { + Key_Binding *cur, *next; + for (cur = *list; cur; cur = next) { + next = cur->next; + delete cur; + } + *list = 0; +} + +void +Fl_Text_Editor::remove_key_binding(int key, int state, Key_Binding** list) { + Key_Binding *cur, *last = 0; + for (cur = *list; cur; last = cur, cur = cur->next) + if (cur->key == key && cur->state == state) break; + if (!cur) return; + if (last) last->next = cur->next; + else *list = cur->next; + delete cur; +} + +void +Fl_Text_Editor::add_key_binding(int key, int state, Key_Func function, + Key_Binding** list) { + Key_Binding* kb = new Key_Binding; + kb->key = key; + kb->state = state; + kb->function = function; + kb->next = *list; + *list = kb; +} + +//////////////////////////////////////////////////////////////// + +#define NORMAL_INPUT_MOVE 0 + +static void kill_selection(Fl_Text_Editor* e) { + if (e->buffer()->selected()) { + e->insert_position(e->buffer()->primary_selection()->start()); + e->buffer()->remove_selection(); + } +} + +int Fl_Text_Editor::kf_default(int c, Fl_Text_Editor* e) { + if (!c || (!isprint(c) && c != '\t')) return 0; + char s[2] = "\0"; + s[0] = (char)c; + kill_selection(e); + if (e->insert_mode()) e->insert(s); + else e->overstrike(s); + e->show_insert_position(); + e->set_changed(); + if (e->when()&FL_WHEN_CHANGED) e->do_callback(); + return 1; +} + +int Fl_Text_Editor::kf_ignore(int, Fl_Text_Editor*) { + return 0; // don't handle +} + +int Fl_Text_Editor::kf_backspace(int, Fl_Text_Editor* e) { + if (!e->buffer()->selected() && e->move_left()) + e->buffer()->select(e->insert_position(), e->insert_position()+1); + kill_selection(e); + e->show_insert_position(); + e->set_changed(); + if (e->when()&FL_WHEN_CHANGED) e->do_callback(); + return 1; +} + +int Fl_Text_Editor::kf_enter(int, Fl_Text_Editor* e) { + kill_selection(e); + e->insert("\n"); + e->show_insert_position(); + e->set_changed(); + if (e->when()&FL_WHEN_CHANGED) e->do_callback(); + return 1; +} + +extern void fl_text_drag_me(int pos, Fl_Text_Display* d); + +int Fl_Text_Editor::kf_move(int c, Fl_Text_Editor* e) { + int i; + int selected = e->buffer()->selected(); + if (!selected) + e->dragPos = e->insert_position(); + e->buffer()->unselect(); + switch (c) { + case FL_Home: + e->insert_position(e->buffer()->line_start(e->insert_position())); + break; + case FL_End: + e->insert_position(e->buffer()->line_end(e->insert_position())); + break; + case FL_Left: + e->move_left(); + break; + case FL_Right: + e->move_right(); + break; + case FL_Up: + e->move_up(); + break; + case FL_Down: + e->move_down(); + break; + case FL_Page_Up: + for (i = 0; i < e->mNVisibleLines - 1; i++) e->move_up(); + break; + case FL_Page_Down: + for (i = 0; i < e->mNVisibleLines - 1; i++) e->move_down(); + break; + } + e->show_insert_position(); + return 1; +} + +int Fl_Text_Editor::kf_shift_move(int c, Fl_Text_Editor* e) { + kf_move(c, e); + fl_text_drag_me(e->insert_position(), e); + return 1; +} + +int Fl_Text_Editor::kf_ctrl_move(int c, Fl_Text_Editor* e) { + if (!e->buffer()->selected()) + e->dragPos = e->insert_position(); + if (c != FL_Up && c != FL_Down) { + e->buffer()->unselect(); + e->show_insert_position(); + } + switch (c) { + case FL_Home: + e->insert_position(0); + e->scroll(0, 0); + break; + case FL_End: + e->insert_position(e->buffer()->length()); + e->scroll(e->count_lines(0, e->buffer()->length(), 1), 0); + break; + case FL_Left: + e->previous_word(); + break; + case FL_Right: + e->next_word(); + break; + case FL_Up: + e->scroll(e->mTopLineNum-1, e->mHorizOffset); + break; + case FL_Down: + e->scroll(e->mTopLineNum+1, e->mHorizOffset); + break; + case FL_Page_Up: + e->insert_position(e->mLineStarts[0]); + break; + case FL_Page_Down: + e->insert_position(e->mLineStarts[e->mNVisibleLines-2]); + break; + } + return 1; +} + +int Fl_Text_Editor::kf_c_s_move(int c, Fl_Text_Editor* e) { + kf_ctrl_move(c, e); + fl_text_drag_me(e->insert_position(), e); + return 1; +} + +int Fl_Text_Editor::kf_home(int, Fl_Text_Editor* e) { + return kf_move(FL_Home, e); +} + +int Fl_Text_Editor::kf_end(int, Fl_Text_Editor* e) { + return kf_move(FL_End, e); +} + +int Fl_Text_Editor::kf_left(int, Fl_Text_Editor* e) { + return kf_move(FL_Left, e); +} + +int Fl_Text_Editor::kf_up(int, Fl_Text_Editor* e) { + return kf_move(FL_Up, e); +} + +int Fl_Text_Editor::kf_right(int, Fl_Text_Editor* e) { + return kf_move(FL_Right, e); +} + +int Fl_Text_Editor::kf_down(int, Fl_Text_Editor* e) { + return kf_move(FL_Down, e); +} + +int Fl_Text_Editor::kf_page_up(int, Fl_Text_Editor* e) { + return kf_move(FL_Page_Up, e); +} + +int Fl_Text_Editor::kf_page_down(int, Fl_Text_Editor* e) { + return kf_move(FL_Page_Down, e); +} + + +int Fl_Text_Editor::kf_insert(int, Fl_Text_Editor* e) { + e->insert_mode(e->insert_mode() ? 0 : 1); + return 1; +} + +int Fl_Text_Editor::kf_delete(int, Fl_Text_Editor* e) { + if (!e->buffer()->selected()) + e->buffer()->select(e->insert_position(), e->insert_position()+1); + kill_selection(e); + e->show_insert_position(); + e->set_changed(); + if (e->when()&FL_WHEN_CHANGED) e->do_callback(); + return 1; +} + +int Fl_Text_Editor::kf_copy(int, Fl_Text_Editor* e) { + if (!e->buffer()->selected()) return 1; + const char *copy = e->buffer()->selection_text(); + if (*copy) Fl::copy(copy, strlen(copy), 1); + free((void*)copy); + e->show_insert_position(); + return 1; +} + +int Fl_Text_Editor::kf_cut(int c, Fl_Text_Editor* e) { + kf_copy(c, e); + kill_selection(e); + e->set_changed(); + if (e->when()&FL_WHEN_CHANGED) e->do_callback(); + return 1; +} + +int Fl_Text_Editor::kf_paste(int, Fl_Text_Editor* e) { + kill_selection(e); + Fl::paste(*e, 1); + e->show_insert_position(); + e->set_changed(); + if (e->when()&FL_WHEN_CHANGED) e->do_callback(); + return 1; +} + +int Fl_Text_Editor::kf_select_all(int, Fl_Text_Editor* e) { + e->buffer()->select(0, e->buffer()->length()); + return 1; +} + +int Fl_Text_Editor::kf_undo(int , Fl_Text_Editor* e) { + e->buffer()->unselect(); + int crsr; + int ret = e->buffer()->undo(&crsr); + e->insert_position(crsr); + e->show_insert_position(); + e->set_changed(); + if (e->when()&FL_WHEN_CHANGED) e->do_callback(); + return ret; +} + +int Fl_Text_Editor::handle_key() { + // Call FLTK's rules to try to turn this into a printing character. + // This uses the right-hand ctrl key as a "compose prefix" and returns + // the changes that should be made to the text, as a number of + // bytes to delete and a string to insert: + int del; + if (Fl::compose(del)) { + if (del) buffer()->select(insert_position()-del, insert_position()); + kill_selection(this); + if (Fl::event_length()) { + if (insert_mode()) insert(Fl::event_text()); + else overstrike(Fl::event_text()); + } + show_insert_position(); + set_changed(); + if (when()&FL_WHEN_CHANGED) do_callback(); + return 1; + } + + int key = Fl::event_key(), state = Fl::event_state(), c = Fl::event_text()[0]; + state &= FL_SHIFT|FL_CTRL|FL_ALT|FL_META; // only care about these states + Key_Func f; + f = bound_key_function(key, state, global_key_bindings); + if (!f) f = bound_key_function(key, state, key_bindings); + if (f) return f(key, this); + if (default_key_function_ && !state) return default_key_function_(c, this); + return 0; +} + +void Fl_Text_Editor::maybe_do_callback() { +// printf("Fl_Text_Editor::maybe_do_callback()\n"); +// printf("changed()=%d, when()=%x\n", changed(), when()); + if (changed() || (when()&FL_WHEN_NOT_CHANGED)) do_callback(); +} + +int Fl_Text_Editor::handle(int event) { + if (!buffer()) return 0; + + if (event == FL_PUSH && Fl::event_button() == 2) { + dragType = -1; + Fl::paste(*this, 0); + Fl::focus(this); + set_changed(); + if (when()&FL_WHEN_CHANGED) do_callback(); + return 1; + } + + switch (event) { + case FL_FOCUS: + show_cursor(mCursorOn); // redraws the cursor + if (buffer()->selected()) redraw(); // Redraw selections... + Fl::focus(this); + return 1; + + case FL_UNFOCUS: + show_cursor(mCursorOn); // redraws the cursor + if (buffer()->selected()) redraw(); // Redraw selections... + case FL_HIDE: + if (when() & FL_WHEN_RELEASE) maybe_do_callback(); + return 1; + + case FL_KEYBOARD: + return handle_key(); + + case FL_PASTE: + if (!Fl::event_text()) { + fl_beep(); + return 1; + } + buffer()->remove_selection(); + if (insert_mode()) insert(Fl::event_text()); + else overstrike(Fl::event_text()); + show_insert_position(); + set_changed(); + if (when()&FL_WHEN_CHANGED) do_callback(); + return 1; + + case FL_ENTER: +// MRS: WIN32 only? Need to test! +// case FL_MOVE: + show_cursor(mCursorOn); + return 1; + } + + return Fl_Text_Display::handle(event); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Tile.cxx b/Utilities/FLTK/src/Fl_Tile.cxx new file mode 100644 index 0000000000..ead237cad6 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Tile.cxx @@ -0,0 +1,203 @@ +// +// "$Id$" +// +// Tile widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Group of 2 or 4 "tiles" that can be resized by dragging border +// The size of the first child determines where the resize border is. +// The resizebox is used to limit where the border can be dragged to. + +#include <FL/Fl.H> +#include <FL/Fl_Tile.H> +#include <FL/Fl_Window.H> +#include <stdlib.h> + +// Drag the edges that were initially at oldx,oldy to newx,newy: +// pass zero as oldx or oldy to disable drag in that direction: + +void Fl_Tile::position(int oix, int oiy, int newx, int newy) { + Fl_Widget*const* a = array(); + short* p = sizes(); + p += 8; // skip group & resizable's saved size + for (int i=children(); i--; p += 4) { + Fl_Widget* o = *a++; + if (o == resizable()) continue; + int X = o->x(); + int R = X+o->w(); + if (oix) { + int t = p[0]; + if (t == oix || t>oix && X<newx || t<oix && X>newx) X = newx; + t = p[1]; + if (t == oix || t>oix && R<newx || t<oix && R>newx) R = newx; + } + int Y = o->y(); + int B = Y+o->h(); + if (oiy) { + int t = p[2]; + if (t == oiy || t>oiy && Y<newy || t<oiy && Y>newy) Y = newy; + t = p[3]; + if (t == oiy || t>oiy && B<newy || t<oiy && B>newy) B = newy; + } + o->damage_resize(X,Y,R-X,B-Y); + } +} + +// move the lower-right corner (sort of): +void Fl_Tile::resize(int X,int Y,int W,int H) { + // remember how much to move the child widgets: + int dx = X-x(); + int dy = Y-y(); + int dw = W-w(); + int dh = H-h(); + short* p = sizes(); + // resize this (skip the Fl_Group resize): + Fl_Widget::resize(X,Y,W,H); + // find bottom-right of resiable: + int OR = p[5]; + int NR = X+W-(p[1]-OR); + int OB = p[7]; + int NB = Y+H-(p[3]-OB); + // move everything to be on correct side of new resizable: + Fl_Widget*const* a = array(); + p += 8; + for (int i=children(); i--;) { + Fl_Widget* o = *a++; + int xx = o->x()+dx; + int R = xx+o->w(); + if (*p++ >= OR) xx += dw; else if (xx > NR) xx = NR; + if (*p++ >= OR) R += dw; else if (R > NR) R = NR; + int yy = o->y()+dy; + int B = yy+o->h(); + if (*p++ >= OB) yy += dh; else if (yy > NB) yy = NB; + if (*p++ >= OB) B += dh; else if (B > NB) B = NB; + o->resize(xx,yy,R-xx,B-yy); o->redraw(); + } +} + +static void set_cursor(Fl_Tile*t, Fl_Cursor c) { + static Fl_Cursor cursor; + if (cursor == c || !t->window()) return; + cursor = c; +#ifdef __sgi + t->window()->cursor(c,FL_RED,FL_WHITE); +#else + t->window()->cursor(c); +#endif +} + +static Fl_Cursor cursors[4] = { + FL_CURSOR_DEFAULT, + FL_CURSOR_WE, + FL_CURSOR_NS, + FL_CURSOR_MOVE}; + +int Fl_Tile::handle(int event) { + static int sdrag; + static int sdx, sdy; + static int sx, sy; +#define DRAGH 1 +#define DRAGV 2 +#define GRABAREA 4 + + int mx = Fl::event_x(); + int my = Fl::event_y(); + + switch (event) { + + case FL_MOVE: + case FL_ENTER: + case FL_PUSH: { + int mindx = 100; + int mindy = 100; + int oldx = 0; + int oldy = 0; + Fl_Widget*const* a = array(); + short* q = sizes(); + short* p = q+8; + for (int i=children(); i--; p += 4) { + Fl_Widget* o = *a++; + if (o == resizable()) continue; + if (p[1]<q[1] && o->y()<=my+GRABAREA && o->y()+o->h()>=my-GRABAREA) { + int t = mx - (o->x()+o->w()); + if (abs(t) < mindx) { + sdx = t; + mindx = abs(t); + oldx = p[1]; + } + } + if (p[3]<q[3] && o->x()<=mx+GRABAREA && o->x()+o->w()>=mx-GRABAREA) { + int t = my - (o->y()+o->h()); + if (abs(t) < mindy) { + sdy = t; + mindy = abs(t); + oldy = p[3]; + } + } + } + sdrag = 0; sx = sy = 0; + if (mindx <= GRABAREA) {sdrag = DRAGH; sx = oldx;} + if (mindy <= GRABAREA) {sdrag |= DRAGV; sy = oldy;} + set_cursor(this, cursors[sdrag]); + if (sdrag) return 1; + return Fl_Group::handle(event); + } + + case FL_LEAVE: + set_cursor(this, FL_CURSOR_DEFAULT); + break; + + case FL_DRAG: + // This is necessary if CONSOLIDATE_MOTION in Fl_x.cxx is turned off: + // if (damage()) return 1; // don't fall behind + case FL_RELEASE: { + if (!sdrag) return 0; // should not happen + Fl_Widget* r = resizable(); if (!r) r = this; + int newx; + if (sdrag&DRAGH) { + newx = Fl::event_x()-sdx; + if (newx < r->x()) newx = r->x(); + else if (newx > r->x()+r->w()) newx = r->x()+r->w(); + } else + newx = sx; + int newy; + if (sdrag&DRAGV) { + newy = Fl::event_y()-sdy; + if (newy < r->y()) newy = r->y(); + else if (newy > r->y()+r->h()) newy = r->y()+r->h(); + } else + newy = sy; + position(sx,sy,newx,newy); + if (event == FL_DRAG) set_changed(); + do_callback(); + return 1;} + + } + + return Fl_Group::handle(event); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Tiled_Image.cxx b/Utilities/FLTK/src/Fl_Tiled_Image.cxx new file mode 100644 index 0000000000..c2058e3bc9 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Tiled_Image.cxx @@ -0,0 +1,139 @@ +// +// "$Id$" +// +// Tiled image code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Tiled_Image.H> +#include <FL/fl_draw.H> + + +// +// 'Fl_Tiled_Image::Fl_Tiled_Image()' - Constructor. +// +// Use a width and height of 0 to tile the whole window/widget. +// + +Fl_Tiled_Image::Fl_Tiled_Image(Fl_Image *i, // I - Image to tile + int W, // I - Width of tiled area + int H) : // I - Height of tiled area + Fl_Image(W,H,0) { + image_ = i; + alloc_image_ = 0; + + if (W == 0) w(Fl::w()); + if (H == 0) h(Fl::h()); +} + + +// +// 'Fl_Tiled_Image::~Fl_Tiled_Image()' - Destructor. +// + +Fl_Tiled_Image::~Fl_Tiled_Image() { + if (alloc_image_) delete image_; +} + + +// +// 'Fl_Tiled_Image::copy()' - Copy and resize a tiled image... +// + +Fl_Image * // O - New image +Fl_Tiled_Image::copy(int W, // I - New width + int H) { // I - New height + if (W == w() && H == h()) return this; + else return new Fl_Tiled_Image(image_, W, H); +} + + +// +// 'Fl_Tiled_Image::color_average()' - Blend colors... +// + +void +Fl_Tiled_Image::color_average(Fl_Color c, // I - Color to blend with + float i) { // I - Blend fraction + if (!alloc_image_) { + image_ = image_->copy(); + alloc_image_ = 1; + } + + image_->color_average(c, i); +} + + +// +// 'Fl_Tiled_Image::desaturate()' - Convert the image to grayscale... +// + +void +Fl_Tiled_Image::desaturate() { + if (!alloc_image_) { + image_ = image_->copy(); + alloc_image_ = 1; + } + + image_->desaturate(); +} + + +// +// 'Fl_Tiled_Image::draw()' - Draw a shared image... +// + +void +Fl_Tiled_Image::draw(int X, // I - Starting X position + int Y, // I - Starting Y position + int W, // I - Width of area to be filled + int H, // I - Height of area to be filled + int cx, // I - "Source" X position + int cy) { // I - "Source" Y position + if (!image_->w() || !image_->h()) return; + if (W == 0) W = Fl::w(); + if (H == 0) H = Fl::h(); + + fl_clip(X, Y, W, H); + + X += cx; + Y += cy; + + X = X - (X % image_->w()); + Y = Y - (Y % image_->h()); + + W += X; + H += Y; + + for (int yy = Y; yy < H; yy += image_->h()) + for (int xx = X; xx < W; xx += image_->w()) + image_->draw(xx, yy); + + fl_pop_clip(); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Tooltip.cxx b/Utilities/FLTK/src/Fl_Tooltip.cxx new file mode 100644 index 0000000000..2834b3cec1 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Tooltip.cxx @@ -0,0 +1,262 @@ +// +// "$Id$" +// +// Tooltip source file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl_Tooltip.H> +#include <FL/fl_draw.H> +#include <FL/Fl_Menu_Window.H> + +#include <stdio.h> + +float Fl_Tooltip::delay_ = 1.0f; +float Fl_Tooltip::hoverdelay_ = 0.2f; +int Fl_Tooltip::enabled_ = 1; +unsigned Fl_Tooltip::color_ = fl_color_cube(FL_NUM_RED - 1, + FL_NUM_GREEN - 1, + FL_NUM_BLUE - 2); +unsigned Fl_Tooltip::textcolor_ = FL_BLACK; +int Fl_Tooltip::font_ = FL_HELVETICA; +int Fl_Tooltip::size_ = FL_NORMAL_SIZE; + +#define MAX_WIDTH 400 + +static const char* tip; + +class Fl_TooltipBox : public Fl_Menu_Window { +public: + Fl_TooltipBox() : Fl_Menu_Window(0, 0) { + set_override(); + end(); + } + void draw(); + void layout(); + void show() { + if (tip) Fl_Menu_Window::show(); + } +}; + +Fl_Widget* Fl_Tooltip::widget_ = 0; +static Fl_TooltipBox *window = 0; +static int X,Y,W,H; + +void Fl_TooltipBox::layout() { + fl_font(Fl_Tooltip::font(), Fl_Tooltip::size()); + int ww, hh; + ww = MAX_WIDTH; + fl_measure(tip, ww, hh, FL_ALIGN_LEFT|FL_ALIGN_WRAP|FL_ALIGN_INSIDE); + ww += 6; hh += 6; + + // find position on the screen of the widget: + int ox = Fl::event_x_root(); + //int ox = X+W/2; + int oy = Y + H+2; + for (Fl_Widget* p = Fl_Tooltip::current(); p; p = p->window()) { + //ox += p->x(); + oy += p->y(); + } + int scr_x, scr_y, scr_w, scr_h; + Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h); + if (ox+ww > scr_x+scr_w) ox = scr_x+scr_w - ww; + if (ox < scr_x) ox = scr_x; + if (H > 30) { + oy = Fl::event_y_root()+13; + if (oy+hh > scr_y+scr_h) oy -= 23+hh; + } else { + if (oy+hh > scr_y+scr_h) oy -= (4+hh+H); + } + if (oy < scr_y) oy = scr_y; + + resize(ox, oy, ww, hh); +} + +void Fl_TooltipBox::draw() { + draw_box(FL_BORDER_BOX, 0, 0, w(), h(), Fl_Tooltip::color()); + fl_color(Fl_Tooltip::textcolor()); + fl_font(Fl_Tooltip::font(), Fl_Tooltip::size()); + fl_draw(tip, 3, 3, w()-6, h()-6, Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_WRAP)); +} + +static char recent_tooltip; + +static void recent_timeout(void*) { +#ifdef DEBUG + puts("recent_timeout();"); +#endif // DEBUG + + recent_tooltip = 0; +} + +static char recursion; + +static void tooltip_timeout(void*) { +#ifdef DEBUG + puts("tooltip_timeout();"); +#endif // DEBUG + + if (recursion) return; + recursion = 1; + if (!tip || !*tip) { + if (window) window->hide(); + } else { + //if (Fl::grab()) return; + if (!window) window = new Fl_TooltipBox; + // this cast bypasses the normal Fl_Window label() code: + ((Fl_Widget*)window)->label(tip); + window->layout(); + window->redraw(); +// printf("tooltip_timeout: Showing window %p with tooltip \"%s\"...\n", +// window, tip ? tip : "(null)"); + window->show(); + } + + Fl::remove_timeout(recent_timeout); + recent_tooltip = 1; + recursion = 0; +} + +// If this widget or one of it's parents has a tooltip, enter it. This +// will do nothing if this is the current widget (even if the mouse moved +// out so an exit() was done and then moved back in). If no tooltip can +// be found do Fl_Tooltip::exit_(). If you don't want this behavior (for instance +// if you want the tooltip to reappear when the mouse moves back in) +// call the fancier enter_area() below. +void +Fl_Tooltip::enter_(Fl_Widget* w) { +#ifdef DEBUG + printf("Fl_Tooltip::enter_(w=%p)\n", w); + printf(" window=%p\n", window); +#endif // DEBUG + + // find the enclosing group with a tooltip: + Fl_Widget* tw = w; + for (;;) { + if (!tw) {exit_(0); return;} + if (tw == widget_) return; + if (tw->tooltip()) break; + tw = tw->parent(); + } + enter_area(w, 0, 0, w->w(), w->h(), tw->tooltip()); +} + +// Acts as though enter(widget) was done but does not pop up a +// tooltip. This is useful to prevent a tooltip from reappearing when +// a modal overlapping window is deleted. FLTK does this automatically +// when you click the mouse button. +void Fl_Tooltip::current(Fl_Widget* w) { +#ifdef DEBUG + printf("Fl_Tooltip::current(w=%p)\n", w); +#endif // DEBUG + + exit_(0); + // find the enclosing group with a tooltip: + Fl_Widget* tw = w; + for (;;) { + if (!tw) return; + if (tw->tooltip()) break; + tw = tw->parent(); + } + // act just like Fl_Tooltip::enter_() except we can remember a zero: + widget_ = w; +} + +// Hide any visible tooltip. +void +Fl_Tooltip::exit_(Fl_Widget *w) { +#ifdef DEBUG + printf("Fl_Tooltip::exit_(w=%p)\n", w); + printf(" widget=%p, window=%p\n", widget_, window); +#endif // DEBUG + + if (!widget_ || w == window) return; + widget_ = 0; + Fl::remove_timeout(tooltip_timeout); + Fl::remove_timeout(recent_timeout); + if (window) window->hide(); + if (recent_tooltip) { + if (Fl::event_state() & FL_BUTTONS) recent_tooltip = 0; + else Fl::add_timeout(Fl_Tooltip::hoverdelay(), recent_timeout); + } +} + +// Get ready to display a tooltip. The widget and the xywh box inside +// it define an area the tooltip is for, this along with the current +// mouse position places the tooltip (the mouse is assummed to point +// inside or near the box). +void +Fl_Tooltip::enter_area(Fl_Widget* wid, int x,int y,int w,int h, const char* t) +{ +#ifdef DEBUG + printf("Fl_Tooltip::enter_area(wid=%p, x=%d, y=%d, w=%d, h=%d, t=\"%s\")\n", + wid, x, y, w, h, t ? t : "(null)"); + printf(" recursion=%d, window=%p\n", recursion, window); +#endif // DEBUG + + if (recursion) return; + if (!t || !*t || !enabled()) { + exit_(0); + return; + } + // do nothing if it is the same: + if (wid==widget_ /*&& x==X && y==Y && w==W && h==H*/ && t==tip) return; + Fl::remove_timeout(tooltip_timeout); + Fl::remove_timeout(recent_timeout); + // remember it: + widget_ = wid; X = x; Y = y; W = w; H = h; tip = t; + // popup the tooltip immediately if it was recently up: + if (recent_tooltip) { + if (window) window->hide(); + Fl::add_timeout(Fl_Tooltip::hoverdelay(), tooltip_timeout); + } else if (Fl_Tooltip::delay() < .1) { +#ifdef WIN32 + // possible fix for the Windows titlebar, it seems to want the + // window to be destroyed, moving it messes up the parenting: + if (window) window->hide(); +#endif // WIN32 + tooltip_timeout(0); + } else { + if (window) window->hide(); + Fl::add_timeout(Fl_Tooltip::delay(), tooltip_timeout); + } + +#ifdef DEBUG + printf(" tip=\"%s\", window->shown()=%d\n", tip ? tip : "(null)", + window ? window->shown() : 0); +#endif // DEBUG +} + +void Fl_Widget::tooltip(const char *tt) { + static char beenhere = 0; + if (!beenhere) { + beenhere = 1; + Fl_Tooltip::enter = Fl_Tooltip::enter_; + Fl_Tooltip::exit = Fl_Tooltip::exit_; + } + tooltip_ = tt; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Valuator.cxx b/Utilities/FLTK/src/Fl_Valuator.cxx new file mode 100644 index 0000000000..296951022f --- /dev/null +++ b/Utilities/FLTK/src/Fl_Valuator.cxx @@ -0,0 +1,149 @@ +// +// "$Id$" +// +// Valuator widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Base class for sliders and all other one-value "knobs" + +#include <FL/Fl.H> +#include <FL/Fl_Valuator.H> +#include <FL/math.h> +#include <stdio.h> +#include "flstring.h" + +Fl_Valuator::Fl_Valuator(int X, int Y, int W, int H, const char* L) + : Fl_Widget(X,Y,W,H,L) { + align(FL_ALIGN_BOTTOM); + when(FL_WHEN_CHANGED); + value_ = 0; + previous_value_ = 1; + min = 0; + max = 1; + A = 0.0; + B = 1; +} + +const double epsilon = 4.66e-10; + +void Fl_Valuator::step(double s) { + if (s < 0) s = -s; + A = rint(s); + B = 1; + while (fabs(s-A/B) > epsilon && B<=(0x7fffffff/10)) {B *= 10; A = rint(s*B);} +} + +void Fl_Valuator::precision(int p) { + A = 1.0; + for (B = 1; p--;) B *= 10; +} + +void Fl_Valuator::value_damage() {damage(FL_DAMAGE_EXPOSE);} // by default do partial-redraw + +int Fl_Valuator::value(double v) { + clear_changed(); + if (v == value_) return 0; + value_ = v; + value_damage(); + return 1; +} + +double Fl_Valuator::softclamp(double v) { + int which = (min<=max); + double p = previous_value_; + if ((v<min)==which && p!=min && (p<min)!=which) return min; + else if ((v>max)==which && p!=max && (p>max)!=which) return max; + else return v; +} + +// inline void Fl_Valuator::handle_push() {previous_value_ = value_;} + +void Fl_Valuator::handle_drag(double v) { + if (v != value_) { + value_ = v; + value_damage(); + set_changed(); + if (when() & FL_WHEN_CHANGED) do_callback(); + } +} + +void Fl_Valuator::handle_release() { + if (when()&FL_WHEN_RELEASE) { + // insure changed() is off even if no callback is done. It may have + // been turned on by the drag, and then the slider returned to it's + // initial position: + clear_changed(); + // now do the callback only if slider in new position or always is on: + if (value_ != previous_value_ || when() & FL_WHEN_NOT_CHANGED) { + do_callback(); + } + } +} + +double Fl_Valuator::round(double v) { + if (A) return rint(v*B/A)*A/B; + else return v; +} + +double Fl_Valuator::clamp(double v) { + if ((v<min)==(min<=max)) return min; + else if ((v>max)==(min<=max)) return max; + else return v; +} + +double Fl_Valuator::increment(double v, int n) { + if (!A) return v+n*(max-min)/100; + if (min > max) n = -n; + return (rint(v*B/A)+n)*A/B; +} + +int Fl_Valuator::format(char* buffer) { + double v = value(); + // MRS: THIS IS A HACK - RECOMMEND ADDING BUFFER SIZE ARGUMENT + if (!A || !B) return snprintf(buffer, 128, "%g", v); + + // Figure out how many digits are required to correctly format the + // value. + int i, c = 0; + char temp[32]; + // output a number with many digits after the decimal point. This + // seems to be needed to get high precission + snprintf(temp, sizeof(temp), "%.12f", A/B); + // strip all trailing 0's + for (i=strlen(temp)-1; i>0; i--) { + if (temp[i]!='0') break; + } + // count digits until we find the decimal point (or comma or whatever + // letter is set in the current locale) + for (; i>0; i--, c++) { + if (!isdigit(temp[i])) break; + } + + // MRS: THIS IS A HACK - RECOMMEND ADDING BUFFER SIZE ARGUMENT + return snprintf(buffer, 128, "%.*f", c, v); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Value_Input.cxx b/Utilities/FLTK/src/Fl_Value_Input.cxx new file mode 100644 index 0000000000..d3f5c6e610 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Value_Input.cxx @@ -0,0 +1,133 @@ +// +// "$Id$" +// +// Value input widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// FLTK widget for drag-adjusting a floating point value. +// Warning: this works by making a child Fl_Input object, even +// though this object is *not* an Fl_Group. May be a kludge? + +#include <FL/Fl.H> +#include <FL/Fl_Value_Input.H> +#include <FL/Fl_Group.H> +#include <stdlib.h> +#include <FL/math.h> + + +void Fl_Value_Input::input_cb(Fl_Widget*, void* v) { + Fl_Value_Input& t = *(Fl_Value_Input*)v; + double nv; + if ((t.step() - floor(t.step()))>0.0 || t.step() == 0.0) nv = strtod(t.input.value(), 0); + else nv = strtol(t.input.value(), 0, 0); + if (nv != t.value() || t.when() & FL_WHEN_NOT_CHANGED) { + t.set_value(nv); + t.set_changed(); + if (t.when()) t.do_callback(); + } +} + +void Fl_Value_Input::draw() { + if (damage()&~FL_DAMAGE_CHILD) input.clear_damage(FL_DAMAGE_ALL); + input.box(box()); + input.color(color(), selection_color()); + input.draw(); + input.clear_damage(); +} + +void Fl_Value_Input::resize(int X, int Y, int W, int H) { + Fl_Valuator::resize(X, Y, W, H); + input.resize(X, Y, W, H); +} + +void Fl_Value_Input::value_damage() { + char buf[128]; + format(buf); + input.value(buf); + input.mark(input.position()); // turn off selection highlight +} + +int Fl_Value_Input::handle(int event) { + double v; + int delta; + int mx = Fl::event_x_root(); + static int ix, drag; + input.when(when()); + switch (event) { + case FL_PUSH: + if (!step()) goto DEFAULT; + ix = mx; + drag = Fl::event_button(); + handle_push(); + return 1; + case FL_DRAG: + if (!step()) goto DEFAULT; + delta = mx-ix; + if (delta > 5) delta -= 5; + else if (delta < -5) delta += 5; + else delta = 0; + switch (drag) { + case 3: v = increment(previous_value(), delta*100); break; + case 2: v = increment(previous_value(), delta*10); break; + default:v = increment(previous_value(), delta); break; + } + v = round(v); + handle_drag(soft()?softclamp(v):clamp(v));; + return 1; + case FL_RELEASE: + if (!step()) goto DEFAULT; + if (value() != previous_value() || !Fl::event_is_click()) + handle_release(); + else { + input.handle(FL_PUSH); + input.handle(FL_RELEASE); + } + return 1; + case FL_FOCUS: + return input.take_focus(); + default: + DEFAULT: + input.type(((step() - floor(step()))>0.0 || step() == 0.0) ? FL_FLOAT_INPUT : FL_INT_INPUT); + return input.handle(event); + } +} + +Fl_Value_Input::Fl_Value_Input(int X, int Y, int W, int H, const char* l) +: Fl_Valuator(X, Y, W, H, l), input(X, Y, W, H, 0) { + soft_ = 0; + if (input.parent()) // defeat automatic-add + ((Fl_Group*)input.parent())->remove(input); + input.parent((Fl_Group *)this); // kludge! + input.callback(input_cb, this); + input.when(FL_WHEN_CHANGED); + box(input.box()); + color(input.color()); + selection_color(input.selection_color()); + align(FL_ALIGN_LEFT); + value_damage(); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Value_Output.cxx b/Utilities/FLTK/src/Fl_Value_Output.cxx new file mode 100644 index 0000000000..6574bf1065 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Value_Output.cxx @@ -0,0 +1,103 @@ +// +// "$Id$" +// +// Value output widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Fltk widget for drag-adjusting a floating point value. +// This is much lighter than Fl_Value_Input because it has no text editor +// If step() is zero then it can be used to display a floating-point value + +#include <FL/Fl.H> +#include <FL/Fl_Value_Output.H> +#include <FL/fl_draw.H> + +void Fl_Value_Output::draw() { + Fl_Boxtype b = box() ? box() : FL_DOWN_BOX; + int X = x()+Fl::box_dx(b); + int Y = y()+Fl::box_dy(b); + int W = w()-Fl::box_dw(b); + int H = h()-Fl::box_dh(b); + if (damage()&~FL_DAMAGE_CHILD) + draw_box(b, color()); + else { + fl_color(color()); + fl_rectf(X, Y, W, H); + } + char buf[128]; + format(buf); + fl_color(active_r() ? textcolor() : fl_inactive(textcolor())); + fl_font(textfont(), textsize()); + fl_draw(buf,X,Y,W,H,FL_ALIGN_LEFT); +} + +int Fl_Value_Output::handle(int event) { + if (!step()) return 0; + double v; + int delta; + int mx = Fl::event_x(); + static int ix, drag; + switch (event) { + case FL_PUSH: + ix = mx; + drag = Fl::event_button(); + handle_push(); + return 1; + case FL_DRAG: + delta = Fl::event_x()-ix; + if (delta > 5) delta -= 5; + else if (delta < -5) delta += 5; + else delta = 0; + switch (drag) { + case 3: v = increment(previous_value(),delta*100); break; + case 2: v = increment(previous_value(),delta*10); break; + default:v = increment(previous_value(),delta); break; + } + v = round(v); + handle_drag(soft()?softclamp(v):clamp(v));; + return 1; + case FL_RELEASE: + handle_release(); + return 1; + case FL_ENTER : + case FL_LEAVE : + return 1; + default: + return 0; + } +} + +Fl_Value_Output::Fl_Value_Output(int X, int Y, int W, int H,const char *l) +: Fl_Valuator(X,Y,W,H,l) { + box(FL_NO_BOX); + align(FL_ALIGN_LEFT); + textfont_ = FL_HELVETICA; + textsize_ = (uchar)FL_NORMAL_SIZE; + textcolor_ = FL_FOREGROUND_COLOR; + soft_ = 0; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Value_Slider.cxx b/Utilities/FLTK/src/Fl_Value_Slider.cxx new file mode 100644 index 0000000000..ac7ca2efbc --- /dev/null +++ b/Utilities/FLTK/src/Fl_Value_Slider.cxx @@ -0,0 +1,82 @@ +// +// "$Id$" +// +// Value slider widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Value_Slider.H> +#include <FL/fl_draw.H> +#include <math.h> + +Fl_Value_Slider::Fl_Value_Slider(int X, int Y, int W, int H, const char*l) +: Fl_Slider(X,Y,W,H,l) { + step(1,100); + textfont_ = FL_HELVETICA; + textsize_ = 10; + textcolor_ = FL_FOREGROUND_COLOR; +} + +void Fl_Value_Slider::draw() { + int sxx = x(), syy = y(), sww = w(), shh = h(); + int bxx = x(), byy = y(), bww = w(), bhh = h(); + if (horizontal()) { + bww = 35; sxx += 35; sww -= 35; + } else { + syy += 25; bhh = 25; shh -= 25; + } + if (damage()&FL_DAMAGE_ALL) draw_box(box(),sxx,syy,sww,shh,color()); + Fl_Slider::draw(sxx+Fl::box_dx(box()), + syy+Fl::box_dy(box()), + sww-Fl::box_dw(box()), + shh-Fl::box_dh(box())); + draw_box(box(),bxx,byy,bww,bhh,color()); + char buf[128]; + format(buf); + fl_font(textfont(), textsize()); + fl_color(active_r() ? textcolor() : fl_inactive(textcolor())); + fl_draw(buf, bxx, byy, bww, bhh, FL_ALIGN_CLIP); +} + +int Fl_Value_Slider::handle(int event) { + if (event == FL_PUSH && Fl::visible_focus()) { + Fl::focus(this); + redraw(); + } + int sxx = x(), syy = y(), sww = w(), shh = h(); + if (horizontal()) { + sxx += 35; sww -= 35; + } else { + syy += 25; shh -= 25; + } + return Fl_Slider::handle(event, + sxx+Fl::box_dx(box()), + syy+Fl::box_dy(box()), + sww-Fl::box_dw(box()), + shh-Fl::box_dh(box())); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Widget.cxx b/Utilities/FLTK/src/Fl_Widget.cxx new file mode 100644 index 0000000000..3c637767bd --- /dev/null +++ b/Utilities/FLTK/src/Fl_Widget.cxx @@ -0,0 +1,283 @@ +// +// "$Id$" +// +// Base widget class for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Widget.H> +#include <FL/Fl_Group.H> +#include <FL/Fl_Tooltip.H> +#include <FL/fl_draw.H> +#include <stdlib.h> +#include "flstring.h" + + +//////////////////////////////////////////////////////////////// +// for compatability with Forms, all widgets without callbacks are +// inserted into a "queue" when they are activated, and the forms +// compatability interaction functions (fl_do_events, etc) will +// read one widget at a time from this queue and return it: + +const int QUEUE_SIZE = 20; + +static Fl_Widget *obj_queue[QUEUE_SIZE]; +static int obj_head, obj_tail; + +void Fl_Widget::default_callback(Fl_Widget *o, void * /*v*/) { +#if 0 + // This is necessary for strict forms compatability but is confusing. + // Use the parent's callback if this widget does not have one. + for (Fl_Widget *p = o->parent(); p; p = p->parent()) + if (p->callback() != default_callback) { + p->do_callback(o,v); + return; + } +#endif + obj_queue[obj_head++] = o; + if (obj_head >= QUEUE_SIZE) obj_head = 0; + if (obj_head == obj_tail) { + obj_tail++; + if (obj_tail >= QUEUE_SIZE) obj_tail = 0; + } +} + +Fl_Widget *Fl::readqueue() { + if (obj_tail==obj_head) return 0; + Fl_Widget *o = obj_queue[obj_tail++]; + if (obj_tail >= QUEUE_SIZE) obj_tail = 0; + return o; +} + +//////////////////////////////////////////////////////////////// + +int Fl_Widget::handle(int) { + return 0; +} + +int FL_NORMAL_SIZE = 14; + +Fl_Widget::Fl_Widget(int X, int Y, int W, int H, const char* L) { + + x_ = X; y_ = Y; w_ = W; h_ = H; + + label_.value = L; + label_.image = 0; + label_.deimage = 0; + label_.type = FL_NORMAL_LABEL; + label_.font = FL_HELVETICA; + label_.size = (uchar)FL_NORMAL_SIZE; + label_.color = FL_FOREGROUND_COLOR; + tooltip_ = 0; + callback_ = default_callback; + user_data_ = 0; + type_ = 0; + flags_ = VISIBLE_FOCUS; + damage_ = 0; + box_ = FL_NO_BOX; + color_ = FL_GRAY; + color2_ = FL_GRAY; + align_ = FL_ALIGN_CENTER; + when_ = FL_WHEN_RELEASE; + + parent_ = 0; + if (Fl_Group::current()) Fl_Group::current()->add(this); +} + +void Fl_Widget::resize(int X, int Y, int W, int H) { + x_ = X; y_ = Y; w_ = W; h_ = H; +} + +// this is useful for parent widgets to call to resize children: +int Fl_Widget::damage_resize(int X, int Y, int W, int H) { + if (x() == X && y() == Y && w() == W && h() == H) return 0; + resize(X, Y, W, H); + redraw(); + return 1; +} + +int Fl_Widget::take_focus() { + if (!takesevents()) return 0; + if (!visible_focus()) return 0; + if (!handle(FL_FOCUS)) return 0; // see if it wants it + if (contains(Fl::focus())) return 1; // it called Fl::focus for us + Fl::focus(this); + return 1; +} + +extern void fl_throw_focus(Fl_Widget*); // in Fl_x.cxx + +// Destruction does not remove from any parent group! And groups when +// destroyed destroy all their children. This is convienent and fast. +// However, it is only legal to destroy a "root" such as an Fl_Window, +// and automatic destructors may be called. +Fl_Widget::~Fl_Widget() { + if (flags() & COPIED_LABEL) free((void *)(label_.value)); + parent_ = 0; // Don't throw focus to a parent widget. + fl_throw_focus(this); +} + +// draw a focus box for the widget... +void +Fl_Widget::draw_focus(Fl_Boxtype B, int X, int Y, int W, int H) const { + if (!Fl::visible_focus()) return; + switch (B) { + case FL_DOWN_BOX: + case FL_DOWN_FRAME: + case FL_THIN_DOWN_BOX: + case FL_THIN_DOWN_FRAME: + X ++; + Y ++; + default: + break; + } + + fl_color(fl_contrast(FL_BLACK, color())); + +#if defined(WIN32) || defined(__APPLE_QD__) + // Windows 95/98/ME do not implement the dotted line style, so draw + // every other pixel around the focus area... + // + // Also, QuickDraw (MacOS) does not support line styles specifically, + // and the hack we use in fl_line_style() will not draw horizontal lines + // on odd-numbered rows... + int i, xx, yy; + + X += Fl::box_dx(B); + Y += Fl::box_dy(B); + W -= Fl::box_dw(B) + 2; + H -= Fl::box_dh(B) + 2; + + for (xx = 0, i = 1; xx < W; xx ++, i ++) if (i & 1) fl_point(X + xx, Y); + for (yy = 0; yy < H; yy ++, i ++) if (i & 1) fl_point(X + W, Y + yy); + for (xx = W; xx > 0; xx --, i ++) if (i & 1) fl_point(X + xx, Y + H); + for (yy = H; yy > 0; yy --, i ++) if (i & 1) fl_point(X, Y + yy); +#else + fl_line_style(FL_DOT); + fl_rect(X + Fl::box_dx(B), Y + Fl::box_dy(B), + W - Fl::box_dw(B) - 1, H - Fl::box_dh(B) - 1); + fl_line_style(FL_SOLID); +#endif // WIN32 +} + + +void Fl_Widget::activate() { + if (!active()) { + clear_flag(INACTIVE); + if (active_r()) { + redraw(); + redraw_label(); + handle(FL_ACTIVATE); + if (inside(Fl::focus())) Fl::focus()->take_focus(); + } + } +} + +void Fl_Widget::deactivate() { + if (active_r()) { + set_flag(INACTIVE); + redraw(); + redraw_label(); + handle(FL_DEACTIVATE); + fl_throw_focus(this); + } else { + set_flag(INACTIVE); + } +} + +int Fl_Widget::active_r() const { + for (const Fl_Widget* o = this; o; o = o->parent()) + if (!o->active()) return 0; + return 1; +} + +void Fl_Widget::show() { + if (!visible()) { + clear_flag(INVISIBLE); + if (visible_r()) { + redraw(); + redraw_label(); + handle(FL_SHOW); + if (inside(Fl::focus())) Fl::focus()->take_focus(); + } + } +} + +void Fl_Widget::hide() { + if (visible_r()) { + set_flag(INVISIBLE); + for (Fl_Widget *p = parent(); p; p = p->parent()) + if (p->box() || !p->parent()) {p->redraw(); break;} + handle(FL_HIDE); + fl_throw_focus(this); + } else { + set_flag(INVISIBLE); + } +} + +int Fl_Widget::visible_r() const { + for (const Fl_Widget* o = this; o; o = o->parent()) + if (!o->visible()) return 0; + return 1; +} + +// return true if widget is inside (or equal to) this: +// Returns false for null widgets. +int Fl_Widget::contains(const Fl_Widget *o) const { + for (; o; o = o->parent_) if (o == this) return 1; + return 0; +} + + +void +Fl_Widget::label(const char *a) { + if (flags() & COPIED_LABEL) { + // reassigning a copied label remains the same copied label + if (label_.value == a) + return; + free((void *)(label_.value)); + clear_flag(COPIED_LABEL); + } + label_.value=a; + redraw_label(); +} + + +void +Fl_Widget::copy_label(const char *a) { + if (flags() & COPIED_LABEL) free((void *)(label_.value)); + if (a) { + set_flag(COPIED_LABEL); + label_.value=strdup(a); + } else { + clear_flag(COPIED_LABEL); + label_.value=(char *)0; + } + redraw_label(); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Window.cxx b/Utilities/FLTK/src/Fl_Window.cxx new file mode 100644 index 0000000000..d8aa8e91d0 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Window.cxx @@ -0,0 +1,176 @@ +// +// "$Id$" +// +// Window widget class for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// The Fl_Window is a window in the fltk library. +// This is the system-independent portions. The huge amount of +// crap you need to do to communicate with X is in Fl_x.cxx, the +// equivalent (but totally different) crap for MSWindows is in Fl_win32.cxx + +#include <FL/Fl.H> +#include <FL/Fl_Window.H> +#include <stdlib.h> +#include "flstring.h" + +#ifdef __APPLE_QUARTZ__ +#include <FL/fl_draw.h> +#endif + +void Fl_Window::_Fl_Window() { + type(FL_WINDOW); + box(FL_FLAT_BOX); + if (Fl::scheme_bg_) { + labeltype(FL_NORMAL_LABEL); + align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP); + image(Fl::scheme_bg_); + } else { + labeltype(FL_NO_LABEL); + } + i = 0; + xclass_ = 0; + icon_ = 0; + iconlabel_ = 0; + resizable(0); + size_range_set = 0; + minw = maxw = minh = maxh = 0; + callback((Fl_Callback*)default_callback); +} + +Fl_Window::Fl_Window(int X,int Y,int W, int H, const char *l) +: Fl_Group(X, Y, W, H, l) { + cursor_default = FL_CURSOR_DEFAULT; + cursor_fg = FL_BLACK; + cursor_bg = FL_WHITE; + + _Fl_Window(); + set_flag(FL_FORCE_POSITION); +} + +Fl_Window::Fl_Window(int W, int H, const char *l) +// fix common user error of a missing end() with current(0): + : Fl_Group((Fl_Group::current(0),0), 0, W, H, l) { + cursor_default = FL_CURSOR_DEFAULT; + cursor_fg = FL_BLACK; + cursor_bg = FL_WHITE; + + _Fl_Window(); + clear_visible(); +} + +Fl_Window *Fl_Widget::window() const { + for (Fl_Widget *o = parent(); o; o = o->parent()) + if (o->type() >= FL_WINDOW) return (Fl_Window*)o; + return 0; +} + +int Fl_Window::x_root() const { + Fl_Window *p = window(); + if (p) return p->x_root() + x(); + return x(); +} + +int Fl_Window::y_root() const { + Fl_Window *p = window(); + if (p) return p->y_root() + y(); + return y(); +} + +void Fl_Window::draw() { + const char *savelabel = label(); + uchar saveflags = flags(); + int savex = x(); x(0); + int savey = y(); y(0); + // Make sure we don't draw the window title in the window background... + Fl_Widget::label(0); + Fl_Group::draw(); +#ifdef __APPLE_QUARTZ__ + if (!parent() && resizable()) { + int dx = Fl::box_dw(box())-Fl::box_dx(box()); + int dy = Fl::box_dh(box())-Fl::box_dy(box()); + if (dx<=0) dx = 1; + if (dy<=0) dy = 1; + int x1 = w()-dx-1, x2 = x1, y1 = h()-dx-1, y2 = y1; + Fl_Color c[4] = { + color(), + fl_color_average(color(), FL_WHITE, 0.7f), + fl_color_average(color(), FL_BLACK, 0.6f), + fl_color_average(color(), FL_BLACK, 0.8f), + }; + int i; + for (i=dx; i<12; i++) { + fl_color(c[i&3]); + fl_line(x1--, y1, x2, y2--); + } + } +#endif + // Restore the label... + Fl_Widget::label(savelabel); + set_flag(saveflags); + y(savey); + x(savex); +} + +void Fl_Window::label(const char *name) {label(name, iconlabel());} + +void Fl_Window::copy_label(const char *a) { + if (flags() & COPIED_LABEL) { + free((void *)label()); + clear_flag(COPIED_LABEL); + } + if (a) a = strdup(a); + label(a, iconlabel()); + set_flag(COPIED_LABEL); +} + + +void Fl_Window::iconlabel(const char *iname) { + uchar saveflags = flags(); + label(label(), iname); + set_flag(saveflags); +} + +// the Fl::atclose pointer is provided for back compatability. You +// can now just change the callback for the window instead. + +void Fl::default_atclose(Fl_Window* window, void* v) { + window->hide(); + Fl_Widget::default_callback(window, v); // put on Fl::read_queue() +} + +void (*Fl::atclose)(Fl_Window*, void*) = default_atclose; + +void Fl_Window::default_callback(Fl_Window* win, void* v) { + Fl::atclose(win, v); +} + +Fl_Window *Fl_Window::current() { + return current_; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Window_fullscreen.cxx b/Utilities/FLTK/src/Fl_Window_fullscreen.cxx new file mode 100644 index 0000000000..8437368455 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Window_fullscreen.cxx @@ -0,0 +1,99 @@ +// +// "$Id$" +// +// Fullscreen window support for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Turning the border on/off by changing the motif_wm_hints property +// works on Irix 4DWM. Does not appear to work for any other window +// manager. Fullscreen still works on some window managers (fvwm is one) +// because they allow the border to be placed off-screen. + +// Unfortunatly most X window managers ignore changes to the border +// and refuse to position the border off-screen, so attempting to make +// the window full screen will lose the size of the border off the +// bottom and right. + +#include <FL/Fl.H> +#include <FL/x.H> + +#ifdef __APPLE__ +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#endif + +void Fl_Window::border(int b) { + if (b) { + if (border()) return; + clear_flag(FL_NOBORDER); + } else { + if (!border()) return; + set_flag(FL_NOBORDER); + } +#ifdef WIN32 + // not yet implemented, but it's possible + // for full fullscreen we have to make the window topmost as well +#elif defined(__APPLE_QD__) + // warning: not implemented in Quickdraw/Carbon +#elif defined(__APPLE_QUARTZ__) + // warning: not implemented in Quartz/Carbon +#else + if (shown()) Fl_X::i(this)->sendxjunk(); +#endif +} + +void Fl_Window::fullscreen() { +#ifndef WIN32 + //this would clobber the fake wm, since it relies on the border flags to + //determine its thickness + border(0); +#endif +#if defined(__APPLE__) || defined(WIN32) + int sx, sy, sw, sh; + Fl::screen_xywh(sx, sy, sw, sh, x()+w()/2, y()+h()/2); + // if we are on the main screen, we will leave the system menu bar unobstructed + if (Fl::x()>=sx && Fl::y()>=sy && Fl::x()+Fl::w()<=sx+sw && Fl::y()+Fl::h()<=sy+sh) { + sx = Fl::x(); sy = Fl::y(); + sw = Fl::w(); sh = Fl::h(); + } + if (x()==sx) x(sx+1); // make sure that we actually execute the resize + resize(sx, sy, sw, sh); +#else + if (!x()) x(1); // force it to call XResizeWindow() + resize(0,0,Fl::w(),Fl::h()); +#endif +} + +void Fl_Window::fullscreen_off(int X,int Y,int W,int H) { + // this order produces less blinking on IRIX: + resize(X,Y,W,H); +#ifndef WIN32 + border(1); +#endif +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Window_hotspot.cxx b/Utilities/FLTK/src/Fl_Window_hotspot.cxx new file mode 100644 index 0000000000..ea2c5fb642 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Window_hotspot.cxx @@ -0,0 +1,90 @@ +// +// "$Id$" +// +// Common hotspot routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Window.H> +#include <FL/x.H> +#include <stdio.h> + +void Fl_Window::hotspot(int X, int Y, int offscreen) { + int mx,my; + + // Update the screen position based on the mouse position. + Fl::get_mouse(mx,my); + X = mx-X; Y = my-Y; + + // If offscreen is 0 (the default), make sure that the window + // stays on the screen, if possible. + if (!offscreen) { +#if defined(WIN32) || defined(__APPLE__) + // These will be used by reference, so we must passed different variables + int bt,bx,by; + x(X);y(Y); + Fl_X::fake_X_wm(this, X, Y, bt, bx, by); + //force FL_FORCE_POSITION to be set in Fl_Window::resize() + if (X==x()) x(X-1); +#else + int scr_x, scr_y, scr_w, scr_h; + Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h); + + if (border()) { + // Ensure border is on screen; these values are generic enough + // to work with many window managers, and are based on KDE defaults. + const int top = 20; + const int left = 4; + const int right = 4; + const int bottom = 8; + if (X+w()+right > scr_w-scr_x) X = scr_w-scr_x-right-w(); + if (X-left < scr_x) X = left; + if (Y+h()+bottom > scr_h-scr_y) Y = scr_h-scr_y-bottom-h(); + if (Y-top < scr_y) Y = top; + } + // now insure contents are on-screen (more important than border): + if (X+w() > scr_w-scr_x) X = scr_w-scr_x-w(); + if (X < scr_x) X = scr_x; + if (Y+h() > scr_h-scr_y) Y = scr_h-scr_y-h(); + if (Y < scr_y) Y = scr_y; +#endif + } + + position(X,Y); +} + +void Fl_Window::hotspot(const Fl_Widget *o, int offscreen) { + int X = o->w()/2; + int Y = o->h()/2; + while (o != this && o) { + X += o->x(); Y += o->y(); + o = o->window(); + } + hotspot(X,Y,offscreen); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Window_iconize.cxx b/Utilities/FLTK/src/Fl_Window_iconize.cxx new file mode 100644 index 0000000000..c19e542dd2 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Window_iconize.cxx @@ -0,0 +1,49 @@ +// +// "$Id$" +// +// Window minification code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/x.H> + +extern char fl_show_iconic; // in Fl_x.cxx + +void Fl_Window::iconize() { + if (!shown()) { + fl_show_iconic = 1; + show(); + } else { +#ifdef WIN32 + ShowWindow(i->xid, SW_SHOWMINNOACTIVE); +#elif defined(__APPLE__) + CollapseWindow( i->xid, true ); +#else + XIconifyWindow(fl_display, i->xid, fl_screen); +#endif + } +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_Wizard.cxx b/Utilities/FLTK/src/Fl_Wizard.cxx new file mode 100644 index 0000000000..cf88f90583 --- /dev/null +++ b/Utilities/FLTK/src/Fl_Wizard.cxx @@ -0,0 +1,210 @@ +// +// "$Id$" +// +// Fl_Wizard widget routines. +// +// Copyright 1997-2005 by Easy Software Products. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +// Contents: +// +// Fl_Wizard::Fl_Wizard() - Create an Fl_Wizard widget. +// Fl_Wizard::draw() - Draw the wizard border and visible child. +// Fl_Wizard::next() - Show the next child. +// Fl_Wizard::prev() - Show the previous child. +// Fl_Wizard::value() - Return the current visible child. +// Fl_Wizard::value() - Set the visible child. +// + +// +// Include necessary header files... +// + +#include <FL/Fl_Wizard.H> +#include <FL/Fl_Window.H> +#include <FL/fl_draw.H> + + +// +// 'Fl_Wizard::Fl_Wizard()' - Create an Fl_Wizard widget. +// + +Fl_Wizard::Fl_Wizard(int xx, // I - Lefthand position + int yy, // I - Upper position + int ww, // I - Width + int hh, // I - Height + const char *l) : // I - Label + Fl_Group(xx, yy, ww, hh, l) +{ + box(FL_THIN_UP_BOX); + + value_ = (Fl_Widget *)0; +} + + +// +// 'Fl_Wizard::draw()' - Draw the wizard border and visible child. +// + +void +Fl_Wizard::draw() +{ + Fl_Widget *kid; // Visible child + + + kid = value(); + + if (damage() & FL_DAMAGE_ALL) + { + // Redraw everything... + if (kid) + { + draw_box(box(), x(), y(), w(), h(), kid->color()); + draw_child(*kid); + } + else + draw_box(box(), x(), y(), w(), h(), color()); + + } + else if (kid) + update_child(*kid); +} + + +// +// 'Fl_Wizard::next()' - Show the next child. +// + +void +Fl_Wizard::next() +{ + int num_kids; + Fl_Widget * const *kids; + + + if ((num_kids = children()) == 0) + return; + + for (kids = array(); num_kids > 0; kids ++, num_kids --) + if ((*kids)->visible()) + break; + + if (num_kids > 1) + value(kids[1]); +} + + +// +// 'Fl_Wizard::prev()' - Show the previous child. +// + + +void +Fl_Wizard::prev() +{ + int num_kids; + Fl_Widget * const *kids; + + + if ((num_kids = children()) == 0) + return; + + for (kids = array(); num_kids > 0; kids ++, num_kids --) + if ((*kids)->visible()) + break; + + if (num_kids > 0 && num_kids < children()) + value(kids[-1]); +} + + +// +// 'Fl_Wizard::value()' - Return the current visible child. +// + +Fl_Widget * +Fl_Wizard::value() +{ + int num_kids; + Fl_Widget * const *kids; + Fl_Widget *kid; + + + if ((num_kids = children()) == 0) + return ((Fl_Widget *)0); + + for (kids = array(), kid = (Fl_Widget *)0; num_kids > 0; kids ++, num_kids --) + { + if ((*kids)->visible()) + { + if (kid) + (*kids)->hide(); + else + kid = *kids; + } + } + + if (!kid) + { + kids --; + kid = *kids; + kid->show(); + } + + return (kid); +} + + +// +// 'Fl_Wizard::value()' - Set the visible child. +// + +void +Fl_Wizard::value(Fl_Widget *kid) +{ + int num_kids; + Fl_Widget * const *kids; + + + if ((num_kids = children()) == 0) + return; + + for (kids = array(); num_kids > 0; kids ++, num_kids --) + { + if (*kids == kid) + { + if (!kid->visible()) + kid->show(); + } + else + (*kids)->hide(); + } + + // This will restore the mouse pointer to the window's default cursor + // whenever the wizard pane is changed. Otherwise text widgets that + // show the next pane may leave the cursor set to the I beam, etc... + if (window()) window()->cursor(FL_CURSOR_DEFAULT); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_XBM_Image.cxx b/Utilities/FLTK/src/Fl_XBM_Image.cxx new file mode 100644 index 0000000000..49773bd82e --- /dev/null +++ b/Utilities/FLTK/src/Fl_XBM_Image.cxx @@ -0,0 +1,106 @@ +// +// "$Id$" +// +// Fl_XBM_Image routines. +// +// Copyright 1997-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +// Contents: +// +// Fl_XBM_Image::Fl_XBM_Image() - Load an XBM file. +// + +// +// Include necessary header files... +// + +#include <FL/Fl.H> +#include <FL/Fl_XBM_Image.H> +#include <stdio.h> +#include <stdlib.h> +#include "flstring.h" + +// +// 'Fl_XBM_Image::Fl_XBM_Image()' - Load an XBM file. +// + +Fl_XBM_Image::Fl_XBM_Image(const char *name) : Fl_Bitmap((const char *)0,0,0) { + FILE *f; + uchar *ptr; + + if ((f = fopen(name, "rb")) == NULL) return; + + char buffer[1024]; + char junk[1024]; + int wh[2]; // width and height + int i; + for (i = 0; i<2; i++) { + for (;;) { + if (!fgets(buffer,1024,f)) { + fclose(f); + return; + } + int r = sscanf(buffer,"#define %s %d",junk,&wh[i]); + if (r >= 2) break; + } + } + + // skip to data array: + for (;;) { + if (!fgets(buffer,1024,f)) { + fclose(f); + return; + } + if (!strncmp(buffer,"static ",7)) break; + } + + // Allocate memory... + w(wh[0]); + h(wh[1]); + + int n = ((wh[0]+7)/8)*wh[1]; + array = new uchar[n]; + + // read the data: + for (i = 0, ptr = (uchar *)array; i < n;) { + if (!fgets(buffer,1024,f)) { + fclose(f); + return; + } + const char *a = buffer; + while (*a && i<n) { + unsigned int t; + if (sscanf(a," 0x%x",&t)>0) { + *ptr++ = (uchar)t; + i ++; + } + while (*a && *a++ != ','); + } + } + + fclose(f); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_XColor.H b/Utilities/FLTK/src/Fl_XColor.H new file mode 100644 index 0000000000..c0f893cd97 --- /dev/null +++ b/Utilities/FLTK/src/Fl_XColor.H @@ -0,0 +1,46 @@ +// +// "$Id: Fl_XColor.H 4288 2005-04-16 00:13:17Z mike $" +// +// X-specific color definitions for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2001 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <config.h> +#include <FL/Enumerations.H> + +// one of these for each color in fltk's "colormap": +// if overlays are enabled, another one for the overlay +struct Fl_XColor { + unsigned char r,g,b; // actual color used by X + unsigned char mapped; // true when XAllocColor done + unsigned long pixel; // the X pixel to use +}; +extern Fl_XColor fl_xmap[/*overlay*/][256]; + +// mask & shifts to produce xcolor for truecolor visuals: +extern unsigned char fl_redmask, fl_greenmask, fl_bluemask; +extern int fl_redshift, fl_greenshift, fl_blueshift, fl_extrashift; + +// +// End of "$Id: Fl_XColor.H 4288 2005-04-16 00:13:17Z mike $". +// diff --git a/Utilities/FLTK/src/Fl_XPM_Image.cxx b/Utilities/FLTK/src/Fl_XPM_Image.cxx new file mode 100644 index 0000000000..31228a32d5 --- /dev/null +++ b/Utilities/FLTK/src/Fl_XPM_Image.cxx @@ -0,0 +1,131 @@ +// +// "$Id$" +// +// Fl_XPM_Image routines. +// +// Copyright 1997-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +// Contents: +// +// + +// +// Include necessary header files... +// + +#include <FL/Fl.H> +#include <FL/Fl_XPM_Image.H> +#include <stdio.h> +#include <stdlib.h> +#include "flstring.h" + + +// +// 'hexdigit()' - Convert a hex digit to an integer. +// + +static int hexdigit(int x) { // I - Hex digit... + if (isdigit(x)) return x-'0'; + if (isupper(x)) return x-'A'+10; + if (islower(x)) return x-'a'+10; + return 20; +} + +#define MAXSIZE 2048 +#define INITIALLINES 256 + +Fl_XPM_Image::Fl_XPM_Image(const char *name) : Fl_Pixmap((char *const*)0) { + FILE *f; + + if ((f = fopen(name, "rb")) == NULL) return; + + // read all the c-strings out of the file: + char** new_data = new char *[INITIALLINES]; + char** temp_data; + int malloc_size = INITIALLINES; + char buffer[MAXSIZE+20]; + int i = 0; + while (fgets(buffer,MAXSIZE+20,f)) { + if (buffer[0] != '\"') continue; + char *myp = buffer; + char *q = buffer+1; + while (*q != '\"' && myp < buffer+MAXSIZE) { + if (*q == '\\') switch (*++q) { + case '\r': + case '\n': + fgets(q,(buffer+MAXSIZE+20)-q,f); break; + case 0: + break; + case 'x': { + q++; + int n = 0; + for (int x = 0; x < 3; x++) { + int xd = hexdigit(*q); + if (xd > 15) break; + n = (n<<4)+xd; + q++; + } + *myp++ = n; + } break; + default: { + int c = *q++; + if (c>='0' && c<='7') { + c -= '0'; + for (int x=0; x<2; x++) { + int xd = hexdigit(*q); + if (xd>7) break; + c = (c<<3)+xd; + q++; + } + } + *myp++ = c; + } break; + } else { + *myp++ = *q++; + } + } + *myp++ = 0; + if (i >= malloc_size) { + temp_data = new char *[malloc_size + INITIALLINES]; + memcpy(temp_data, new_data, sizeof(char *) * malloc_size); + delete[] new_data; + new_data = temp_data; + malloc_size += INITIALLINES; + } + new_data[i] = new char[myp-buffer+1]; + memcpy(new_data[i], buffer,myp-buffer); + new_data[i][myp-buffer] = 0; + i++; + } + + fclose(f); + + data((const char **)new_data, i); + alloc_data = 1; + + measure(); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_abort.cxx b/Utilities/FLTK/src/Fl_abort.cxx new file mode 100644 index 0000000000..7a0648a004 --- /dev/null +++ b/Utilities/FLTK/src/Fl_abort.cxx @@ -0,0 +1,102 @@ +// +// "$Id$" +// +// Warning/error message code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// This method is in it's own source file so that stdlib and stdio +// do not need to be included in Fl.cxx: +// You can also override this by redefining all of these. + +#include <FL/Fl.H> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include "flstring.h" + +#ifdef WIN32 +# include <windows.h> + +static void warning(const char *, ...) { + // Show nothing for warnings under WIN32... +} + +static void error(const char *format, ...) { + va_list args; + char buf[1024]; + va_start(args, format); + vsnprintf(buf, 1024, format, args); + va_end(args); + MessageBox(0,buf,"Error",MB_ICONEXCLAMATION|MB_SYSTEMMODAL); +} + +static void fatal(const char *format, ...) { + va_list args; + char buf[1024]; + va_start(args, format); + vsnprintf(buf, 1024, format, args); + va_end(args); + MessageBox(0,buf,"Error",MB_ICONSTOP|MB_SYSTEMMODAL); + ::exit(1); +} + +#else + +static void warning(const char *format, ...) { + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fputc('\n', stderr); + fflush(stderr); +} + +static void error(const char *format, ...) { + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fputc('\n', stderr); + fflush(stderr); +} + +static void fatal(const char *format, ...) { + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fputc('\n', stderr); + fflush(stderr); + ::exit(1); +} + +#endif + +void (*Fl::warning)(const char* format, ...) = ::warning; +void (*Fl::error)(const char* format, ...) = ::error; +void (*Fl::fatal)(const char* format, ...) = ::fatal; + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_add_idle.cxx b/Utilities/FLTK/src/Fl_add_idle.cxx new file mode 100644 index 0000000000..1afc4e9877 --- /dev/null +++ b/Utilities/FLTK/src/Fl_add_idle.cxx @@ -0,0 +1,100 @@ +// +// "$Id$" +// +// Idle routine support for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Allows you to manage an arbitrary set of idle() callbacks. +// Replaces the older set_idle() call (which is used to implement this) + +#include <FL/Fl.H> + +struct idle_cb { + void (*cb)(void*); + void* data; + idle_cb *next; +}; + +// the callbacks are stored linked in a ring. last points at the one +// just called, first at the next to call. last->next == first. + +static idle_cb* first; +static idle_cb* last; +static idle_cb* freelist; + +static void call_idle() { + idle_cb* p = first; + last = p; first = p->next; + p->cb(p->data); // this may call add_idle() or remove_idle()! +} + +void Fl::add_idle(void (*cb)(void*), void* data) { + idle_cb* p = freelist; + if (p) freelist = p->next; + else p = new idle_cb; + p->cb = cb; + p->data = data; + if (first) { + last->next = p; + last = p; + p->next = first; + } else { + first = last = p; + p->next = p; + set_idle(call_idle); + } +} + +int Fl::has_idle(void (*cb)(void*), void* data) { + idle_cb* p = first; + if (!p) return 0; + for (;; p = p->next) { + if (p->cb == cb && p->data == data) return 1; + if (p==last) return 0; + } +} + +void Fl::remove_idle(void (*cb)(void*), void* data) { + idle_cb* p = first; + if (!p) return; + idle_cb* l = last; + for (;; p = p->next) { + if (p->cb == cb && p->data == data) break; + if (p==last) return; // not found + l = p; + } + if (l == p) { // only one + first = last = 0; + set_idle(0); + } else { + last = l; + first = l->next = p->next; + } + p->next = freelist; + freelist = p; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_arg.cxx b/Utilities/FLTK/src/Fl_arg.cxx new file mode 100644 index 0000000000..c6b2e60a7b --- /dev/null +++ b/Utilities/FLTK/src/Fl_arg.cxx @@ -0,0 +1,424 @@ +// +// "$Id$" +// +// Optional argument initialization code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// OPTIONAL initialization code for a program using fltk. +// You do not need to call this! Feel free to make up your own switches. + +#include <FL/Fl.H> +#include <FL/x.H> +#include <FL/Fl_Window.H> +#include <FL/Fl_Tooltip.H> +#include <FL/filename.H> +#include <FL/fl_draw.H> +#include <ctype.h> +#include "flstring.h" + +#if defined(WIN32) || defined(__APPLE__) +int XParseGeometry(const char*, int*, int*, unsigned int*, unsigned int*); +# define NoValue 0x0000 +# define XValue 0x0001 +# define YValue 0x0002 +# define WidthValue 0x0004 +# define HeightValue 0x0008 +# define AllValues 0x000F +# define XNegative 0x0010 +# define YNegative 0x0020 +#endif + +static int fl_match(const char *a, const char *s, int atleast = 1) { + const char *b = s; + while (*a && (*a == *b || tolower(*a) == *b)) {a++; b++;} + return !*a && b >= s+atleast; +} + +// flags set by previously parsed arguments: +extern char fl_show_iconic; // in Fl_x.cxx +static char arg_called; +static char return_i; +static const char *name; +static const char *geometry; +static const char *title; +// these are in Fl_get_system_colors and are set by the switches: +extern const char *fl_fg; +extern const char *fl_bg; +extern const char *fl_bg2; + +// consume a switch from argv. Returns number of words eaten, 0 on error: +int Fl::arg(int argc, char **argv, int &i) { + arg_called = 1; + const char *s = argv[i]; + + if (!s) {i++; return 1;} // something removed by calling program? + + // a word that does not start with '-', or a word after a '--', or + // the word '-' by itself all start the "non-switch arguments" to + // a program. Return 0 to indicate that we don't understand the + // word, but set a flag (return_i) so that args() will return at + // that point: + if (s[0] != '-' || s[1] == '-' || !s[1]) {return_i = 1; return 0;} + s++; // point after the dash + + if (fl_match(s, "iconic")) { + fl_show_iconic = 1; + i++; + return 1; + } else if (fl_match(s, "kbd")) { + Fl::visible_focus(1); + i++; + return 1; + } else if (fl_match(s, "nokbd", 3)) { + Fl::visible_focus(0); + i++; + return 1; + } else if (fl_match(s, "dnd", 2)) { + Fl::dnd_text_ops(1); + i++; + return 1; + } else if (fl_match(s, "nodnd", 3)) { + Fl::dnd_text_ops(0); + i++; + return 1; + } else if (fl_match(s, "tooltips", 2)) { + Fl_Tooltip::enable(); + i++; + return 1; + } else if (fl_match(s, "notooltips", 3)) { + Fl_Tooltip::disable(); + i++; + return 1; + } +#ifdef __APPLE__ + // The Finder application in MacOS X passes the "-psn_N_NNNNN" option + // to all apps... + else if (strncmp(s, "psn_", 4) == 0) { + i++; + return 1; + } +#endif // __APPLE__ + + const char *v = argv[i+1]; + if (i >= argc-1 || !v) + return 0; // all the rest need an argument, so if missing it is an error + + if (fl_match(s, "geometry")) { + + int flags, gx, gy; unsigned int gw, gh; + flags = XParseGeometry(v, &gx, &gy, &gw, &gh); + if (!flags) return 0; + geometry = v; + +#if !defined(WIN32) && !defined(__APPLE__) + } else if (fl_match(s, "display", 2)) { + Fl::display(v); +#endif + + } else if (fl_match(s, "title", 2)) { + title = v; + + } else if (fl_match(s, "name", 2)) { + name = v; + + } else if (fl_match(s, "bg2", 3) || fl_match(s, "background2", 11)) { + fl_bg2 = v; + + } else if (fl_match(s, "bg", 2) || fl_match(s, "background", 10)) { + fl_bg = v; + + } else if (fl_match(s, "fg", 2) || fl_match(s, "foreground", 10)) { + fl_fg = v; + + } else if (fl_match(s, "scheme", 1)) { + Fl::scheme(v); + + } else return 0; // unrecognized + + i += 2; + return 2; +} + +// consume all switches from argv. Returns number of words eaten. +// Returns zero on error. 'i' will either point at first word that +// does not start with '-', at the error word, or after a '--', or at +// argc. If your program does not take any word arguments you can +// report an error if i < argc. + +int Fl::args(int argc, char** argv, int& i, int (*cb)(int,char**,int&)) { + arg_called = 1; + i = 1; // skip argv[0] + while (i < argc) { + if (cb && cb(argc,argv,i)) continue; + if (!arg(argc,argv,i)) return return_i ? i : 0; + } + return i; +} + +// show a main window, use any parsed arguments +void Fl_Window::show(int argc, char **argv) { + if (argc && !arg_called) Fl::args(argc,argv); + + Fl::get_system_colors(); + +#if !defined(WIN32) && !defined(__APPLE__) + // Get defaults for drag-n-drop and focus... + const char *key = 0, *val; + + if (Fl::first_window()) key = Fl::first_window()->xclass(); + if (!key) key = "fltk"; + + val = XGetDefault(fl_display, key, "dndTextOps"); + if (val) Fl::dnd_text_ops(strcasecmp(val, "true") == 0 || + strcasecmp(val, "on") == 0 || + strcasecmp(val, "yes") == 0); + + val = XGetDefault(fl_display, key, "tooltips"); + if (val) Fl_Tooltip::enable(strcasecmp(val, "true") == 0 || + strcasecmp(val, "on") == 0 || + strcasecmp(val, "yes") == 0); + + val = XGetDefault(fl_display, key, "visibleFocus"); + if (val) Fl::visible_focus(strcasecmp(val, "true") == 0 || + strcasecmp(val, "on") == 0 || + strcasecmp(val, "yes") == 0); +#endif // !WIN32 && !__APPLE__ + + // set colors first, so background_pixel is correct: + static char beenhere; + if (!beenhere) { + if (geometry) { + int fl = 0, gx = x(), gy = y(); unsigned int gw = w(), gh = h(); + fl = XParseGeometry(geometry, &gx, &gy, &gw, &gh); + if (fl & XNegative) gx = Fl::w()-w()+gx; + if (fl & YNegative) gy = Fl::h()-h()+gy; + // int mw,mh; minsize(mw,mh); + // if (mw > gw) gw = mw; + // if (mh > gh) gh = mh; + Fl_Widget *r = resizable(); + if (!r) resizable(this); + // for WIN32 we assumme window is not mapped yet: + if (fl & (XValue | YValue)) + x(-1), resize(gx,gy,gw,gh); + else + size(gw,gh); + resizable(r); + } + } + + // set the class, which is used by X version of get_system_colors: + if (name) {xclass(name); name = 0;} + else if (!xclass()) xclass(fl_filename_name(argv[0])); + + if (title) {label(title); title = 0;} + else if (!label()) label(xclass()); + + if (!beenhere) { + beenhere = 1; + Fl::scheme(Fl::scheme()); // opens display! May call Fl::fatal() + } + + // Show the window AFTER we have set the colors and scheme. + show(); + +#if !defined(WIN32) && !defined(__APPLE__) + // set the command string, used by state-saving window managers: + int j; + int n=0; for (j=0; j<argc; j++) n += strlen(argv[j])+1; + char *buffer = new char[n]; + char *p = buffer; + for (j=0; j<argc; j++) for (const char *q = argv[j]; (*p++ = *q++);); + XChangeProperty(fl_display, fl_xid(this), XA_WM_COMMAND, XA_STRING, 8, 0, + (unsigned char *)buffer, p-buffer-1); + delete[] buffer; +#endif // !WIN32 && !__APPLE__ +} + +// Calls useful for simple demo programs, with automatic help message: + +static const char * const helpmsg = +"options are:\n" +" -bg2 color\n" +" -bg color\n" +" -di[splay] host:n.n\n" +" -dn[d]\n" +" -fg color\n" +" -g[eometry] WxH+X+Y\n" +" -i[conic]\n" +" -k[bd]\n" +" -na[me] classname\n" +" -nod[nd]\n" +" -nok[bd]\n" +" -not[ooltips]\n" +" -s[cheme] scheme\n" +" -ti[tle] windowtitle\n" +" -to[oltips]"; + +const char * const Fl::help = helpmsg+13; + +void Fl::args(int argc, char **argv) { + int i; if (Fl::args(argc,argv,i) < argc) Fl::error(helpmsg); +} + +#if defined(WIN32) || defined(__APPLE__) + +/* the following function was stolen from the X sources as indicated. */ + +/* Copyright Massachusetts Institute of Technology 1985, 1986, 1987 */ +/* $XConsortium: XParseGeom.c,v 11.18 91/02/21 17:23:05 rws Exp $ */ + +/* +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the name of M.I.T. not be used in advertising or +publicity pertaining to distribution of the software without specific, +written prior permission. M.I.T. makes no representations about the +suitability of this software for any purpose. It is provided "as is" +without express or implied warranty. +*/ + +/* + * XParseGeometry parses strings of the form + * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where + * width, height, xoffset, and yoffset are unsigned integers. + * Example: "=80x24+300-49" + * The equal sign is optional. + * It returns a bitmask that indicates which of the four values + * were actually found in the string. For each value found, + * the corresponding argument is updated; for each value + * not found, the corresponding argument is left unchanged. + */ + +static int ReadInteger(char* string, char** NextString) +{ + register int Result = 0; + int Sign = 1; + + if (*string == '+') + string++; + else if (*string == '-') { + string++; + Sign = -1; + } + for (; (*string >= '0') && (*string <= '9'); string++) { + Result = (Result * 10) + (*string - '0'); + } + *NextString = string; + if (Sign >= 0) + return (Result); + else + return (-Result); +} + +int XParseGeometry(const char* string, int* x, int* y, + unsigned int* width, unsigned int* height) +{ + int mask = NoValue; + register char *strind; + unsigned int tempWidth = 0, tempHeight = 0; + int tempX = 0, tempY = 0; + char *nextCharacter; + + if ( (string == NULL) || (*string == '\0')) return(mask); + if (*string == '=') + string++; /* ignore possible '=' at beg of geometry spec */ + + strind = (char *)string; + if (*strind != '+' && *strind != '-' && *strind != 'x') { + tempWidth = ReadInteger(strind, &nextCharacter); + if (strind == nextCharacter) + return (0); + strind = nextCharacter; + mask |= WidthValue; + } + + if (*strind == 'x' || *strind == 'X') { + strind++; + tempHeight = ReadInteger(strind, &nextCharacter); + if (strind == nextCharacter) + return (0); + strind = nextCharacter; + mask |= HeightValue; + } + + if ((*strind == '+') || (*strind == '-')) { + if (*strind == '-') { + strind++; + tempX = -ReadInteger(strind, &nextCharacter); + if (strind == nextCharacter) + return (0); + strind = nextCharacter; + mask |= XNegative; + + } else { + strind++; + tempX = ReadInteger(strind, &nextCharacter); + if (strind == nextCharacter) + return(0); + strind = nextCharacter; + } + mask |= XValue; + if ((*strind == '+') || (*strind == '-')) { + if (*strind == '-') { + strind++; + tempY = -ReadInteger(strind, &nextCharacter); + if (strind == nextCharacter) + return(0); + strind = nextCharacter; + mask |= YNegative; + + } else { + strind++; + tempY = ReadInteger(strind, &nextCharacter); + if (strind == nextCharacter) + return(0); + strind = nextCharacter; + } + mask |= YValue; + } + } + + /* If strind isn't at the end of the string the it's an invalid + geometry specification. */ + + if (*strind != '\0') return (0); + + if (mask & XValue) + *x = tempX; + if (mask & YValue) + *y = tempY; + if (mask & WidthValue) + *width = tempWidth; + if (mask & HeightValue) + *height = tempHeight; + return (mask); +} + +#endif // ifdef WIN32 + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_compose.cxx b/Utilities/FLTK/src/Fl_compose.cxx new file mode 100644 index 0000000000..f05e6bc1f0 --- /dev/null +++ b/Utilities/FLTK/src/Fl_compose.cxx @@ -0,0 +1,167 @@ +// +// "$Id$" +// +// Character compose processing for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> + +// +// MRS: Uncomment the following define to get the original (pre-1.1.2) +// dead key support code. The original code apparently did not +// work on Belgian keyboards. +// + +//#define OLD_DEAD_KEY_CODE + + +static const char* const compose_pairs = +" ! % # $ y=| & : c a <<~ - r _ * +-2 3 ' u p . , 1 o >>141234? " +"`A'A^A~A:A*AAE,C`E'E^E:E`I'I^I:I-D~N`O'O^O~O:Ox O/`U'U^U:U'YTHss" +"`a'a^a~a:a*aae,c`e'e^e:e`i'i^i:i-d~n`o'o^o~o:o-:o/`u'u^u:u'yth:y"; + +#if !defined(WIN32) && defined(OLD_DEAD_KEY_CODE) // X only +// X dead-key lookup table. This turns a dead-key keysym into the +// first of two characters for one of the compose sequences. These +// keysyms start at 0xFE50. +// Win32 handles the dead keys before FLTK can see them. This is +// unfortunate, because you don't get the preview effect. +static char dead_keys[] = { + '`', // XK_dead_grave + '\'', // XK_dead_acute + '^', // XK_dead_circumflex + '~', // XK_dead_tilde + '_', // XK_dead_macron + 0, // XK_dead_breve + '.', // XK_dead_abovedot + ':', // XK_dead_diaeresis + '*', // XK_dead_abovering + 0, // XK_dead_doubleacute + 'v', // XK_dead_caron + ',' // XK_dead_cedilla +// 0, // XK_dead_ogonek +// 0, // XK_dead_iota +// 0, // XK_dead_voiced_sound +// 0, // XK_dead_semivoiced_sound +// 0 // XK_dead_belowdot +}; +#endif // !WIN32 && OLD_DEAD_KEY_CODE + +int Fl::compose_state = 0; + +int Fl::compose(int& del) { + + del = 0; + unsigned char ascii = (unsigned)e_text[0]; + + // Alt+letters are reserved for shortcuts. But alt+foreign letters + // has to be allowed, because some key layouts require alt to be held + // down in order to type them... + // + // OSX users sometimes need to hold down ALT for keys, so we only check + // for META on OSX... +#ifdef __APPLE__ + if ((e_state & FL_META) && !(ascii & 128)) return 0; +#else + if ((e_state & (FL_ALT|FL_META)) && !(ascii & 128)) return 0; +#endif // __APPLE__ + + if (compose_state == 1) { // after the compose key + + if (ascii == ' ') { // space turns into nbsp + e_text[0] = char(0xA0); + compose_state = 0; + return 1; + } else if (ascii < ' ' || ascii == 127) { + compose_state = 0; + return 0; + } + + // see if it is either character of any pair: + for (const char *p = compose_pairs; *p; p += 2) + if (p[0] == ascii || p[1] == ascii) { + if (p[1] == ' ') e_text[0] = (p-compose_pairs)/2+0xA0; + compose_state = ascii; + return 1; + } + + if (e_length) { // compose key also "quotes" control characters + compose_state = 0; + return 1; + } + + } else if (compose_state) { // second character of compose + + char c1 = char(compose_state); // retrieve first character + // now search for the pair in either order: + for (const char *p = compose_pairs; *p; p += 2) { + if (p[0] == ascii && p[1] == c1 || p[1] == ascii && p[0] == c1) { + e_text[0] = (p-compose_pairs)/2+0xA0; + del = 1; // delete the old character and insert new one + compose_state = 0; + return 1; + } + } + + } + + int i = e_keysym; + + // See if they type the compose prefix key: + if (i == FL_Control_R || i == 0xff20/* Multi-Key */) { + compose_state = 1; + return 1; + } + +#ifndef WIN32 // X only + // See if they typed a dead key. This gets it into the same state as + // typing prefix+accent: + if (i >= 0xfe50 && i <= 0xfe5b) { +# ifdef OLD_DEAD_KEY_CODE + ascii = dead_keys[i-0xfe50]; + for (const char *p = compose_pairs; *p; p += 2) + if (p[0] == ascii) { + compose_state = ascii; + return 1; + } +# else + ascii = e_text[0]; + for (const char *p = compose_pairs; *p; p += 2) + if (p[0] == ascii || + (p[1] == ' ' && (p - compose_pairs) / 2 + 0xA0 == ascii)) { + compose_state = p[0]; + return 1; + } +# endif // OLD_DEAD_KEY_CODE + compose_state = 0; + return 1; + } +#endif + + // Only insert non-control characters: + if (e_length && (ascii & ~31 && ascii!=127)) {compose_state = 0; return 1;} + + return 0; +} + diff --git a/Utilities/FLTK/src/Fl_display.cxx b/Utilities/FLTK/src/Fl_display.cxx new file mode 100644 index 0000000000..8afc2583e7 --- /dev/null +++ b/Utilities/FLTK/src/Fl_display.cxx @@ -0,0 +1,54 @@ +// +// "$Id$" +// +// Display function for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Startup method to set what display to use. +// Using setenv makes programs that are exec'd use the same display. + +#include <FL/Fl.H> +#include <stdlib.h> +#include "flstring.h" + +void Fl::display(const char *d) { +#if defined(__APPLE__) || defined(WIN32) + (void)d; +#else + static char e[1024]; + strcpy(e,"DISPLAY="); + strlcat(e,d,sizeof(e)); + for (char *c = e+8; *c!=':'; c++) { + if (!*c) { + strlcat(e,":0.0",sizeof(e)); + break; + } + } + putenv(e); +#endif // __APPLE__ +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_get_key.cxx b/Utilities/FLTK/src/Fl_get_key.cxx new file mode 100644 index 0000000000..02efea25d5 --- /dev/null +++ b/Utilities/FLTK/src/Fl_get_key.cxx @@ -0,0 +1,69 @@ +// +// "$Id$" +// +// Keyboard state routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifdef WIN32 +# include "Fl_get_key_win32.cxx" +#elif defined(__APPLE__) +# include "Fl_get_key_mac.cxx" +#else + +// Return the current state of a key. This is the X version. I identify +// keys (mostly) by the X keysym. So this turns the keysym into a keycode +// and looks it up in the X key bit vector, which Fl_x.cxx keeps track of. + +# include <FL/Fl.H> +# include <FL/x.H> + +extern char fl_key_vector[32]; // in Fl_x.cxx + +int Fl::event_key(int k) { + if (k > FL_Button && k <= FL_Button+8) + return Fl::event_state(8<<(k-FL_Button)); + int i; +# ifdef __sgi + // get some missing PC keyboard keys: + if (k == FL_Meta_L) i = 147; + else if (k == FL_Meta_R) i = 148; + else if (k == FL_Menu) i = 149; + else +# endif + i = XKeysymToKeycode(fl_display, k); + if (i==0) return 0; + return fl_key_vector[i/8] & (1 << (i%8)); +} + +int Fl::get_key(int k) { + fl_open_display(); + XQueryKeymap(fl_display, fl_key_vector); + return event_key(k); +} + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_get_key_mac.cxx b/Utilities/FLTK/src/Fl_get_key_mac.cxx new file mode 100644 index 0000000000..39f0d4b97e --- /dev/null +++ b/Utilities/FLTK/src/Fl_get_key_mac.cxx @@ -0,0 +1,107 @@ +// +// "$Id$" +// +// MacOS keyboard state routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Return the current state of a key. Keys are named by fltk symbols, +// which are actually X keysyms. So this has to translate to macOS +// symbols. + +#include <FL/Fl.H> +#include <FL/x.H> +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +// convert an FLTK (X) keysym to a MacOS symbol: +// See also the inverse converter in Fl_mac.cxx +// This table is in numeric order by FLTK symbol order for binary search: + +static const struct {unsigned short vk, fltk;} vktab[] = { + { 49, ' ' }, { 39, '\'' }, { 43, ',' }, { 27, '-' }, { 47, '.' }, { 44, '/' }, + { 29, '0' }, { 18, '1' }, { 19, '2' }, { 20, '3' }, + { 21, '4' }, { 23, '5' }, { 22, '6' }, { 26, '7' }, + { 28, '8' }, { 25, '9' }, { 41, ';' }, { 24, '=' }, + { 0, 'A' }, { 11, 'B' }, { 8, 'C' }, { 2, 'D' }, + { 14, 'E' }, { 3, 'F' }, { 5, 'G' }, { 4, 'H' }, + { 34, 'I' }, { 38, 'J' }, { 40, 'K' }, { 37, 'L' }, + { 46, 'M' }, { 45, 'N' }, { 31, 'O' }, { 35, 'P' }, + { 12, 'Q' }, { 15, 'R' }, { 1, 'S' }, { 17, 'T' }, + { 32, 'U' }, { 9, 'V' }, { 13, 'W' }, { 7, 'X' }, + { 16, 'Y' }, { 6, 'Z' }, + { 33, '[' }, { 30, ']' }, { 50, '`' }, { 42, '|' }, + { 51, FL_BackSpace }, { 48, FL_Tab }, { 36, FL_Enter }, { 127, FL_Pause }, + { 107, FL_Scroll_Lock }, { 53, FL_Escape }, { 0x73, FL_Home }, { 123, FL_Left }, + { 126, FL_Up }, { 124, FL_Right }, { 125, FL_Down }, { 0x74, FL_Page_Up }, + { 0x79, FL_Page_Down }, { 119, FL_End }, { 0x71, FL_Print }, { 127, FL_Insert }, + { 0x6e, FL_Menu }, { 114, FL_Help }, { 0x47, FL_Num_Lock }, + { 76, FL_KP_Enter }, { 67, FL_KP+'*' }, { 69, FL_KP+'+'}, { 78, FL_KP+'-' }, { 65, FL_KP+'.' }, { 75, FL_KP+'/' }, + { 82, FL_KP+'0' }, { 83, FL_KP+'1' }, { 84, FL_KP+'2' }, { 85, FL_KP+'3' }, + { 86, FL_KP+'4' }, { 87, FL_KP+'5' }, { 88, FL_KP+'6' }, { 89, FL_KP+'7' }, + { 91, FL_KP+'8' }, { 92, FL_KP+'9' }, { 81, FL_KP+'=' }, + { 0x7a, FL_F+1 }, { 0x78, FL_F+2 }, { 0x63, FL_F+3 }, { 0x76, FL_F+4 }, + { 0x60, FL_F+5 }, { 0x61, FL_F+6 }, { 0x62, FL_F+7 }, { 0x64, FL_F+8 }, + { 0x65, FL_F+9 }, { 0x6D, FL_F+10 }, { 0x67, FL_F+11 }, { 0x6f, FL_F+12 }, + { 56, FL_Shift_L }, { 56, FL_Shift_R }, { 59, FL_Control_L }, { 59, FL_Control_R }, + { 57, FL_Caps_Lock }, { 55, FL_Meta_L }, { 55, FL_Meta_R }, + { 58, FL_Alt_L }, { 58, FL_Alt_R }, { 0x75, FL_Delete }, +}; + +static int fltk2mac(int fltk) { + int a = 0; + int b = sizeof(vktab)/sizeof(*vktab); + while (a < b) { + int c = (a+b)/2; + if (vktab[c].fltk == fltk) return vktab[c].vk; + if (vktab[c].fltk < fltk) a = c+1; else b = c; + } + return 127; +} + +//: returns true, if that key was pressed during the last event +int Fl::event_key(int k) { + return get_key(k); +} + +#include <stdio.h> + +//: returns true, if that key is pressed right now +int Fl::get_key(int k) { + KeyMap foo; + GetKeys(foo); +#ifdef MAC_TEST_FOR_KEYCODES + static int cnt = 0; + if (cnt++>1024) { + cnt = 0; + printf("%08x %08x %08x %08x\n", (ulong*)(foo)[3], (ulong*)(foo)[2], (ulong*)(foo)[1], (ulong*)(foo)[0]); + } +#endif + int i = fltk2mac(k); + unsigned char *b = (unsigned char*)foo; + return (b[i>>3]>>(i&7))&1; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_get_key_win32.cxx b/Utilities/FLTK/src/Fl_get_key_win32.cxx new file mode 100755 index 0000000000..eaa677a5ab --- /dev/null +++ b/Utilities/FLTK/src/Fl_get_key_win32.cxx @@ -0,0 +1,138 @@ +// +// "$Id$" +// +// WIN32 keyboard state routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Return the current state of a key. Keys are named by fltk symbols, +// which are actually X keysyms. So this has to translate to MSWindows +// VK_x symbols. + +#include <FL/Fl.H> +#include <FL/x.H> + +// convert an Fltk (X) keysym to a MSWindows VK symbol: +// See also the inverse converter in Fl_win32.cxx +// This table is in numeric order by Fltk symbol order for binary search: + +static const struct {unsigned short vk, fltk;} vktab[] = { + {VK_SPACE, ' '}, + {'1', '!'}, + {0xde, '\"'}, + {'3', '#'}, + {'4', '$'}, + {'5', '%'}, + {'7', '&'}, + {0xde, '\''}, + {'9', '('}, + {'0', ')'}, + {'8', '*'}, + {0xbb, '+'}, + {0xbc, ','}, + {0xbd, '-'}, + {0xbe, '.'}, + {0xbf, '/'}, + {0xba, ':'}, + {0xba, ';'}, + {0xbc, '<'}, + {0xbb, '='}, + {0xbe, '>'}, + {0xbf, '?'}, + {'2', '@'}, + {0xdb, '['}, + {0xdc, '\\'}, + {0xdd, ']'}, + {'6', '^'}, + {0xbd, '_'}, + {0xc0, '`'}, + {0xdb, '{'}, + {0xdc, '|'}, + {0xdd, '}'}, + {0xc0, '~'}, + {VK_BACK, FL_BackSpace}, + {VK_TAB, FL_Tab}, + {VK_CLEAR, 0xff0b/*XK_Clear*/}, + {VK_RETURN, FL_Enter}, + {VK_PAUSE, FL_Pause}, + {VK_SCROLL, FL_Scroll_Lock}, + {VK_ESCAPE, FL_Escape}, + {VK_HOME, FL_Home}, + {VK_LEFT, FL_Left}, + {VK_UP, FL_Up}, + {VK_RIGHT, FL_Right}, + {VK_DOWN, FL_Down}, + {VK_PRIOR, FL_Page_Up}, + {VK_NEXT, FL_Page_Down}, + {VK_END, FL_End}, + {VK_SNAPSHOT, FL_Print}, + {VK_INSERT, FL_Insert}, + {VK_APPS, FL_Menu}, + {VK_NUMLOCK, FL_Num_Lock}, +//{VK_???, FL_KP_Enter}, + {VK_MULTIPLY, FL_KP+'*'}, + {VK_ADD, FL_KP+'+'}, + {VK_SUBTRACT, FL_KP+'-'}, + {VK_DECIMAL, FL_KP+'.'}, + {VK_DIVIDE, FL_KP+'/'}, + {VK_LSHIFT, FL_Shift_L}, + {VK_RSHIFT, FL_Shift_R}, + {VK_LCONTROL, FL_Control_L}, + {VK_RCONTROL, FL_Control_R}, + {VK_CAPITAL, FL_Caps_Lock}, + {VK_LWIN, FL_Meta_L}, + {VK_RWIN, FL_Meta_R}, + {VK_LMENU, FL_Alt_L}, + {VK_RMENU, FL_Alt_R}, + {VK_DELETE, FL_Delete} +}; + +static int fltk2ms(int fltk) { + if (fltk >= '0' && fltk <= '9') return fltk; + if (fltk >= 'A' && fltk <= 'Z') return fltk; + if (fltk >= 'a' && fltk <= 'z') return fltk-('a'-'A'); + if (fltk > FL_F && fltk <= FL_F+16) return fltk-(FL_F-(VK_F1-1)); + if (fltk >= FL_KP+'0' && fltk<=FL_KP+'9') return fltk-(FL_KP+'0'-VK_NUMPAD0); + int a = 0; + int b = sizeof(vktab)/sizeof(*vktab); + while (a < b) { + int c = (a+b)/2; + if (vktab[c].fltk == fltk) return vktab[c].vk; + if (vktab[c].fltk < fltk) a = c+1; else b = c; + } + return 0; +} + +int Fl::event_key(int k) { + return GetKeyState(fltk2ms(k))&~1; +} + +int Fl::get_key(int k) { + uchar foo[256]; + GetKeyboardState(foo); + return foo[fltk2ms(k)]&~1; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_get_system_colors.cxx b/Utilities/FLTK/src/Fl_get_system_colors.cxx new file mode 100644 index 0000000000..1193647fff --- /dev/null +++ b/Utilities/FLTK/src/Fl_get_system_colors.cxx @@ -0,0 +1,348 @@ +// +// "$Id$" +// +// System color support for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/*OTB Modifications: add line #include "fltk-config.h" */ +#include "fltk-config.h" + +#include <FL/Fl.H> +#include <FL/fl_draw.H> +#include <FL/x.H> +#include <FL/math.h> +#include "flstring.h" +#include <stdio.h> +#include <stdlib.h> +#include <FL/Fl_Pixmap.H> +#include <FL/Fl_Tiled_Image.H> +#include "tile.xpm" + +#if defined(__APPLE__) && defined(__MWERKS__) +extern "C" int putenv(const char*); +#endif // __APPLE__ && __MWERKS__ + +#if defined(WIN32) && !defined(__CYGWIN__) +// Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs +// on Windows, which is supposed to be POSIX compliant... +# define putenv _putenv +#endif // WIN32 && !__CYGWIN__ + +static char fl_bg_set = 0; +static char fl_bg2_set = 0; +static char fl_fg_set = 0; + + +void Fl::background(uchar r, uchar g, uchar b) { + fl_bg_set = 1; + + // replace the gray ramp so that FL_GRAY is this color + if (!r) r = 1; else if (r==255) r = 254; + double powr = log(r/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0)); + if (!g) g = 1; else if (g==255) g = 254; + double powg = log(g/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0)); + if (!b) b = 1; else if (b==255) b = 254; + double powb = log(b/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0)); + for (int i = 0; i < FL_NUM_GRAY; i++) { + double gray = i/(FL_NUM_GRAY-1.0); + Fl::set_color(fl_gray_ramp(i), + uchar(pow(gray,powr)*255+.5), + uchar(pow(gray,powg)*255+.5), + uchar(pow(gray,powb)*255+.5)); + } +} + +void Fl::foreground(uchar r, uchar g, uchar b) { + fl_fg_set = 1; + + Fl::set_color(FL_FOREGROUND_COLOR,r,g,b); +} + +void Fl::background2(uchar r, uchar g, uchar b) { + fl_bg2_set = 1; + + Fl::set_color(FL_BACKGROUND2_COLOR,r,g,b); + Fl::set_color(FL_FOREGROUND_COLOR, + get_color(fl_contrast(FL_FOREGROUND_COLOR,FL_BACKGROUND2_COLOR))); +} + +// these are set by Fl::args() and override any system colors: +const char *fl_fg = NULL; +const char *fl_bg = NULL; +const char *fl_bg2 = NULL; + +static void set_selection_color(uchar r, uchar g, uchar b) { + Fl::set_color(FL_SELECTION_COLOR,r,g,b); +} + +#if defined(WIN32) || defined(__APPLE__) + +# include <stdio.h> +// simulation of XParseColor: +int fl_parse_color(const char* p, uchar& r, uchar& g, uchar& b) { + if (*p == '#') p++; + int n = strlen(p); + int m = n/3; + const char *pattern = 0; + switch(m) { + case 1: pattern = "%1x%1x%1x"; break; + case 2: pattern = "%2x%2x%2x"; break; + case 3: pattern = "%3x%3x%3x"; break; + case 4: pattern = "%4x%4x%4x"; break; + default: return 0; + } + int R,G,B; if (sscanf(p,pattern,&R,&G,&B) != 3) return 0; + switch(m) { + case 1: R *= 0x11; G *= 0x11; B *= 0x11; break; + case 3: R >>= 4; G >>= 4; B >>= 4; break; + case 4: R >>= 8; G >>= 8; B >>= 8; break; + } + r = (uchar)R; g = (uchar)G; b = (uchar)B; + return 1; +} +#else +// Wrapper around XParseColor... +int fl_parse_color(const char* p, uchar& r, uchar& g, uchar& b) { + XColor x; + if (!fl_display) fl_open_display(); + if (XParseColor(fl_display, fl_colormap, p, &x)) { + r = (uchar)(x.red>>8); + g = (uchar)(x.green>>8); + b = (uchar)(x.blue>>8); + return 1; + } else return 0; +} +#endif // WIN32 || __APPLE__ + +#if defined(WIN32) +static void +getsyscolor(int what, const char* arg, void (*func)(uchar,uchar,uchar)) +{ + if (arg) { + uchar r,g,b; + if (!fl_parse_color(arg, r,g,b)) + Fl::error("Unknown color: %s", arg); + else + func(r,g,b); + } else { + DWORD x = GetSysColor(what); + func(uchar(x&255), uchar(x>>8), uchar(x>>16)); + } +} + +void Fl::get_system_colors() { + if (!fl_bg2_set) getsyscolor(COLOR_WINDOW, fl_bg2,Fl::background2); + if (!fl_fg_set) getsyscolor(COLOR_WINDOWTEXT, fl_fg, Fl::foreground); + if (!fl_bg_set) getsyscolor(COLOR_BTNFACE, fl_bg, Fl::background); + getsyscolor(COLOR_HIGHLIGHT, 0, set_selection_color); +} + +#elif defined(__APPLE__) +// MacOS X currently supports two color schemes - Blue and Graphite. +// Since we aren't emulating the Aqua interface (even if Apple would +// let us), we use some defaults that are similar to both. The +// Fl::scheme("plastic") color/box scheme provides a usable Aqua-like +// look-n-feel... +void Fl::get_system_colors() +{ + fl_open_display(); + + if (!fl_bg2_set) background2(0xff, 0xff, 0xff); + if (!fl_fg_set) foreground(0, 0, 0); + if (!fl_bg_set) background(0xd8, 0xd8, 0xd8); + set_selection_color(0x00, 0x00, 0x80); +} +#else + +// Read colors that KDE writes to the xrdb database. + +// XGetDefault does not do the expected thing: it does not like +// periods in either word. Therefore it cannot match class.Text.background. +// However *.Text.background is matched by pretending the program is "Text". +// But this will also match *.background if there is no *.Text.background +// entry, requiring users to put in both (unless they want the text fields +// the same color as the windows). + +static void +getsyscolor(const char *key1, const char* key2, const char *arg, const char *defarg, void (*func)(uchar,uchar,uchar)) +{ + if (!arg) { + arg = XGetDefault(fl_display, key1, key2); + if (!arg) arg = defarg; + } + XColor x; + if (!XParseColor(fl_display, fl_colormap, arg, &x)) + Fl::error("Unknown color: %s", arg); + else + func(x.red>>8, x.green>>8, x.blue>>8); +} + +void Fl::get_system_colors() +{ + fl_open_display(); + const char* key1 = 0; + if (Fl::first_window()) key1 = Fl::first_window()->xclass(); + if (!key1) key1 = "fltk"; + if (!fl_bg2_set) getsyscolor("Text","background", fl_bg2, "#ffffff", Fl::background2); + if (!fl_fg_set) getsyscolor(key1, "foreground", fl_fg, "#000000", Fl::foreground); + if (!fl_bg_set) getsyscolor(key1, "background", fl_bg, "#c0c0c0", Fl::background); + getsyscolor(key1, "selectBackground",0, "#000080", set_selection_color); +} + +#endif + + +//// Simple implementation of 2.0 Fl::scheme() interface... +#define D1 BORDER_WIDTH +#define D2 (BORDER_WIDTH+BORDER_WIDTH) + +extern void fl_up_box(int, int, int, int, Fl_Color); +extern void fl_down_box(int, int, int, int, Fl_Color); +extern void fl_thin_up_box(int, int, int, int, Fl_Color); +extern void fl_thin_down_box(int, int, int, int, Fl_Color); +extern void fl_round_up_box(int, int, int, int, Fl_Color); +extern void fl_round_down_box(int, int, int, int, Fl_Color); + +extern void fl_up_frame(int, int, int, int, Fl_Color); +extern void fl_down_frame(int, int, int, int, Fl_Color); +extern void fl_thin_up_frame(int, int, int, int, Fl_Color); +extern void fl_thin_down_frame(int, int, int, int, Fl_Color); + +const char *Fl::scheme_ = (const char *)0; +Fl_Image *Fl::scheme_bg_ = (Fl_Image *)0; + +static Fl_Pixmap tile(tile_xpm); + +int Fl::scheme(const char *s) { + if (!s) { + if ((s = getenv("FLTK_SCHEME")) == NULL) { +#if !defined(WIN32) && !defined(__APPLE__) + const char* key = 0; + if (Fl::first_window()) key = Fl::first_window()->xclass(); + if (!key) key = "fltk"; + fl_open_display(); + s = XGetDefault(fl_display, key, "scheme"); +#endif // !WIN32 && !__APPLE__ + } + } + + if (s) { + if (!strcasecmp(s, "none") || !strcasecmp(s, "base") || !*s) s = 0; + else s = strdup(s); + } + if (scheme_) free((void*)scheme_); + scheme_ = s; + + // Save the new scheme in the FLTK_SCHEME env var so that child processes + // inherit it... + static char e[1024]; + strcpy(e,"FLTK_SCHEME="); + if (s) strlcat(e,s,sizeof(e)); + putenv(e); + + // Load the scheme... + return reload_scheme(); +} + +int Fl::reload_scheme() { + Fl_Window *win; + + if (scheme_ && !strcasecmp(scheme_, "plastic")) { + // Update the tile image to match the background color... + uchar r, g, b; + int nr, ng, nb; + int i; +// static uchar levels[3] = { 0xff, 0xef, 0xe8 }; + // OSX 10.3 and higher use a background with less contrast... + static uchar levels[3] = { 0xff, 0xf8, 0xf4 }; + + get_color(FL_GRAY, r, g, b); + +// printf("FL_GRAY = 0x%02x 0x%02x 0x%02x\n", r, g, b); + + for (i = 0; i < 3; i ++) { + nr = levels[i] * r / 0xe8; + if (nr > 255) nr = 255; + + ng = levels[i] * g / 0xe8; + if (ng > 255) ng = 255; + + nb = levels[i] * b / 0xe8; + if (nb > 255) nb = 255; + + sprintf(tile_cmap[i], "%c c #%02x%02x%02x", "Oo."[i], nr, ng, nb); +// puts(tile_cmap[i]); + } + + tile.uncache(); + + if (!scheme_bg_) scheme_bg_ = new Fl_Tiled_Image(&tile, w(), h()); + + // Load plastic buttons, etc... + set_boxtype(FL_UP_FRAME, FL_PLASTIC_UP_FRAME); + set_boxtype(FL_DOWN_FRAME, FL_PLASTIC_DOWN_FRAME); + set_boxtype(FL_THIN_UP_FRAME, FL_PLASTIC_UP_FRAME); + set_boxtype(FL_THIN_DOWN_FRAME, FL_PLASTIC_DOWN_FRAME); + + set_boxtype(FL_UP_BOX, FL_PLASTIC_UP_BOX); + set_boxtype(FL_DOWN_BOX, FL_PLASTIC_DOWN_BOX); + set_boxtype(FL_THIN_UP_BOX, FL_PLASTIC_THIN_UP_BOX); + set_boxtype(FL_THIN_DOWN_BOX, FL_PLASTIC_THIN_DOWN_BOX); + set_boxtype(_FL_ROUND_UP_BOX, FL_PLASTIC_ROUND_UP_BOX); + set_boxtype(_FL_ROUND_DOWN_BOX, FL_PLASTIC_ROUND_DOWN_BOX); + } else { + // Use the standard FLTK look-n-feel... + if (scheme_bg_) { + delete scheme_bg_; + scheme_bg_ = (Fl_Image *)0; + } + + set_boxtype(FL_UP_FRAME, fl_up_frame, D1, D1, D2, D2); + set_boxtype(FL_DOWN_FRAME, fl_down_frame, D1, D1, D2, D2); + set_boxtype(FL_THIN_UP_FRAME, fl_thin_up_frame, 1, 1, 2, 2); + set_boxtype(FL_THIN_DOWN_FRAME, fl_thin_down_frame, 1, 1, 2, 2); + + set_boxtype(FL_UP_BOX, fl_up_box, D1, D1, D2, D2); + set_boxtype(FL_DOWN_BOX, fl_down_box, D1, D1, D2, D2); + set_boxtype(FL_THIN_UP_BOX, fl_thin_up_box, 1, 1, 2, 2); + set_boxtype(FL_THIN_DOWN_BOX, fl_thin_down_box, 1, 1, 2, 2); + set_boxtype(_FL_ROUND_UP_BOX, fl_round_up_box, 3, 3, 6, 6); + set_boxtype(_FL_ROUND_DOWN_BOX, fl_round_down_box, 3, 3, 6, 6); + } + + // Set (or clear) the background tile for all windows... + for (win = first_window(); win; win = next_window(win)) { + win->labeltype(scheme_bg_ ? FL_NORMAL_LABEL : FL_NO_LABEL); + win->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP); + win->image(scheme_bg_); + win->redraw(); + } + + return 1; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_grab.cxx b/Utilities/FLTK/src/Fl_grab.cxx new file mode 100644 index 0000000000..a1a5ee5a82 --- /dev/null +++ b/Utilities/FLTK/src/Fl_grab.cxx @@ -0,0 +1,108 @@ +// +// "$Id$" +// +// Grab/release code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#include <FL/x.H> +#include <FL/Fl.H> + +//////////////////////////////////////////////////////////////// +// "Grab" is done while menu systems are up. This has several effects: +// Events are all sent to the "grab window", which does not even +// have to be displayed (and in the case of Fl_Menu.cxx it isn't). +// The system is also told to "grab" events and send them to this app. +// This also modifies how Fl_Window::show() works, on X it turns on +// override_redirect, it does similar things on WIN32. + +extern void fl_fix_focus(); // in Fl.cxx + +#ifdef WIN32 +// We have to keep track of whether we have captured the mouse, since +// MSWindows shows little respect for this... Grep for fl_capture to +// see where and how this is used. +extern HWND fl_capture; +#endif + +#ifdef __APPLE__ +// MacOS Carbon does not seem to have a mechanism to grab the mouse pointer +extern WindowRef fl_capture; +#endif + +void Fl::grab(Fl_Window* win) { + if (win) { + if (!grab_) { +#ifdef WIN32 + SetActiveWindow(fl_capture = fl_xid(first_window())); + SetCapture(fl_capture); +#elif defined(__APPLE__) + fl_capture = fl_xid( first_window() ); + SetUserFocusWindow( fl_capture ); +#else + XGrabPointer(fl_display, + fl_xid(first_window()), + 1, + ButtonPressMask|ButtonReleaseMask| + ButtonMotionMask|PointerMotionMask, + GrabModeAsync, + GrabModeAsync, + None, + 0, + fl_event_time); + XGrabKeyboard(fl_display, + fl_xid(first_window()), + 1, + GrabModeAsync, + GrabModeAsync, + fl_event_time); +#endif + } + grab_ = win; + } else { + if (grab_) { +#ifdef WIN32 + fl_capture = 0; + ReleaseCapture(); +#elif defined(__APPLE__) + fl_capture = 0; + SetUserFocusWindow( (WindowRef)kUserFocusAuto ); +#else + XUngrabKeyboard(fl_display, fl_event_time); + XUngrabPointer(fl_display, fl_event_time); + // this flush is done in case the picked menu item goes into + // an infinite loop, so we don't leave the X server locked up: + XFlush(fl_display); +#endif + grab_ = 0; + fl_fix_focus(); + } + } +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_lock.cxx b/Utilities/FLTK/src/Fl_lock.cxx new file mode 100644 index 0000000000..4a47f90821 --- /dev/null +++ b/Utilities/FLTK/src/Fl_lock.cxx @@ -0,0 +1,211 @@ +// +// "$Id$" +// +// Multi-threading support code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + + +#include <FL/Fl.H> +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +/* + From Bill: + + I would prefer that FLTK contain the minimal amount of extra + stuff for doing threads. There are other portable thread + wrapper libraries out there and FLTK should not be providing + another. This file is an attempt to make minimal additions + and make them self-contained in this source file. + + Fl::lock() - recursive lock. You must call this before the + first call to Fl::wait()/run() to initialize the thread + system. The lock is locked all the time except when + Fl::wait() is waiting for events. + + Fl::unlock() - release the recursive lock. + + Fl::awake(void*) - Causes Fl::wait() to return (with the lock + locked) even if there are no events ready. + + Fl::thread_message() - returns an argument sent to an + Fl::awake() call, or returns NULL if none. WARNING: the + current implementation only has a one-entry queue and only + returns the most recent value! +*/ + + +//////////////////////////////////////////////////////////////// +// Windows threading... +#ifdef WIN32 +# include <windows.h> +# include <process.h> +# include <FL/x.H> + +// These pointers are in Fl_win32.cxx: +extern void (*fl_lock_function)(); +extern void (*fl_unlock_function)(); + +// The main thread's ID +static DWORD main_thread; + +// Microsoft's version of a MUTEX... +CRITICAL_SECTION cs; + +// +// 'unlock_function()' - Release the lock. +// + +static void unlock_function() { + LeaveCriticalSection(&cs); +} + +// +// 'lock_function()' - Get the lock. +// + +static void lock_function() { + EnterCriticalSection(&cs); +} + +// +// 'Fl::lock()' - Lock access to FLTK data structures... +// + +void Fl::lock() { + if (!main_thread) InitializeCriticalSection(&cs); + + lock_function(); + + if (!main_thread) { + fl_lock_function = lock_function; + fl_unlock_function = unlock_function; + main_thread = GetCurrentThreadId(); + } +} + +// +// 'Fl::unlock()' - Unlock access to FLTK data structures... +// + +void Fl::unlock() { + unlock_function(); +} + + +// +// 'Fl::awake()' - Let the main thread know an update is pending. +// +// When called from a thread, it causes FLTK to awake from Fl::wait()... +// + +void Fl::awake(void* msg) { + PostThreadMessage( main_thread, fl_wake_msg, (WPARAM)msg, 0); +} + +//////////////////////////////////////////////////////////////// +// POSIX threading... +#elif HAVE_PTHREAD +# include <unistd.h> +# include <pthread.h> + +# if defined (PTHREAD_MUTEX_RECURSIVE_NP) +// Linux supports recursive locks, use them directly: + +static bool minit; +static pthread_mutex_t fltk_mutex; +// this is needed for the Fl_Mutex constructor: +pthread_mutexattr_t Fl_Mutex_attrib = {PTHREAD_MUTEX_RECURSIVE_NP}; + +static void lock_function() { + if (!minit) { + pthread_mutex_init(&fltk_mutex, &Fl_Mutex_attrib); + minit = true; + } + pthread_mutex_lock(&fltk_mutex); +} + +void Fl::unlock() { + pthread_mutex_unlock(&fltk_mutex); +} + +# else +// Make a recursive lock out of the pthread mutex: + +static pthread_mutex_t fltk_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_t owner; +static int counter; + +static void lock_function() { + if (!counter || owner != pthread_self()) { + pthread_mutex_lock(&fltk_mutex); + owner = pthread_self(); + } + counter++; +} + +void Fl::unlock() { + if (!--counter) pthread_mutex_unlock(&fltk_mutex); +} + +# endif + +// Pipe for thread messaging... +static int thread_filedes[2]; + +// These pointers are in Fl_x.cxx: +extern void (*fl_lock_function)(); +extern void (*fl_unlock_function)(); + +static void* thread_message_; +void* Fl::thread_message() { + void* r = thread_message_; + thread_message_ = 0; + return r; +} + +static void thread_awake_cb(int fd, void*) { + read(fd, &thread_message_, sizeof(void*)); +} + +void Fl::lock() { + lock_function(); + if (!thread_filedes[1]) { // initialize the mt support + // Init threads communication pipe to let threads awake FLTK from wait + pipe(thread_filedes); + Fl::add_fd(thread_filedes[0], FL_READ, thread_awake_cb); + fl_lock_function = lock_function; + fl_unlock_function = Fl::unlock; + } +} + +void Fl::awake(void* msg) { + write(thread_filedes[1], &msg, sizeof(void*)); +} + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_mac.cxx b/Utilities/FLTK/src/Fl_mac.cxx new file mode 100644 index 0000000000..18a507e4c8 --- /dev/null +++ b/Utilities/FLTK/src/Fl_mac.cxx @@ -0,0 +1,2244 @@ +// +// "$Id$" +// +// MacOS specific code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2006 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +//// From the inner edge of a MetroWerks CodeWarrior CD: +// (without permission) +// +// Three Compiles for 68Ks under the sky, +// Seven Compiles for PPCs in their fragments of code, +// Nine Compiles for Mortal Carbon doomed to die, +// One Compile for Mach-O Cocoa on its Mach-O throne, +// in the Land of MacOS X where the Drop-Shadows lie. +// +// One Compile to link them all, One Compile to merge them, +// One Compile to copy them all and in the bundle bind them, +// in the Land of MacOS X where the Drop-Shadows lie. + +// warning: the Apple Quartz version still uses some Quickdraw calls, +// mostly to get around the single active context in QD and +// to implement clipping. This should be changed into pure +// Quartz calls in the near future. + +// we don't need the following definition because we deliver only +// true mouse moves. On very slow systems however, this flag may +// still be useful. +#define CONSOLIDATE_MOTION 0 +extern "C" { +#include <pthread.h> +} + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#include <FL/x.H> +#include <FL/Fl_Tooltip.H> +#include <FL/Fl_Window.H> +#include <FL/Fl_Sys_Menu_Bar.H> +#include <stdio.h> +#include <stdlib.h> +#include "flstring.h" +#include <unistd.h> + +// #define DEBUG_SELECT // UNCOMMENT FOR SELECT()/THREAD DEBUGGING +#ifdef DEBUG_SELECT +#include <stdio.h> // testing +#define DEBUGMSG(msg) if ( msg ) fprintf(stderr, msg); +#define DEBUGPERRORMSG(msg) if ( msg ) perror(msg) +#define DEBUGTEXT(txt) txt +#else +#define DEBUGMSG(msg) +#define DEBUGPERRORMSG(msg) +#define DEBUGTEXT(txt) NULL +#endif /*DEBUG_SELECT*/ + +// external functions +extern Fl_Window* fl_find(Window); +extern void fl_fix_focus(); + +// forward definition of functions in this file +static void handleUpdateEvent( WindowPtr xid ); +//+ int fl_handle(const EventRecord &event); +static int FSSpec2UnixPath( FSSpec *fs, char *dst ); + +// public variables +int fl_screen; +CGContextRef fl_gc = 0; +Handle fl_system_menu; +Fl_Sys_Menu_Bar *fl_sys_menu_bar = 0; +CursHandle fl_default_cursor; +WindowRef fl_capture = 0; // we need this to compensate for a missing(?) mouse capture +ulong fl_event_time; // the last timestamp from an x event +char fl_key_vector[32]; // used by Fl::get_key() +bool fl_show_iconic; // true if called from iconize() - shows the next created window in collapsed state +int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR +const Fl_Window* fl_modal_for; // parent of modal() window +Fl_Region fl_window_region = 0; +Window fl_window; +Fl_Window *Fl_Window::current_; +EventRef fl_os_event; // last (mouse) event + +// forward declarations of variables in this file +static int got_events = 0; +static Fl_Window* resize_from_system; +static CursPtr default_cursor_ptr; +static Cursor default_cursor; +static WindowRef fl_os_capture = 0; // the dispatch handler will redirect mose move and drag events to these windows + +#if CONSOLIDATE_MOTION +static Fl_Window* send_motion; +extern Fl_Window* fl_xmousewin; +#endif + +enum { kEventClassFLTK = 'fltk' }; +enum { kEventFLTKBreakLoop = 1, kEventFLTKDataReady }; + +/** +* Mac keyboard lookup table + */ +static unsigned short macKeyLookUp[128] = +{ + 'a', 's', 'd', 'f', 'h', 'g', 'z', 'x', + 'c', 'v', 0/*ISO extra ('#' on German keyboard)*/, 'b', 'q', 'w', 'e', 'r', + + 'y', 't', '1', '2', '3', '4', '6', '5', + '=', '9', '7', '-', '8', '0', ']', 'o', + + 'u', '[', 'i', 'p', FL_Enter, 'l', 'j', '\'', + 'k', ';', '\\', ',', '/', 'n', 'm', '.', + + FL_Tab, ' ', '`', FL_BackSpace, 0/*kp_enter on powerbook G4*/, FL_Escape, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, FL_KP+'.', FL_Right, FL_KP+'*', 0, FL_KP+'+', FL_Left, FL_Num_Lock, + FL_Down, 0, 0, FL_KP+'/', FL_KP_Enter, FL_Up, FL_KP+'-', 0, + + 0, FL_KP+'=', FL_KP+'0', FL_KP+'1', FL_KP+'2', FL_KP+'3', FL_KP+'4', FL_KP+'5', + FL_KP+'6', FL_KP+'7', 0, FL_KP+'8', FL_KP+'9', 0, 0, 0, + + FL_F+5, FL_F+6, FL_F+7, FL_F+3, FL_F+8, FL_F+9, 0, FL_F+11, + 0, 0, FL_Print, FL_Scroll_Lock, 0, FL_F+10, FL_Menu, FL_F+12, + + 0, FL_Pause, FL_Help, FL_Home, FL_Page_Up, FL_Delete, FL_F+4, FL_End, + FL_F+2, FL_Page_Down, FL_F+1, FL_Left, FL_Right, FL_Down, FL_Up, 0, +}; + +/** + * convert the current mouse chord into the FLTK modifier state + */ +static void mods_to_e_state( UInt32 mods ) +{ + long state = 0; + if ( mods & kEventKeyModifierNumLockMask ) state |= FL_NUM_LOCK; + if ( mods & cmdKey ) state |= FL_META; + if ( mods & (optionKey|rightOptionKey) ) state |= FL_ALT; + if ( mods & (controlKey|rightControlKey) ) state |= FL_CTRL; + if ( mods & (shiftKey|rightShiftKey) ) state |= FL_SHIFT; + if ( mods & alphaLock ) state |= FL_CAPS_LOCK; + Fl::e_state = ( Fl::e_state & 0xff000000 ) | state; + //printf( "State 0x%08x (%04x)\n", Fl::e_state, mods ); +} + + +/** + * convert the current mouse chord into the FLTK keysym + */ +static void mods_to_e_keysym( UInt32 mods ) +{ + if ( mods & cmdKey ) Fl::e_keysym = FL_Meta_L; + else if ( mods & kEventKeyModifierNumLockMask ) Fl::e_keysym = FL_Num_Lock; + else if ( mods & optionKey ) Fl::e_keysym = FL_Alt_L; + else if ( mods & rightOptionKey ) Fl::e_keysym = FL_Alt_R; + else if ( mods & controlKey ) Fl::e_keysym = FL_Control_L; + else if ( mods & rightControlKey ) Fl::e_keysym = FL_Control_R; + else if ( mods & shiftKey ) Fl::e_keysym = FL_Shift_L; + else if ( mods & rightShiftKey ) Fl::e_keysym = FL_Shift_R; + else if ( mods & alphaLock ) Fl::e_keysym = FL_Caps_Lock; + else Fl::e_keysym = 0; + //printf( "to sym 0x%08x (%04x)\n", Fl::e_keysym, mods ); +} +// these pointers are set by the Fl::lock() function: +static void nothing() {} +void (*fl_lock_function)() = nothing; +void (*fl_unlock_function)() = nothing; + +// +// Select interface -- how it's implemented: +// When the user app configures one or more file descriptors to monitor +// with Fl::add_fd(), we start a separate thread to select() the data, +// sending a custom OSX 'FLTK data ready event' to the parent thread's +// RunApplicationLoop(), so that it triggers the data ready callbacks +// in the parent thread. -erco 04/04/04 +// +#define POLLIN 1 +#define POLLOUT 4 +#define POLLERR 8 + +// Class to handle select() 'data ready' +class DataReady +{ + struct FD + { + int fd; + short events; + void (*cb)(int, void*); + void* arg; + }; + int nfds, fd_array_size; + FD *fds; + pthread_t tid; // select()'s thread id + + // Data that needs to be locked (all start with '_') + pthread_mutex_t _datalock; // data lock + fd_set _fdsets[3]; // r/w/x sets user wants to monitor + int _maxfd; // max fd count to monitor + int _cancelpipe[2]; // pipe used to help cancel thread + void *_userdata; // thread's userdata + +public: + DataReady() + { + nfds = 0; + fd_array_size = 0; + fds = 0; + tid = 0; + + pthread_mutex_init(&_datalock, NULL); + FD_ZERO(&_fdsets[0]); FD_ZERO(&_fdsets[1]); FD_ZERO(&_fdsets[2]); + _cancelpipe[0] = _cancelpipe[1] = 0; + _userdata = 0; + _maxfd = 0; + } + + ~DataReady() + { + CancelThread(DEBUGTEXT("DESTRUCTOR\n")); + if (fds) { free(fds); fds = 0; } + nfds = 0; + } + + // Locks + // The convention for locks: volatile vars start with '_', + // and must be locked before use. Locked code is prefixed + // with /*LOCK*/ to make painfully obvious esp. in debuggers. -erco + // + void DataLock() { pthread_mutex_lock(&_datalock); } + void DataUnlock() { pthread_mutex_unlock(&_datalock); } + + // Accessors + int IsThreadRunning() { return(tid ? 1 : 0); } + int GetNfds() { return(nfds); } + int GetCancelPipe(int ix) { return(_cancelpipe[ix]); } + fd_set GetFdset(int ix) { return(_fdsets[ix]); } + + // Methods + void AddFD(int n, int events, void (*cb)(int, void*), void *v); + void RemoveFD(int n, int events); + int CheckData(fd_set& r, fd_set& w, fd_set& x); + void HandleData(fd_set& r, fd_set& w, fd_set& x); + static void* DataReadyThread(void *self); + void StartThread(void *userdata); + void CancelThread(const char *reason); +}; + +static DataReady dataready; + +void DataReady::AddFD(int n, int events, void (*cb)(int, void*), void *v) +{ + RemoveFD(n, events); + int i = nfds++; + if (i >= fd_array_size) + { + FD *temp; + fd_array_size = 2*fd_array_size+1; + if (!fds) { temp = (FD*)malloc(fd_array_size*sizeof(FD)); } + else { temp = (FD*)realloc(fds, fd_array_size*sizeof(FD)); } + if (!temp) return; + fds = temp; + } + fds[i].cb = cb; + fds[i].arg = v; + fds[i].fd = n; + fds[i].events = events; + DataLock(); + /*LOCK*/ if (events & POLLIN) FD_SET(n, &_fdsets[0]); + /*LOCK*/ if (events & POLLOUT) FD_SET(n, &_fdsets[1]); + /*LOCK*/ if (events & POLLERR) FD_SET(n, &_fdsets[2]); + /*LOCK*/ if (n > _maxfd) _maxfd = n; + DataUnlock(); +} + +// Remove an FD from the array +void DataReady::RemoveFD(int n, int events) +{ + int i,j; + for (i=j=0; i<nfds; i++) + { + if (fds[i].fd == n) + { + int e = fds[i].events & ~events; + if (!e) continue; // if no events left, delete this fd + fds[i].events = e; + } + // move it down in the array if necessary: + if (j<i) + { fds[j] = fds[i]; } + j++; + } + nfds = j; + DataLock(); + /*LOCK*/ if (events & POLLIN) FD_CLR(n, &_fdsets[0]); + /*LOCK*/ if (events & POLLOUT) FD_CLR(n, &_fdsets[1]); + /*LOCK*/ if (events & POLLERR) FD_CLR(n, &_fdsets[2]); + /*LOCK*/ if (n == _maxfd) _maxfd--; + DataUnlock(); +} + +// CHECK IF USER DATA READY, RETURNS r/w/x INDICATING WHICH IF ANY +int DataReady::CheckData(fd_set& r, fd_set& w, fd_set& x) +{ + int ret; + DataLock(); + /*LOCK*/ timeval t = { 0, 1 }; // quick check + /*LOCK*/ r = _fdsets[0], w = _fdsets[1], x = _fdsets[2]; + /*LOCK*/ ret = ::select(_maxfd+1, &r, &w, &x, &t); + DataUnlock(); + if ( ret == -1 ) + { DEBUGPERRORMSG("CheckData(): select()"); } + return(ret); +} + +// HANDLE DATA READY CALLBACKS +void DataReady::HandleData(fd_set& r, fd_set& w, fd_set& x) +{ + for (int i=0; i<nfds; i++) + { + int f = fds[i].fd; + short revents = 0; + if (FD_ISSET(f, &r)) revents |= POLLIN; + if (FD_ISSET(f, &w)) revents |= POLLOUT; + if (FD_ISSET(f, &x)) revents |= POLLERR; + if (fds[i].events & revents) + { + DEBUGMSG("DOING CALLBACK: "); + fds[i].cb(f, fds[i].arg); + DEBUGMSG("DONE\n"); + } + } +} + +// DATA READY THREAD +// This thread watches for changes in user's file descriptors. +// Sends a 'data ready event' to the main thread if any change. +// +void* DataReady::DataReadyThread(void *o) +{ + DataReady *self = (DataReady*)o; + while ( 1 ) // loop until thread cancel or error + { + // Thread safe local copies of data before each select() + self->DataLock(); + /*LOCK*/ int maxfd = self->_maxfd; + /*LOCK*/ fd_set r = self->GetFdset(0); + /*LOCK*/ fd_set w = self->GetFdset(1); + /*LOCK*/ fd_set x = self->GetFdset(2); + /*LOCK*/ void *userdata = self->_userdata; + /*LOCK*/ int cancelpipe = self->GetCancelPipe(0); + /*LOCK*/ if ( cancelpipe > maxfd ) maxfd = cancelpipe; + /*LOCK*/ FD_SET(cancelpipe, &r); // add cancelpipe to fd's to watch + /*LOCK*/ FD_SET(cancelpipe, &x); + self->DataUnlock(); + // timeval t = { 1000, 0 }; // 1000 seconds; + timeval t = { 2, 0 }; // HACK: 2 secs prevents 'hanging' problem + int ret = ::select(maxfd+1, &r, &w, &x, &t); + pthread_testcancel(); // OSX 10.0.4 and older: needed for parent to cancel + switch ( ret ) + { + case 0: // NO DATA + continue; + case -1: // ERROR + { + DEBUGPERRORMSG("CHILD THREAD: select() failed"); + return(NULL); // error? exit thread + } + default: // DATA READY + { + if (FD_ISSET(cancelpipe, &r) || FD_ISSET(cancelpipe, &x)) // cancel? + { return(NULL); } // just exit + DEBUGMSG("CHILD THREAD: DATA IS READY\n"); + EventRef drEvent; + CreateEvent( 0, kEventClassFLTK, kEventFLTKDataReady, + 0, kEventAttributeUserEvent, &drEvent); + EventQueueRef eventqueue = (EventQueueRef)userdata; + PostEventToQueue(eventqueue, drEvent, kEventPriorityStandard ); + ReleaseEvent( drEvent ); + return(NULL); // done with thread + } + } + } +} + +// START 'DATA READY' THREAD RUNNING, CREATE INTER-THREAD PIPE +void DataReady::StartThread(void *new_userdata) +{ + CancelThread(DEBUGTEXT("STARTING NEW THREAD\n")); + DataLock(); + /*LOCK*/ pipe(_cancelpipe); // pipe for sending cancel msg to thread + /*LOCK*/ _userdata = new_userdata; + DataUnlock(); + DEBUGMSG("*** START THREAD\n"); + pthread_create(&tid, NULL, DataReadyThread, (void*)this); +} + +// CANCEL 'DATA READY' THREAD, CLOSE PIPE +void DataReady::CancelThread(const char *reason) +{ + if ( tid ) + { + DEBUGMSG("*** CANCEL THREAD: "); + DEBUGMSG(reason); + if ( pthread_cancel(tid) == 0 ) // cancel first + { + DataLock(); + /*LOCK*/ write(_cancelpipe[1], "x", 1); // wake thread from select + DataUnlock(); + pthread_join(tid, NULL); // wait for thread to finish + } + tid = 0; + DEBUGMSG("(JOINED) OK\n"); + } + // Close pipe if open + DataLock(); + /*LOCK*/ if ( _cancelpipe[0] ) { close(_cancelpipe[0]); _cancelpipe[0] = 0; } + /*LOCK*/ if ( _cancelpipe[1] ) { close(_cancelpipe[1]); _cancelpipe[1] = 0; } + DataUnlock(); +} + +void Fl::add_fd( int n, int events, void (*cb)(int, void*), void *v ) + { dataready.AddFD(n, events, cb, v); } + +void Fl::add_fd(int fd, void (*cb)(int, void*), void* v) + { dataready.AddFD(fd, POLLIN, cb, v); } + +void Fl::remove_fd(int n, int events) + { dataready.RemoveFD(n, events); } + +void Fl::remove_fd(int n) + { dataready.RemoveFD(n, -1); } + +/** + * Check if there is actually a message pending! + */ +int fl_ready() +{ + EventRef event; + return !ReceiveNextEvent(0, NULL, 0.0, false, &event); +} + +/** + * handle Apple Menu items (can be created using the Fl_Sys_Menu_Bar + * returns eventNotHandledErr if the menu item could not be handled + */ +OSStatus HandleMenu( HICommand *cmd ) +{ + OSStatus ret = eventNotHandledErr; + // attributes, commandIDm menu.menuRef, menu.menuItemIndex + UInt32 ref; + OSErr rrc = GetMenuItemRefCon( cmd->menu.menuRef, cmd->menu.menuItemIndex, &ref ); + //printf( "%d, %08x, %08x, %d, %d, %8x\n", rrc, cmd->attributes, cmd->commandID, cmd->menu.menuRef, cmd->menu.menuItemIndex, rrc ); + if ( rrc==noErr && ref ) + { + Fl_Menu_Item *m = (Fl_Menu_Item*)ref; + //printf( "Menu: %s\n", m->label() ); + fl_sys_menu_bar->picked( m ); + if ( m->flags & FL_MENU_TOGGLE ) // update the menu toggle symbol + SetItemMark( cmd->menu.menuRef, cmd->menu.menuItemIndex, (m->flags & FL_MENU_VALUE ) ? 0x12 : 0 ); + if ( m->flags & FL_MENU_RADIO ) // update all radio buttons in this menu + { + Fl_Menu_Item *j = m; + int i = cmd->menu.menuItemIndex; + for (;;) + { + if ( j->flags & FL_MENU_DIVIDER ) + break; + j++; i++; + if ( !j->text || !j->radio() ) + break; + SetItemMark( cmd->menu.menuRef, i, ( j->flags & FL_MENU_VALUE ) ? 0x13 : 0 ); + } + j = m-1; i = cmd->menu.menuItemIndex-1; + for ( ; i>0; j--, i-- ) + { + if ( !j->text || j->flags&FL_MENU_DIVIDER || !j->radio() ) + break; + SetItemMark( cmd->menu.menuRef, i, ( j->flags & FL_MENU_VALUE ) ? 0x13 : 0 ); + } + SetItemMark( cmd->menu.menuRef, cmd->menu.menuItemIndex, ( m->flags & FL_MENU_VALUE ) ? 0x13 : 0 ); + } + ret = noErr; // done handling this event + } + HiliteMenu(0); + return ret; +} + + +/** + * We can make every event pass through this function + * - mouse events need to be manipulated to use a mouse focus window + * - keyboard, mouse and some window events need to quit the Apple Event Loop + * so FLTK can continue its own management + */ +static pascal OSStatus carbonDispatchHandler( EventHandlerCallRef nextHandler, EventRef event, void *userData ) +{ + OSStatus ret = eventNotHandledErr; + HICommand cmd; + + fl_lock_function(); + + got_events = 1; + + switch ( GetEventClass( event ) ) + { + case kEventClassMouse: + switch ( GetEventKind( event ) ) + { + case kEventMouseUp: + case kEventMouseMoved: + case kEventMouseDragged: + if ( fl_capture ) + ret = SendEventToEventTarget( event, GetWindowEventTarget( fl_capture ) ); + else if ( fl_os_capture ){ + ret = SendEventToEventTarget( event, GetWindowEventTarget( fl_os_capture ) ); + fl_os_capture = 0; + } + break; + } + break; + case kEventClassCommand: + switch (GetEventKind( event ) ) + { + case kEventCommandProcess: + GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd ); + ret = HandleMenu( &cmd ); + break; + } + break; + case kEventClassFLTK: + switch ( GetEventKind( event ) ) + { + case kEventFLTKBreakLoop: + ret = noErr; + break; + case kEventFLTKDataReady: + { + dataready.CancelThread(DEBUGTEXT("DATA READY EVENT\n")); + + // CHILD THREAD TELLS US DATA READY + // Check to see what's ready, and invoke user's cb's + // + fd_set r,w,x; + switch(dataready.CheckData(r,w,x)) + { + case 0: // NO DATA + break; + case -1: // ERROR + break; + default: // DATA READY + dataready.HandleData(r,w,x); + break; + } + } + ret = noErr; + break; + } + } + if ( ret == eventNotHandledErr ) + ret = CallNextEventHandler( nextHandler, event ); // let the OS handle the activation, but continue to get a click-through effect + + fl_unlock_function(); + + return ret; +} + + +/** + * break the current event loop + */ +static void breakMacEventLoop() +{ + EventRef breakEvent; + + fl_lock_function(); + + CreateEvent( 0, kEventClassFLTK, kEventFLTKBreakLoop, 0, kEventAttributeUserEvent, &breakEvent ); + PostEventToQueue( GetCurrentEventQueue(), breakEvent, kEventPriorityStandard ); + ReleaseEvent( breakEvent ); + + fl_unlock_function(); +} + +// +// MacOS X timers +// + +struct MacTimeout { + Fl_Timeout_Handler callback; + void* data; + EventLoopTimerRef timer; +}; +static MacTimeout* mac_timers; +static int mac_timer_alloc; +static int mac_timer_used; + + +static void realloc_timers() +{ + if (mac_timer_alloc == 0) { + mac_timer_alloc = 8; + } + MacTimeout* new_timers = new MacTimeout[mac_timer_alloc * 2]; + memmove(new_timers, mac_timers, sizeof(MacTimeout) * mac_timer_used); + MacTimeout* delete_me = mac_timers; + mac_timers = new_timers; + delete [] delete_me; + mac_timer_alloc *= 2; +} + +static void delete_timer(MacTimeout& t) +{ + RemoveEventLoopTimer(t.timer); + memset(&t, 0, sizeof(MacTimeout)); +} + + +static pascal void do_timer(EventLoopTimerRef timer, void* data) +{ + for (int i = 0; i < mac_timer_used; ++i) { + MacTimeout& t = mac_timers[i]; + if (t.timer == timer && t.data == data) { + (*t.callback)(data); + break; + } + } + breakMacEventLoop(); +} + +/** + * This function is the central event handler. + * It reads events from the event queue using the given maximum time + * Funny enough, it returns the same time that it got as the argument. + */ +static double do_queued_events( double time = 0.0 ) +{ + static bool been_here = 0; + static RgnHandle rgn; + + // initialize events and a region that enables mouse move events + if (!been_here) { + rgn = NewRgn(); + Point mp; + GetMouse(&mp); + SetRectRgn(rgn, mp.h, mp.v, mp.h, mp.v); + SetEventMask(everyEvent); + been_here = 1; + } + OSStatus ret; + static EventTargetRef target = 0; + if ( !target ) + { + target = GetEventDispatcherTarget(); + + EventHandlerUPP dispatchHandler = NewEventHandlerUPP( carbonDispatchHandler ); // will not be disposed by Carbon... + static EventTypeSpec dispatchEvents[] = { + { kEventClassWindow, kEventWindowShown }, + { kEventClassWindow, kEventWindowHidden }, + { kEventClassWindow, kEventWindowActivated }, + { kEventClassWindow, kEventWindowDeactivated }, + { kEventClassWindow, kEventWindowClose }, + { kEventClassKeyboard, kEventRawKeyDown }, + { kEventClassKeyboard, kEventRawKeyRepeat }, + { kEventClassKeyboard, kEventRawKeyUp }, + { kEventClassKeyboard, kEventRawKeyModifiersChanged }, + { kEventClassMouse, kEventMouseDown }, + { kEventClassMouse, kEventMouseUp }, + { kEventClassMouse, kEventMouseMoved }, + { kEventClassMouse, 11 }, // MightyMouse wheels + { kEventClassMouse, kEventMouseWheelMoved }, + { kEventClassMouse, kEventMouseDragged }, + { kEventClassFLTK, kEventFLTKBreakLoop }, + { kEventClassFLTK, kEventFLTKDataReady } }; + ret = InstallEventHandler( target, dispatchHandler, GetEventTypeCount(dispatchEvents), dispatchEvents, 0, 0L ); + static EventTypeSpec appEvents[] = { + { kEventClassCommand, kEventCommandProcess } }; + ret = InstallApplicationEventHandler( dispatchHandler, GetEventTypeCount(appEvents), appEvents, 0, 0L ); + } + + got_events = 0; + + // Check for re-entrant condition + if ( dataready.IsThreadRunning() ) + { dataready.CancelThread(DEBUGTEXT("AVOID REENTRY\n")); } + + // Start thread to watch for data ready + if ( dataready.GetNfds() ) + { dataready.StartThread((void*)GetCurrentEventQueue()); } + + fl_unlock_function(); + + EventRef event; + EventTimeout timeout = time; + if (!ReceiveNextEvent(0, NULL, timeout, true, &event)) { + got_events = 1; + OSErr ret = SendEventToEventTarget( event, target ); + if (ret!=noErr) { + EventRecord clevent; + ConvertEventRefToEventRecord(event, &clevent); + if (clevent.what==kHighLevelEvent) { + ret = AEProcessAppleEvent(&clevent); + } + } + if ( ret==eventNotHandledErr + && GetEventClass(event)==kEventClassMouse + && GetEventKind(event)==kEventMouseDown ) { + WindowRef win; Point pos; + GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, + NULL, sizeof(pos), NULL, &pos); + if (MacFindWindow(pos, &win)==inMenuBar) { + MenuSelect(pos); + } + } + ReleaseEvent( event ); + } + + fl_lock_function(); + +#if CONSOLIDATE_MOTION + if (send_motion && send_motion == fl_xmousewin) { + send_motion = 0; + Fl::handle(FL_MOVE, fl_xmousewin); + } +#endif + + return time; +} + + +/** + * This public function handles all events. It wait a maximum of + * 'time' secods for an event. This version returns 1 if events + * other than the timeout timer were processed. + * + * \todo there is no socket handling in this code whatsoever + */ +int fl_wait( double time ) +{ + do_queued_events( time ); + return (got_events); +} + + +/** + * event handler for Apple-Q key combination + * this is also called from the Carbon Window handler after all windows were closed + */ +static OSErr QuitAppleEventHandler( const AppleEvent *appleEvt, AppleEvent* reply, UInt32 refcon ) +{ + fl_lock_function(); + + while ( Fl_X::first ) { + Fl_X *x = Fl_X::first; + Fl::handle( FL_CLOSE, x->w ); + if ( Fl_X::first == x ) { + fl_unlock_function(); + return noErr; // FLTK has not close all windows, so we return to the main program now + } + } + + fl_unlock_function(); + + return noErr; +} + + +/** + * Carbon Window handler + * This needs to be linked into all new window event handlers + */ +static pascal OSStatus carbonWindowHandler( EventHandlerCallRef nextHandler, EventRef event, void *userData ) +{ + UInt32 kind = GetEventKind( event ); + OSStatus ret = eventNotHandledErr; + Fl_Window *window = (Fl_Window*)userData; + + Rect currentBounds, originalBounds; + WindowClass winClass; + static Fl_Window *activeWindow = 0; + + fl_lock_function(); + + switch ( kind ) + { + case kEventWindowBoundsChanging: + GetEventParameter( event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, ¤tBounds ); + GetEventParameter( event, kEventParamOriginalBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &originalBounds ); + break; + case kEventWindowDrawContent: + handleUpdateEvent( fl_xid( window ) ); + ret = noErr; + break; + case kEventWindowBoundsChanged: { + GetEventParameter( event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, ¤tBounds ); + GetEventParameter( event, kEventParamOriginalBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &originalBounds ); + int X = currentBounds.left, W = currentBounds.right-X; + int Y = currentBounds.top, H = currentBounds.bottom-Y; + resize_from_system = window; + window->resize( X, Y, W, H ); + if ( ( originalBounds.right - originalBounds.left != W ) + || ( originalBounds.bottom - originalBounds.top != H ) ) + { + if ( window->shown() ) + handleUpdateEvent( fl_xid( window ) ); + } + break; } + case kEventWindowShown: + if ( !window->parent() ) + { + GetWindowClass( fl_xid( window ), &winClass ); + if ( winClass != kHelpWindowClass ) { // help windows can't get the focus! + Fl::handle( FL_FOCUS, window); + activeWindow = window; + } + Fl::handle( FL_SHOW, window); + mods_to_e_state(GetCurrentKeyModifiers()); + } + break; + case kEventWindowHidden: + if ( !window->parent() ) Fl::handle( FL_HIDE, window); + break; + case kEventWindowActivated: + if ( window!=activeWindow ) + { + GetWindowClass( fl_xid( window ), &winClass ); + if ( winClass != kHelpWindowClass ) { // help windows can't get the focus! + Fl::handle( FL_FOCUS, window); + activeWindow = window; + } + } + break; + case kEventWindowDeactivated: + if ( window==activeWindow ) + { + Fl::handle( FL_UNFOCUS, window); + activeWindow = 0; + } + break; + case kEventWindowClose: + Fl::handle( FL_CLOSE, window ); // this might or might not close the window + // if there are no more windows, send a high-level quit event + if (!Fl_X::first) QuitAppleEventHandler( 0, 0, 0 ); + ret = noErr; // returning noErr tells Carbon to stop following up on this event + break; + } + + fl_unlock_function(); + + return ret; +} + + +/** + * Carbon Mousewheel handler + * This needs to be linked into all new window event handlers + */ +static pascal OSStatus carbonMousewheelHandler( EventHandlerCallRef nextHandler, EventRef event, void *userData ) +{ + // Handle the new "MightyMouse" mouse wheel events. Please, someone explain + // to me why Apple changed the API on this even though the current API + // supports two wheels just fine. Matthias, + fl_lock_function(); + + fl_os_event = event; + Fl_Window *window = (Fl_Window*)userData; + + EventMouseWheelAxis axis; + GetEventParameter( event, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof(EventMouseWheelAxis), NULL, &axis ); + long delta; + GetEventParameter( event, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(long), NULL, &delta ); +// fprintf(stderr, "axis=%d, delta=%d\n", axis, delta); + if ( axis == kEventMouseWheelAxisX ) { + Fl::e_dx = -delta; + Fl::e_dy = 0; + if ( Fl::e_dx) Fl::handle( FL_MOUSEWHEEL, window ); + } else if ( axis == kEventMouseWheelAxisY ) { + Fl::e_dx = 0; + Fl::e_dy = -delta; + if ( Fl::e_dy) Fl::handle( FL_MOUSEWHEEL, window ); + } else { + fl_unlock_function(); + + return eventNotHandledErr; + } + + fl_unlock_function(); + + return noErr; +} + + +/** + * convert the current mouse chord into the FLTK modifier state + */ +static void chord_to_e_state( UInt32 chord ) +{ + static ulong state[] = + { + 0, FL_BUTTON1, FL_BUTTON3, FL_BUTTON1|FL_BUTTON3, FL_BUTTON2, + FL_BUTTON2|FL_BUTTON1, FL_BUTTON2|FL_BUTTON3, + FL_BUTTON2|FL_BUTTON1|FL_BUTTON3 + }; + Fl::e_state = ( Fl::e_state & 0xff0000 ) | state[ chord & 0x07 ]; +} + + +/** + * Carbon Mouse Button Handler + */ +static pascal OSStatus carbonMouseHandler( EventHandlerCallRef nextHandler, EventRef event, void *userData ) +{ + static int keysym[] = { 0, FL_Button+1, FL_Button+3, FL_Button+2 }; + static int px, py; + + fl_lock_function(); + + fl_os_event = event; + Fl_Window *window = (Fl_Window*)userData; + Point pos; + GetEventParameter( event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &pos ); + EventMouseButton btn; + GetEventParameter( event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(EventMouseButton), NULL, &btn ); + UInt32 clickCount; + GetEventParameter( event, kEventParamClickCount, typeUInt32, NULL, sizeof(UInt32), NULL, &clickCount ); + UInt32 chord; + GetEventParameter( event, kEventParamMouseChord, typeUInt32, NULL, sizeof(UInt32), NULL, &chord ); + WindowRef xid = fl_xid(window), tempXid; + int sendEvent = 0, part; + switch ( GetEventKind( event ) ) + { + case kEventMouseDown: + part = FindWindow( pos, &tempXid ); + if ( part != inContent ) { + fl_unlock_function(); + return CallNextEventHandler( nextHandler, event ); // let the OS handle this for us + } + if ( !IsWindowActive( xid ) ) + CallNextEventHandler( nextHandler, event ); // let the OS handle the activation, but continue to get a click-through effect + // normal handling of mouse-down follows + fl_os_capture = xid; + sendEvent = FL_PUSH; + Fl::e_is_click = 1; px = pos.h; py = pos.v; + if (clickCount>1) + Fl::e_clicks++; + else + Fl::e_clicks = 0; + // fall through + case kEventMouseUp: + if ( !window ) break; + if ( !sendEvent ) { + sendEvent = FL_RELEASE; + } + Fl::e_keysym = keysym[ btn ]; + // fall through + case kEventMouseMoved: + if ( !sendEvent ) { + sendEvent = FL_MOVE; chord = 0; + } + // fall through + case kEventMouseDragged: + if ( !sendEvent ) { + sendEvent = FL_MOVE; // Fl::handle will convert into FL_DRAG + if (abs(pos.h-px)>5 || abs(pos.v-py)>5) + Fl::e_is_click = 0; + } + chord_to_e_state( chord ); + GrafPtr oldPort; + GetPort( &oldPort ); + SetPort( GetWindowPort(xid) ); // \todo replace this! There must be some GlobalToLocal call that has a port as an argument + SetOrigin(0, 0); + Fl::e_x_root = pos.h; + Fl::e_y_root = pos.v; + GlobalToLocal( &pos ); + Fl::e_x = pos.h; + Fl::e_y = pos.v; + SetPort( oldPort ); + Fl::handle( sendEvent, window ); + break; + } + + fl_unlock_function(); + + return noErr; +} + + +/** + * convert the keyboard return code into the symbol on the keycaps + */ +static unsigned short keycode_to_sym( UInt32 keyCode, UInt32 mods, unsigned short deflt ) +{ + static Ptr map = 0; + UInt32 state = 0; + if (!map) { + map = (Ptr)GetScriptManagerVariable(smKCHRCache); + if (!map) { + long kbID = GetScriptManagerVariable(smKeyScript); + map = *GetResource('KCHR', kbID); + } + } + if (map) + return KeyTranslate(map, keyCode|mods, &state ); + return deflt; +} + +/** + * handle carbon keyboard events + */ +pascal OSStatus carbonKeyboardHandler( + EventHandlerCallRef nextHandler, EventRef event, void *userData ) +{ + static char buffer[5]; + int sendEvent = 0; + Fl_Window *window = (Fl_Window*)userData; + UInt32 mods; + static UInt32 prevMods = 0xffffffff; + + fl_lock_function(); + + int kind = GetEventKind(event); + + // get the modifiers for any of the events + GetEventParameter( event, kEventParamKeyModifiers, typeUInt32, + NULL, sizeof(UInt32), NULL, &mods ); + if ( prevMods == 0xffffffff ) prevMods = mods; + + // get the key code only for key events + UInt32 keyCode = 0; + unsigned char key = 0; + unsigned short sym = 0; + if (kind!=kEventRawKeyModifiersChanged) { + GetEventParameter( event, kEventParamKeyCode, typeUInt32, + NULL, sizeof(UInt32), NULL, &keyCode ); + GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar, + NULL, sizeof(char), NULL, &key ); + } + /* output a human readbale event identifier for debugging + const char *ev = ""; + switch (kind) { + case kEventRawKeyDown: ev = "kEventRawKeyDown"; break; + case kEventRawKeyRepeat: ev = "kEventRawKeyRepeat"; break; + case kEventRawKeyUp: ev = "kEventRawKeyUp"; break; + case kEventRawKeyModifiersChanged: ev = "kEventRawKeyModifiersChanged"; break; + default: ev = "unknown"; + } + printf("%08x %08x %08x '%c' %s \n", mods, keyCode, key, key, ev); + */ + switch (kind) + { + case kEventRawKeyDown: + case kEventRawKeyRepeat: + sendEvent = FL_KEYBOARD; + // fall through + case kEventRawKeyUp: + if ( !sendEvent ) sendEvent = FL_KEYUP; + // if the user pressed alt/option, event_key should have the keycap, + // but event_text should generate the international symbol + if ( isalpha(key) ) + sym = tolower(key); + else if ( Fl::e_state&FL_CTRL && key<32 ) + sym = key+96; + else if ( Fl::e_state&FL_ALT ) // find the keycap of this key + sym = keycode_to_sym( keyCode & 0x7f, 0, macKeyLookUp[ keyCode & 0x7f ] ); + else + sym = macKeyLookUp[ keyCode & 0x7f ]; + Fl::e_keysym = sym; + if ( keyCode==0x4c ) key=0x0d; + // Matt: the Mac has no concept of a NumLock key, or at least not visible + // Matt: to Carbon. The kEventKeyModifierNumLockMask is only set when + // Matt: a numeric keypad key is pressed and does not correspond with + // Matt: the NumLock light in PowerBook keyboards. + if ( (sym >= FL_KP && sym <= FL_KP_Last) || !(sym & 0xff00) || + sym == FL_Tab || sym == FL_Enter) { + buffer[0] = key; + Fl::e_length = 1; + } else { + buffer[0] = 0; + Fl::e_length = 0; + } + Fl::e_text = buffer; + // insert UnicodeHandling here! + break; + case kEventRawKeyModifiersChanged: { + UInt32 tMods = prevMods ^ mods; + if ( tMods ) + { + mods_to_e_keysym( tMods ); + if ( Fl::e_keysym ) + sendEvent = ( prevMods<mods ) ? FL_KEYBOARD : FL_KEYUP; + Fl::e_length = 0; + buffer[0] = 0; + prevMods = mods; + } + mods_to_e_state( mods ); + break; } + } + while (window->parent()) window = window->window(); + if (sendEvent && Fl::handle(sendEvent,window)) { + fl_unlock_function(); + return noErr; // return noErr if FLTK handled the event + } else { + fl_unlock_function(); + //return CallNextEventHandler( nextHandler, event );; + // Matt: I had better results (no duplicate events) always returning + // Matt: 'noErr'. System keyboard events still seem to work just fine. + return noErr; + } +} + + + +/** + * Open callback function to call... + */ + +static void (*open_cb)(const char *) = 0; + + +/** + * Event handler for Apple-O key combination and also for file opens + * via the finder... + */ + +static OSErr OpenAppleEventHandler(const AppleEvent *appleEvt, + AppleEvent *reply, + UInt32 refcon) { + OSErr err; + AEDescList documents; + long i, n; + FSSpec fileSpec; + AEKeyword keyWd; + DescType typeCd; + Size actSz; + char filename[1024]; + + if (!open_cb) return noErr; + + // Initialize the document list... + AECreateDesc(typeNull, NULL, 0, &documents); + + // Get the open parameter(s)... + err = AEGetParamDesc(appleEvt, keyDirectObject, typeAEList, &documents); + if (err != noErr) { + AEDisposeDesc(&documents); + return err; + } + + // Lock access to FLTK in this thread... + fl_lock_function(); + + // Open the documents via the callback... + if (AECountItems(&documents, &n) == noErr) { + for (i = 1; i <= n; i ++) { + // Get the next FSSpec record... + AEGetNthPtr(&documents, i, typeFSS, &keyWd, &typeCd, + (Ptr)&fileSpec, sizeof(fileSpec), + (actSz = sizeof(fileSpec), &actSz)); + + // Convert to a UNIX path... + FSSpec2UnixPath(&fileSpec, filename); + + // Call the callback with the filename... + (*open_cb)(filename); + } + } + + // Unlock access to FLTK for all threads... + fl_unlock_function(); + + // Get rid of the document list... + AEDisposeDesc(&documents); + + return noErr; +} + + +/** + * Install an open documents event handler... + */ + +void fl_open_callback(void (*cb)(const char *)) { + open_cb = cb; + if (cb) { + AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, + NewAEEventHandlerUPP((AEEventHandlerProcPtr) + OpenAppleEventHandler), 0, false); + } else { + AERemoveEventHandler(kCoreEventClass, kAEOpenDocuments, + NewAEEventHandlerUPP((AEEventHandlerProcPtr) + OpenAppleEventHandler), false); + } +} + + +/** + * initialize the Mac toolboxes and set the default menubar + */ +void fl_open_display() { + static char beenHereDoneThat = 0; + if ( !beenHereDoneThat ) { + beenHereDoneThat = 1; + + FlushEvents(everyEvent,0); + + MoreMasters(); // \todo Carbon suggests MoreMasterPointers() + AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP((AEEventHandlerProcPtr)QuitAppleEventHandler), 0, false ); + + // create the Mac Handle for the default cursor (a pointer to a pointer) + GetQDGlobalsArrow(&default_cursor); + default_cursor_ptr = &default_cursor; + fl_default_cursor = &default_cursor_ptr; + + ClearMenuBar(); + AppendResMenu( GetMenuHandle( 1 ), 'DRVR' ); + DrawMenuBar(); + } +} + + +/** + * get rid of allocated resources + */ +void fl_close_display() { +} + + +/** + * smallest x ccordinate in screen space + */ +int Fl::x() { + BitMap r; + GetQDGlobalsScreenBits(&r); + return r.bounds.left; +} + + +/** + * smallest y ccordinate in screen space + */ +int Fl::y() { + BitMap r; + GetQDGlobalsScreenBits(&r); + return r.bounds.top + 20; // \todo 20 pixel menu bar? +} + + +/** + * screen width (single monitor!?) + */ +int Fl::w() { + BitMap r; + GetQDGlobalsScreenBits(&r); + return r.bounds.right - r.bounds.left; +} + + +/** + * screen height (single monitor!?) + */ +int Fl::h() { + BitMap r; + GetQDGlobalsScreenBits(&r); + return r.bounds.bottom - r.bounds.top - 20; +} + + +/** + * get the current mouse pointer world coordinates + */ +void Fl::get_mouse(int &x, int &y) +{ + fl_open_display(); + Point loc; + GetMouse( &loc ); + LocalToGlobal( &loc ); + x = loc.h; + y = loc.v; +} + + +/** + * convert Mac keystrokes to FLTK + */ +unsigned short mac2fltk(ulong macKey) +{ + unsigned short cc = macKeyLookUp[(macKey>>8)&0x7f]; + if (cc) return cc; + return macKey&0xff; +} + + +/** + * Initialize the given port for redraw and call the windw's flush() to actually draw the content + */ +void Fl_X::flush() +{ + w->flush(); +#ifdef __APPLE_QD__ + GrafPtr port; + GetPort( &port ); + if ( port ) + QDFlushPortBuffer( port, 0 ); +#elif defined (__APPLE_QUARTZ__) + if (fl_gc) + CGContextFlush(fl_gc); +#endif + SetOrigin( 0, 0 ); +} + + +/** + * Handle all clipping and redraw for the given port + * There are two different callers for this event: + * 1: the OS can request a redraw and provides all clipping itself + * 2: Fl::flush() wants all redraws now + */ +void handleUpdateEvent( WindowPtr xid ) +{ + Fl_Window *window = fl_find( xid ); + if ( !window ) return; + GrafPtr oldPort; + GetPort( &oldPort ); + SetPort( GetWindowPort(xid) ); + Fl_X *i = Fl_X::i( window ); + i->wait_for_expose = 0; + if ( window->damage() ) { + if ( i->region ) { + InvalWindowRgn( xid, i->region ); + } + } + if ( i->region ) { // no region, so the sytem will take the update region from the OS + DisposeRgn( i->region ); + i->region = 0; + } + for ( Fl_X *cx = i->xidChildren; cx; cx = cx->xidNext ) + { + cx->w->clear_damage(window->damage()|FL_DAMAGE_EXPOSE); + cx->flush(); + cx->w->clear_damage(); + } + window->clear_damage(window->damage()|FL_DAMAGE_EXPOSE); + i->flush(); + window->clear_damage(); + SetPort( oldPort ); +} + + +/** + * \todo this is a leftover from OS9 times. Please check how much applies to Carbon! + */ +int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) { + int W, H, xoff, yoff, dx, dy; + int ret = bx = by = bt = 0; + if (w->border() && !w->parent()) { + if (w->maxw != w->minw || w->maxh != w->minh) { + ret = 2; + bx = 6; // \todo Mac : GetSystemMetrics(SM_CXSIZEFRAME); + by = 6; // \todo Mac : get Mac window frame size GetSystemMetrics(SM_CYSIZEFRAME); + } else { + ret = 1; + bx = 6; // \todo Mac : GetSystemMetrics(SM_CXFIXEDFRAME); + by = 6; // \todo Mac : GetSystemMetrics(SM_CYFIXEDFRAME); + } + bt = 22; // \todo Mac : GetSystemMetrics(SM_CYCAPTION); + } + //The coordinates of the whole window, including non-client area + xoff = bx; + yoff = by + bt; + dx = 2*bx; + dy = 2*by + bt; + X = w->x()-xoff; + Y = w->y()-yoff; + W = w->w()+dx; + H = w->h()+dy; + + //Proceed to positioning the window fully inside the screen, if possible + + // let's get a little elaborate here. Mac OS X puts a lot of stuff on the desk + // that we want to avoid when positioning our window, namely the Dock and the + // top menu bar (and even more stuff in 10.4 Tiger). So we will go through the + // list of all available screens and find the one that this window is most + // likely to go to, and then reposition it to fit withing the 'good' area. + Rect r; + // find the screen, that the center of this window will fall into + int R = X+W, B = Y+H; // right and bottom + int cx = (X+R)/2, cy = (Y+B)/2; // center of window; + GDHandle gd = 0L; + for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) { + GDPtr gp = *gd; + if ( cx >= gp->gdRect.left && cx <= gp->gdRect.right + && cy >= gp->gdRect.top && cy <= gp->gdRect.bottom) + break; + } + // if the center doesn't fall on a screen, try the top left + if (!gd) { + for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) { + GDPtr gp = *gd; + if ( X >= gp->gdRect.left && X <= gp->gdRect.right + && Y >= gp->gdRect.top && Y <= gp->gdRect.bottom) + break; + } + } + // if that doesn't fall on a screen, try the top right + if (!gd) { + for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) { + GDPtr gp = *gd; + if ( R >= gp->gdRect.left && R <= gp->gdRect.right + && Y >= gp->gdRect.top && Y <= gp->gdRect.bottom) + break; + } + } + // if that doesn't fall on a screen, try the bottom left + if (!gd) { + for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) { + GDPtr gp = *gd; + if ( X >= gp->gdRect.left && X <= gp->gdRect.right + && B >= gp->gdRect.top && B <= gp->gdRect.bottom) + break; + } + } + // last resort, try the bottom right + if (!gd) { + for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) { + GDPtr gp = *gd; + if ( R >= gp->gdRect.left && R <= gp->gdRect.right + && B >= gp->gdRect.top && B <= gp->gdRect.bottom) + break; + } + } + // if we still have not found a screen, we will use the main + // screen, the one that has the application menu bar. + if (!gd) gd = GetMainDevice(); + if (gd) { + GetAvailableWindowPositioningBounds(gd, &r); + if ( R > r.right ) X -= R - r.right; + if ( B > r.bottom ) Y -= B - r.bottom; + if ( X < r.left ) X = r.left; + if ( Y < r.top ) Y = r.top; + } + + //Return the client area's top left corner in (X,Y) + X+=xoff; + Y+=yoff; + + return ret; +} + +/** + * convert a Mac FSSpec structure into a Unix filename + */ +static int FSSpec2UnixPath( FSSpec *fs, char *dst ) +{ + FSRef fsRef; + FSpMakeFSRef( fs, &fsRef ); + FSRefMakePath( &fsRef, (UInt8*)dst, 1024 ); + return strlen(dst); +} + +static DragReference currDragRef = 0; +static char *currDragData = 0L; +static int currDragSize = 0; +static OSErr currDragErr = noErr; +Fl_Window *fl_dnd_target_window = 0; +#include <FL/fl_draw.H> + +/** + * Fill the currDrag* variables with the current DnD ASCII text. + */ +static OSErr fillCurrentDragData(DragReference dragRef) +{ + OSErr ret = noErr; + char *dst = 0L; + + // shortcut through this whole procedure if this is still the same drag event + if (dragRef==currDragRef) + return currDragErr; + + // clear currDrag* for a new drag event + currDragRef = dragRef; + if (currDragData) free(currDragData); + currDragData = 0; + currDragSize = 0; + + // fill currDRag* with ASCII data, if available + UInt16 i, nItem; + ItemReference itemRef; + FlavorFlags flags; + Size itemSize, size = 0; + CountDragItems( dragRef, &nItem ); + for ( i = 1; i <= nItem; i++ ) + { + GetDragItemReferenceNumber( dragRef, i, &itemRef ); + ret = GetFlavorFlags( dragRef, itemRef, 'TEXT', &flags ); + if ( ret == noErr ) + { + GetFlavorDataSize( dragRef, itemRef, 'TEXT', &itemSize ); + size += itemSize; + } + ret = GetFlavorFlags( dragRef, itemRef, 'hfs ', &flags ); + if ( ret == noErr ) + { + size += 1024; //++ ouch! We should create the full pathname and figure out its length + } + } + + if ( !size ) + { + currDragErr = userCanceledErr; + return currDragErr; + } + + currDragSize = size + nItem - 1; + currDragData = dst = (char*)malloc( size+nItem );; + + for ( i = 1; i <= nItem; i++ ) + { + GetDragItemReferenceNumber( dragRef, i, &itemRef ); + ret = GetFlavorFlags( dragRef, itemRef, 'TEXT', &flags ); + if ( ret == noErr ) + { + GetFlavorDataSize( dragRef, itemRef, 'TEXT', &itemSize ); + GetFlavorData( dragRef, itemRef, 'TEXT', dst, &itemSize, 0L ); + dst += itemSize; + *dst++ = '\n'; // add our element seperator + } + ret = GetFlavorFlags( dragRef, itemRef, 'hfs ', &flags ); + if ( ret == noErr ) + { + HFSFlavor hfs; itemSize = sizeof( hfs ); + GetFlavorData( dragRef, itemRef, 'hfs ', &hfs, &itemSize, 0L ); + itemSize = FSSpec2UnixPath( &hfs.fileSpec, dst ); + dst += itemSize; + if ( itemSize>1 && ( hfs.fileType=='fold' || hfs.fileType=='disk' ) ) + *dst++ = '/'; + *dst++ = '\n'; // add our element seperator + } + } + + dst[-1] = 0; + currDragSize = dst - currDragData - 1; + currDragErr = ret; + return ret; +} + +/** + * Drag'n'drop tracking handler + */ +static pascal OSErr dndTrackingHandler( DragTrackingMessage msg, WindowPtr w, void *userData, DragReference dragRef ) +{ + Fl_Window *target = (Fl_Window*)userData; + Point mp; + static int px, py; + + fillCurrentDragData(dragRef); + Fl::e_length = currDragSize; + Fl::e_text = currDragData; + + switch ( msg ) + { + case kDragTrackingEnterWindow: + // check if 'TEXT' is available + GetDragMouse( dragRef, &mp, 0 ); + Fl::e_x_root = px = mp.h; + Fl::e_y_root = py = mp.v; + Fl::e_x = px - target->x(); + Fl::e_y = py - target->y(); + fl_dnd_target_window = target; + if ( Fl::handle( FL_DND_ENTER, target ) ) + fl_cursor( FL_CURSOR_HAND ); //ShowDragHilite( ); // modify the mouse cursor?! + else + fl_cursor( FL_CURSOR_DEFAULT ); //HideDragHilite( dragRef ); + breakMacEventLoop(); + return noErr; + case kDragTrackingInWindow: + GetDragMouse( dragRef, &mp, 0 ); + if ( mp.h==px && mp.v==py ) + break; //+ return previous condition for dnd hiliting + Fl::e_x_root = px = mp.h; + Fl::e_y_root = py = mp.v; + Fl::e_x = px - target->x(); + Fl::e_y = py - target->y(); + fl_dnd_target_window = target; + if ( Fl::handle( FL_DND_DRAG, target ) ) + fl_cursor( FL_CURSOR_HAND ); //ShowDragHilite( ); // modify the mouse cursor?! + else + fl_cursor( FL_CURSOR_DEFAULT ); //HideDragHilite( dragRef ); + breakMacEventLoop(); + return noErr; + break; + case kDragTrackingLeaveWindow: + // HideDragHilite() + fl_cursor( FL_CURSOR_DEFAULT ); //HideDragHilite( dragRef ); + if ( fl_dnd_target_window ) + { + Fl::handle( FL_DND_LEAVE, fl_dnd_target_window ); + fl_dnd_target_window = 0; + } + breakMacEventLoop(); + return noErr; + } + return noErr; +} + + +/** + * Drag'n'drop receive handler + */ +static pascal OSErr dndReceiveHandler( WindowPtr w, void *userData, DragReference dragRef ) +{ + Point mp; + OSErr ret; + + Fl_Window *target = fl_dnd_target_window = (Fl_Window*)userData; + GetDragMouse( dragRef, &mp, 0 ); + Fl::e_x_root = mp.h; + Fl::e_y_root = mp.v; + Fl::e_x = Fl::e_x_root - target->x(); + Fl::e_y = Fl::e_y_root - target->y(); + if ( !Fl::handle( FL_DND_RELEASE, target ) ) + return userCanceledErr; + + ret = fillCurrentDragData(dragRef); + if (ret==userCanceledErr) + return userCanceledErr; + + Fl::e_length = currDragSize; + Fl::e_text = currDragData; +// printf("Sending following text to widget %p:\n%s\n", Fl::belowmouse(), Fl::e_text); + int old_event = Fl::e_number; + Fl::belowmouse()->handle(Fl::e_number = FL_PASTE); + Fl::e_number = old_event; + + if (currDragData) { + free(currDragData); + } + currDragData = 0L; + currDragRef = 0; + Fl::e_text = 0L; + Fl::e_length = 0; + fl_dnd_target_window = 0L; + + breakMacEventLoop(); + return noErr; +} + + +/** + * go ahead, create that (sub)window + * \todo we should make menu windows slightly transparent for the new Mac look + */ +void Fl_X::make(Fl_Window* w) +{ + static int xyPos = 100; + if ( w->parent() ) // create a subwindow + { + Fl_Group::current(0); + Rect wRect; + wRect.top = w->y(); + wRect.left = w->x(); + wRect.bottom = w->y() + w->h(); if (wRect.bottom<=wRect.top) wRect.bottom = wRect.top+1; + wRect.right = w->x() + w->w(); if (wRect.right<=wRect.left) wRect.right = wRect.left+1; + // our subwindow needs this structure to know about its clipping. + Fl_X* x = new Fl_X; + x->other_xid = 0; + x->region = 0; + x->subRegion = 0; + x->cursor = fl_default_cursor; + x->gc = 0; // stay 0 for Quickdraw; fill with CGContext for Quartz + Fl_Window *win = w->window(); + Fl_X *xo = Fl_X::i(win); + w->set_visible(); + if (xo) { + x->xidNext = xo->xidChildren; + x->xidChildren = 0L; + xo->xidChildren = x; + x->xid = fl_xid(win); + x->w = w; w->i = x; + x->wait_for_expose = 0; + x->next = Fl_X::first; // must be in the list for ::flush() + Fl_X::first = x; + int old_event = Fl::e_number; + w->handle(Fl::e_number = FL_SHOW); + Fl::e_number = old_event; + w->redraw(); // force draw to happen + } + fl_show_iconic = 0; + } + else // create a desktop window + { + Fl_Group::current(0); + fl_open_display(); + int winclass = kDocumentWindowClass; + int winattr = kWindowStandardHandlerAttribute | kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute; + int xp = w->x(); + int yp = w->y(); + int wp = w->w(); + int hp = w->h(); + if (w->size_range_set) { + if ( w->minh != w->maxh || w->minw != w->maxw) + winattr |= kWindowFullZoomAttribute | kWindowResizableAttribute | kWindowLiveResizeAttribute; + } else { + if (w->resizable()) { + Fl_Widget *o = w->resizable(); + int minw = o->w(); if (minw > 100) minw = 100; + int minh = o->h(); if (minh > 100) minh = 100; + w->size_range(w->w() - o->w() + minw, w->h() - o->h() + minh, 0, 0); + winattr |= kWindowFullZoomAttribute | kWindowResizableAttribute | kWindowLiveResizeAttribute; + } else { + w->size_range(w->w(), w->h(), w->w(), w->h()); + } + } + int xwm = xp, ywm = yp, bt, bx, by; + + if (!fake_X_wm(w, xwm, ywm, bt, bx, by)) { + // menu windows and tooltips + if (w->modal()||w->override()) { + winclass = kHelpWindowClass; + winattr = 0; + } else { + winattr = 512; // kWindowNoTitleBarAttribute; + } + } else if (w->modal()) { + winclass = kMovableModalWindowClass; + } + + if (by+bt) { + wp += 2*bx; + hp += 2*by+bt; + } + if (!(w->flags() & Fl_Window::FL_FORCE_POSITION)) { + // use the Carbon functions below for default window positioning + w->x(xyPos+Fl::x()); + w->y(xyPos+Fl::y()); + xyPos += 25; + if (xyPos>200) xyPos = 100; + } else { + if (!Fl::grab()) { + xp = xwm; yp = ywm; + w->x(xp);w->y(yp); + } + xp -= bx; + yp -= by+bt; + } + + if (w->non_modal() && Fl_X::first && !fl_disable_transient_for) { + // find some other window to be "transient for": + Fl_Window* w = Fl_X::first->w; + while (w->parent()) w = w->window(); // todo: this code does not make any sense! (w!=w??) + } + + Rect wRect; + wRect.top = w->y(); + wRect.left = w->x(); + wRect.bottom = w->y() + w->h(); if (wRect.bottom<=wRect.top) wRect.bottom = wRect.top+1; + wRect.right = w->x() + w->w(); if (wRect.right<=wRect.left) wRect.right = wRect.left+1; + + const char *name = w->label(); + Str255 pTitle; + if (name) { + if (strlen(name) > 255) pTitle[0] = 255; + else pTitle[0] = strlen(name); + + memcpy(pTitle+1, name, pTitle[0]); + } else pTitle[0] = 0; + + Fl_X* x = new Fl_X; + x->other_xid = 0; // room for doublebuffering image map. On OS X this is only used by overlay windows + x->region = 0; + x->subRegion = 0; + x->cursor = fl_default_cursor; + x->xidChildren = 0; + x->xidNext = 0; + x->gc = 0; + + winattr &= GetAvailableWindowAttributes( winclass ); // make sure that the window will open + CreateNewWindow( winclass, winattr, &wRect, &(x->xid) ); + SetWTitle(x->xid, pTitle); + MoveWindow(x->xid, wRect.left, wRect.top, 1); // avoid Carbon Bug on old OS + if (w->non_modal() && !w->modal()) { + // Major kludge: this is to have the regular look, but stay above the document windows + SetWindowClass(x->xid, kFloatingWindowClass); + } + if (!(w->flags() & Fl_Window::FL_FORCE_POSITION)) + { + WindowRef pw = Fl_X::first ? Fl_X::first->xid : 0 ; + if (w->modal()) { + RepositionWindow(x->xid, pw, kWindowAlertPositionOnParentWindowScreen); + } else if (w->non_modal()) { + RepositionWindow(x->xid, pw, kWindowCenterOnParentWindowScreen); + } else { + RepositionWindow(x->xid, pw, kWindowCascadeOnParentWindowScreen); + } + } + x->w = w; w->i = x; + x->wait_for_expose = 1; + x->next = Fl_X::first; + Fl_X::first = x; + w->set_visible(); + { // Install Carbon Event handlers + OSStatus ret; + EventHandlerUPP mousewheelHandler = NewEventHandlerUPP( carbonMousewheelHandler ); // will not be disposed by Carbon... + static EventTypeSpec mousewheelEvents[] = { + { kEventClassMouse, kEventMouseWheelMoved } }; + ret = InstallWindowEventHandler( x->xid, mousewheelHandler, + (int)(sizeof(mousewheelEvents)/sizeof(mousewheelEvents[0])), + mousewheelEvents, w, 0L ); + EventHandlerUPP mouseHandler = NewEventHandlerUPP( carbonMouseHandler ); // will not be disposed by Carbon... + static EventTypeSpec mouseEvents[] = { + { kEventClassMouse, kEventMouseDown }, + { kEventClassMouse, kEventMouseUp }, + { kEventClassMouse, kEventMouseMoved }, + { kEventClassMouse, kEventMouseDragged } }; + ret = InstallWindowEventHandler( x->xid, mouseHandler, 4, mouseEvents, w, 0L ); + EventHandlerUPP keyboardHandler = NewEventHandlerUPP( carbonKeyboardHandler ); // will not be disposed by Carbon... + static EventTypeSpec keyboardEvents[] = { + { kEventClassKeyboard, kEventRawKeyDown }, + { kEventClassKeyboard, kEventRawKeyRepeat }, + { kEventClassKeyboard, kEventRawKeyUp }, + { kEventClassKeyboard, kEventRawKeyModifiersChanged } }; + ret = InstallWindowEventHandler( x->xid, keyboardHandler, 4, keyboardEvents, w, 0L ); + EventHandlerUPP windowHandler = NewEventHandlerUPP( carbonWindowHandler ); // will not be disposed by Carbon... + static EventTypeSpec windowEvents[] = { + { kEventClassWindow, kEventWindowDrawContent }, + { kEventClassWindow, kEventWindowShown }, + { kEventClassWindow, kEventWindowHidden }, + { kEventClassWindow, kEventWindowActivated }, + { kEventClassWindow, kEventWindowDeactivated }, + { kEventClassWindow, kEventWindowClose }, + { kEventClassWindow, kEventWindowBoundsChanging }, + { kEventClassWindow, kEventWindowBoundsChanged } }; + ret = InstallWindowEventHandler( x->xid, windowHandler, 8, windowEvents, w, 0L ); + ret = InstallTrackingHandler( dndTrackingHandler, x->xid, w ); + ret = InstallReceiveHandler( dndReceiveHandler, x->xid, w ); + } + + if ( ! Fl_X::first->next ) // if this is the first window, we need to bring the application to the front + { + ProcessSerialNumber psn; + OSErr err = GetCurrentProcess( &psn ); + if ( err==noErr ) SetFrontProcess( &psn ); + } + + if (fl_show_iconic) { + fl_show_iconic = 0; + CollapseWindow( x->xid, true ); // \todo Mac ; untested + } else if (winclass != kHelpWindowClass) { + Fl_Tooltip::enter(0); + } + + ShowWindow(x->xid); + + Rect rect; + GetWindowBounds(x->xid, kWindowContentRgn, &rect); + w->x(rect.left); w->y(rect.top); + w->w(rect.right-rect.left); w->h(rect.bottom-rect.top); + + int old_event = Fl::e_number; + w->handle(Fl::e_number = FL_SHOW); + Fl::e_number = old_event; + w->redraw(); // force draw to happen + w->set_visible(); + + if (w->modal()) { Fl::modal_ = w; fl_fix_focus(); } + } +} + + +/** + * this is a leftover from X Windows + */ +void Fl_Window::size_range_() { + size_range_set = 1; +} + + +/** + * returns pointer to the filename, or null if name ends with ':' + */ +const char *fl_filename_name( const char *name ) +{ + const char *p, *q; + if (!name) return (0); + for ( p = q = name ; *p ; ) + { + if ( ( p[0] == ':' ) && ( p[1] == ':' ) ) + { + q = p+2; + p++; + } + else if (p[0] == '/') + q = p + 1; + p++; + } + return q; +} + + +/** + * set the window title bar + * \todo make the titlebar icon work! + */ +void Fl_Window::label(const char *name,const char */*iname*/) { + Fl_Widget::label(name); + Str255 pTitle; + + if (name) { pTitle[0] = strlen(name); memcpy(pTitle+1, name, pTitle[0]); } + else pTitle[0] = 0; + + if (shown() || i) SetWTitle(fl_xid(this), pTitle); +} + + +/** + * make a window visible + */ +void Fl_Window::show() { + image(Fl::scheme_bg_); + if (Fl::scheme_bg_) { + labeltype(FL_NORMAL_LABEL); + align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP); + } else { + labeltype(FL_NO_LABEL); + } + if (!shown() || !i) { + Fl_X::make(this); + } else { + if ( !parent() ) + { + if ( IsWindowCollapsed( i->xid ) ) CollapseWindow( i->xid, false ); + if (!fl_capture) { + BringToFront(i->xid); + SelectWindow(i->xid); + } + } + } +} + + +/** + * resize a window + */ +void Fl_Window::resize(int X,int Y,int W,int H) { + int is_a_resize = (W != w() || H != h()); +// printf("Fl_Winodw::resize(X=%d, Y=%d, W=%d, H=%d), is_a_resize=%d, resize_from_system=%p, this=%p\n", +// X, Y, W, H, is_a_resize, resize_from_system, this); + if (X != x() || Y != y()) set_flag(FL_FORCE_POSITION); + else if (!is_a_resize) return; + if ( (resize_from_system!=this) && (!parent()) && shown()) { + MoveWindow(i->xid, X, Y, 0); + if (is_a_resize) { + if (!resizable()) size_range(W>0 ? W : 1, H>0 ? H : 1, W>0 ? W : 1, H>0 ? H : 1); + SizeWindow(i->xid, W>0 ? W : 1, H>0 ? H : 1, 1); + Rect all; all.top=-32000; all.bottom=32000; all.left=-32000; all.right=32000; + InvalWindowRect( i->xid, &all ); + } + } else if (resize_from_system == this && size_range_set && !parent() && shown()) { + if (size_range_set) { + if (W < minw) W = minw; + else if (W > maxw && maxw) W = maxw; + if (H < minh) H = minh; + else if (H > maxh && maxh) H = maxh; + } + SizeWindow(i->xid, W>0 ? W : 1, H>0 ? H : 1, 1); + } + resize_from_system = 0; + if (is_a_resize) { + Fl_Group::resize(X,Y,W,H); + if (shown()) { + redraw(); + //if (!parent()) i->wait_for_expose = 1; + } + } else { + x(X); y(Y); + } +} + + +/** + * make all drawing go into this window (called by subclass flush() impl.) + */ +void Fl_Window::make_current() +{ +#ifdef __APPLE_QUARTZ__ + Fl_X::q_release_context(); +#endif + if ( !fl_window_region ) + fl_window_region = NewRgn(); + fl_window = i->xid; + current_ = this; + + SetPort( GetWindowPort(i->xid) ); // \todo check for the handling of doublebuffered windows + + int xp = 0, yp = 0; + Fl_Window *win = this; + while ( win ) + { + if ( !win->window() ) + break; + xp += win->x(); + yp += win->y(); + win = (Fl_Window*)win->window(); + } + SetOrigin( -xp, -yp ); + + SetRectRgn( fl_window_region, 0, 0, w(), h() ); + + // \todo for performance reasons: we don't have to create this unless the child windows moved + for ( Fl_X *cx = i->xidChildren; cx; cx = cx->xidNext ) + { + Fl_Window *cw = cx->w; + if (!cw->visible_r()) continue; + Fl_Region r = NewRgn(); + SetRectRgn( r, cw->x() - xp, cw->y() - yp, + cw->x() + cw->w() - xp, cw->y() + cw->h() - yp ); + DiffRgn( fl_window_region, r, fl_window_region ); + DisposeRgn( r ); + } + + fl_clip_region( 0 ); + SetPortClipRegion( GetWindowPort(i->xid), fl_window_region ); +#ifdef __APPLE_QUARTZ__ + QDBeginCGContext(GetWindowPort(i->xid), &i->gc); + fl_gc = i->gc; + CGContextSaveGState(fl_gc); + Fl_X::q_fill_context(); +#endif + return; +} + +// helper function to manage the current CGContext fl_gc +#ifdef __APPLE_QUARTZ__ +extern Fl_Color fl_color_; +extern class Fl_FontSize *fl_fontsize; +extern void fl_font(class Fl_FontSize*); +extern void fl_quartz_restore_line_style_(); + +// FLTK has only on global graphics state. This function copies the FLTK state into the +// current Quartz context +void Fl_X::q_fill_context() { + if (!fl_gc) return; + int hgt = 0; + if (fl_window) { + Rect portRect; + GetPortBounds(GetWindowPort( fl_window ), &portRect); + hgt = portRect.bottom-portRect.top; + } else { + hgt = CGBitmapContextGetHeight(fl_gc); + } + CGContextTranslateCTM(fl_gc, 0.5, hgt-0.5f); + CGContextScaleCTM(fl_gc, 1.0f, -1.0f); + static CGAffineTransform font_mx = { 1, 0, 0, -1, 0, 0 }; + CGContextSetTextMatrix(fl_gc, font_mx); + fl_font(fl_fontsize); + fl_color(fl_color_); + fl_quartz_restore_line_style_(); +} + +// The only way to reste clipping to its original state is to pop the current graphics +// state and restore the global state. +void Fl_X::q_clear_clipping() { + if (!fl_gc) return; + CGContextRestoreGState(fl_gc); + CGContextSaveGState(fl_gc); +} + +// Give the Quartz context back to the system +void Fl_X::q_release_context(Fl_X *x) { + if (x && x->gc!=fl_gc) return; + if (!fl_gc) return; + CGContextRestoreGState(fl_gc); + if (fl_window) QDEndCGContext(GetWindowPort(fl_window), &fl_gc); + fl_gc = 0; +} + +void Fl_X::q_begin_image(CGRect &rect, int cx, int cy, int w, int h) { + CGContextSaveGState(fl_gc); + CGAffineTransform mx = CGContextGetCTM(fl_gc); + CGRect r2 = rect; + r2.origin.x -= 0.5f; + r2.origin.y -= 0.5f; + CGContextClipToRect(fl_gc, r2); + mx.d = -1.0; mx.tx = -mx.tx; + CGContextConcatCTM(fl_gc, mx); + rect.origin.x = rect.origin.x - cx; + rect.origin.y = (mx.ty+0.5f) - rect.origin.y - h + cy; + rect.size.width = w; + rect.size.height = h; +} + +void Fl_X::q_end_image() { + CGContextRestoreGState(fl_gc); +} + +#endif + +//////////////////////////////////////////////////////////////// +// Cut & paste. + +Fl_Widget *fl_selection_requestor = 0; +char *fl_selection_buffer[2]; +int fl_selection_length[2]; +int fl_selection_buffer_length[2]; +static ScrapRef myScrap = 0; + +/** + * create a selection + * owner: widget that created the selection + * stuff: pointer to selected data + * size of selected data + */ +void Fl::copy(const char *stuff, int len, int clipboard) { + if (!stuff || len<0) return; + if (len+1 > fl_selection_buffer_length[clipboard]) { + delete[] fl_selection_buffer[clipboard]; + fl_selection_buffer[clipboard] = new char[len+100]; + fl_selection_buffer_length[clipboard] = len+100; + } + memcpy(fl_selection_buffer[clipboard], stuff, len); + fl_selection_buffer[clipboard][len] = 0; // needed for direct paste + fl_selection_length[clipboard] = len; + if (clipboard) { + ClearCurrentScrap(); + OSStatus ret = GetCurrentScrap( &myScrap ); + if ( ret != noErr ) { + myScrap = 0; + return; + } + // Previous version changed \n to \r before sending the text, but I would + // prefer to leave the local buffer alone, so a copied buffer may be + // needed. Check to see if this is necessary on OS/X. + PutScrapFlavor( myScrap, kScrapFlavorTypeText, 0, + len, fl_selection_buffer[1] ); + } +} + +// Call this when a "paste" operation happens: +void Fl::paste(Fl_Widget &receiver, int clipboard) { + if (clipboard) { + // see if we own the selection, if not go get it: + ScrapRef scrap = 0; + Size len = 0; + if (GetCurrentScrap(&scrap) == noErr && scrap != myScrap && + GetScrapFlavorSize(scrap, kScrapFlavorTypeText, &len) == noErr) { + if ( len > fl_selection_buffer_length[1] ) { + fl_selection_buffer_length[1] = len + 32; + delete[] fl_selection_buffer[1]; + fl_selection_buffer[1] = new char[len]; + } + GetScrapFlavorData( scrap, kScrapFlavorTypeText, &len, + fl_selection_buffer[1] ); + fl_selection_length[1] = len; + // turn all \r characters into \n: + for (int x = 0; x < len; x++) { + if (fl_selection_buffer[1][x] == '\r') + fl_selection_buffer[1][x] = '\n'; + } + } + } + Fl::e_text = fl_selection_buffer[clipboard]; + Fl::e_length = fl_selection_length[clipboard]; + if (!Fl::e_text) Fl::e_text = (char *)""; + receiver.handle(FL_PASTE); + return; +} + +void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void* data) +{ + int timer_id = -1; + for (int i = 0; i < mac_timer_used; ++i) { + if ( !mac_timers[i].timer ) { + timer_id = i; + break; + } + } + if (timer_id == -1) { + if (mac_timer_used == mac_timer_alloc) { + realloc_timers(); + } + timer_id = mac_timer_used++; + } + + EventTimerInterval fireDelay = (EventTimerInterval) time; + EventLoopTimerUPP timerUPP = NewEventLoopTimerUPP(do_timer); + EventLoopTimerRef timerRef; + OSStatus err = InstallEventLoopTimer(GetMainEventLoop(), fireDelay, 0, timerUPP, data, &timerRef); + if (err == noErr) { + mac_timers[timer_id].callback = cb; + mac_timers[timer_id].data = data; + mac_timers[timer_id].timer = timerRef; + } +} + +void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void* data) +{ + remove_timeout(cb, data); + add_timeout(time, cb, data); +} + +int Fl::has_timeout(Fl_Timeout_Handler cb, void* data) +{ + for (int i = 0; i < mac_timer_used; ++i) { + MacTimeout& t = mac_timers[i]; + if (t.callback == cb && t.data == data) { + return 1; + } + } + return 0; +} + +void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data) +{ + for (int i = 0; i < mac_timer_used; ++i) { + MacTimeout& t = mac_timers[i]; + if (t.callback == cb && ( t.data == data || data == NULL)) { + delete_timer(t); + } + } +} + + + +// +// End of "$Id$". +// + diff --git a/Utilities/FLTK/src/Fl_own_colormap.cxx b/Utilities/FLTK/src/Fl_own_colormap.cxx new file mode 100644 index 0000000000..106e5d46da --- /dev/null +++ b/Utilities/FLTK/src/Fl_own_colormap.cxx @@ -0,0 +1,85 @@ +// +// "$Id$" +// +// Private colormap support for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Using the default system colormap can be a bad idea on PseudoColor +// visuals, since typically every application uses the default colormap and +// you can run out of colormap entries easily. +// +// The solution is to always create a new colormap on PseudoColor displays +// and copy the first 16 colors from the default colormap so that we won't +// get huge color changes when switching windows. + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#include <FL/x.H> +#include <FL/Fl.H> + +#ifdef WIN32 +// There is probably something relevant to do on MSWindows 8-bit displays +// but I don't know what it is + +void Fl::own_colormap() {} + +#elif defined(__APPLE__) +// MacOS X always provides a TrueColor interface... + +void Fl::own_colormap() {} +#else +// X version + +void Fl::own_colormap() { + fl_open_display(); +#if USE_COLORMAP + switch (fl_visual->c_class) { + case GrayScale : + case PseudoColor : + case DirectColor : + break; + default: + return; // don't do anything for non-colormapped visuals + } + int i; + XColor colors[16]; + // Get the first 16 colors from the default colormap... + for (i = 0; i < 16; i ++) colors[i].pixel = i; + XQueryColors(fl_display, fl_colormap, colors, 16); + // Create a new colormap... + fl_colormap = XCreateColormap(fl_display, + RootWindow(fl_display,fl_screen), + fl_visual->visual, AllocNone); + // Copy those first 16 colors to our own colormap: + for (i = 0; i < 16; i ++) + XAllocColor(fl_display, fl_colormap, colors + i); +#endif +} + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_visual.cxx b/Utilities/FLTK/src/Fl_visual.cxx new file mode 100644 index 0000000000..ab16581056 --- /dev/null +++ b/Utilities/FLTK/src/Fl_visual.cxx @@ -0,0 +1,123 @@ +// +// "$Id$" +// +// Visual support for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Set the default visual according to passed switches: + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#include <FL/x.H> +#include <FL/Fl.H> + +#ifdef WIN32 +int Fl::visual(int flags) { + fl_GetDC(0); + if (flags & FL_DOUBLE) return 0; + if (!(flags & FL_INDEX) && + GetDeviceCaps(fl_gc,BITSPIXEL) <= 8) return 0; + if ((flags & FL_RGB8) && GetDeviceCaps(fl_gc,BITSPIXEL)<24) return 0; + return 1; +} +#elif defined(__APPLE__) + +// \todo Mac : need to implement Visual flags +int Fl::visual(int flags) { + (void)flags; + return 1; +} + +#else + +#if USE_XDBE +#include <X11/extensions/Xdbe.h> +#endif + +static int test_visual(XVisualInfo& v, int flags) { + if (v.screen != fl_screen) return 0; +#if USE_COLORMAP + if (!(flags & FL_INDEX)) { + if (v.c_class != StaticColor && v.c_class != TrueColor) return 0; + if (v.depth <= 8) return 0; // fltk will work better in colormap mode + } + if (flags & FL_RGB8) { + if (v.depth < 24) return 0; + } + // for now, fltk does not like colormaps of more than 8 bits: + if ((v.c_class&1) && v.depth > 8) return 0; +#else + // simpler if we can't use colormapped visuals at all: + if (v.c_class != StaticColor && v.c_class != TrueColor) return 0; +#endif +#if USE_XDBE + if (flags & FL_DOUBLE) { + static XdbeScreenVisualInfo *xdbejunk; + if (!xdbejunk) { + int event_base, error_base; + if (!XdbeQueryExtension(fl_display, &event_base, &error_base)) return 0; + Drawable root = RootWindow(fl_display,fl_screen); + int numscreens = 1; + xdbejunk = XdbeGetVisualInfo(fl_display,&root,&numscreens); + if (!xdbejunk) return 0; + } + for (int j = 0; ; j++) { + if (j >= xdbejunk->count) return 0; + if (xdbejunk->visinfo[j].visual == v.visualid) break; + } + } +#endif + return 1; +} + +int Fl::visual(int flags) { +#if USE_XDBE == 0 + if (flags & FL_DOUBLE) return 0; +#endif + fl_open_display(); + // always use default if possible: + if (test_visual(*fl_visual, flags)) return 1; + // get all the visuals: + XVisualInfo vTemplate; + int num; + XVisualInfo *visualList = XGetVisualInfo(fl_display, 0, &vTemplate, &num); + // find all matches, use the one with greatest depth: + XVisualInfo *found = 0; + for (int i=0; i<num; i++) if (test_visual(visualList[i], flags)) { + if (!found || found->depth < visualList[i].depth) + found = &visualList[i]; + } + if (!found) {XFree((void*)visualList); return 0;} + fl_visual = found; + fl_colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen), + fl_visual->visual, AllocNone); + return 1; +} + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_win32.cxx b/Utilities/FLTK/src/Fl_win32.cxx new file mode 100644 index 0000000000..36372b2964 --- /dev/null +++ b/Utilities/FLTK/src/Fl_win32.cxx @@ -0,0 +1,1664 @@ +// +// "$Id$" +// +// WIN32-specific code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// This file contains win32-specific code for fltk which is always linked +// in. Search other files for "WIN32" or filenames ending in _win32.cxx +// for other system-specific code. + +#include <FL/Fl.H> +#include <FL/x.H> +#include <FL/Fl_Window.H> +#include <FL/Enumerations.H> +#include "flstring.h" +#include "Fl_Font.H" +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <time.h> +#ifdef __CYGWIN__ +# include <sys/time.h> +# include <unistd.h> +#else +# include <winsock.h> +#endif +#include <winuser.h> +#include <commctrl.h> + +// The following include files require GCC 3.x or a non-GNU compiler... +#if !defined(__GNUC__) || __GNUC__ >= 3 +# include <ole2.h> +# include <shellapi.h> +#endif // !__GNUC__ || __GNUC__ >= 3 + + +// +// USE_ASYNC_SELECT - define it if you have WSAAsyncSelect()... +// +// This currently doesn't appear to work; needs to be fixed! +// + +//#define USE_ASYNC_SELECT + + +// +// USE_TRACK_MOUSE - define it if you have TrackMouseEvent()... +// +// Apparently, at least some versions of Cygwin/MingW don't provide +// the TrackMouseEvent() function. You can define this by hand +// if you have it - this is only needed to support subwindow +// enter/leave notification under Windows. +// + +//#define USE_TRACK_MOUSE + +#if !defined(__GNUC__) +# define USE_TRACK_MOUSE +#endif // !__GNUC__ + + +// +// WM_SYNCPAINT is an "undocumented" message, which is finally defined in +// VC++ 6.0. +// + +#ifndef WM_SYNCPAINT +# define WM_SYNCPAINT 0x0088 +#endif + +#ifndef WM_MOUSELEAVE +# define WM_MOUSELEAVE 0x02a3 +#endif + +#ifndef WM_MOUSEWHEEL +# define WM_MOUSEWHEEL 0x020a +#endif + +#ifndef WHEEL_DELTA +# define WHEEL_DELTA 120 // according to MSDN. +#endif + + +// +// WM_FLSELECT is the user-defined message that we get when one of +// the sockets has pending data, etc. +// + +#define WM_FLSELECT (WM_APP+1) // WM_APP is used for hide-window + + +//////////////////////////////////////////////////////////////// +// interface to poll/select call: + +// fd's are only implemented for sockets. Microsoft Windows does not +// have a unified IO system, so it doesn't support select() on files, +// devices, or pipes... +// +// Microsoft provides the Berkeley select() call and an asynchronous +// select function that sends a WIN32 message when the select condition +// exists... +static int maxfd = 0; +#ifndef USE_ASYNC_SELECT +static fd_set fdsets[3]; +#endif // !USE_ASYNC_SELECT + +#define POLLIN 1 +#define POLLOUT 4 +#define POLLERR 8 + +#if !defined(__GNUC__) || __GNUC__ >= 3 +extern IDropTarget *flIDropTarget; +#endif // !__GNUC__ || __GNUC__ >= 3 + +static int nfds = 0; +static int fd_array_size = 0; +static struct FD { + int fd; + short events; + void (*cb)(int, void*); + void* arg; +} *fd = 0; + +void Fl::add_fd(int n, int events, void (*cb)(int, void*), void *v) { + remove_fd(n,events); + int i = nfds++; + if (i >= fd_array_size) { + fd_array_size = 2*fd_array_size+1; + fd = (FD*)realloc(fd, fd_array_size*sizeof(FD)); + } + fd[i].fd = n; + fd[i].events = (short)events; + fd[i].cb = cb; + fd[i].arg = v; + +#ifdef USE_ASYNC_SELECT + int mask = 0; + if (events & POLLIN) mask |= FD_READ; + if (events & POLLOUT) mask |= FD_WRITE; + if (events & POLLERR) mask |= FD_CLOSE; + WSAAsyncSelect(n, fl_window, WM_FLSELECT, mask); +#else + if (events & POLLIN) FD_SET((unsigned)n, &fdsets[0]); + if (events & POLLOUT) FD_SET((unsigned)n, &fdsets[1]); + if (events & POLLERR) FD_SET((unsigned)n, &fdsets[2]); + if (n > maxfd) maxfd = n; +#endif // USE_ASYNC_SELECT +} + +void Fl::add_fd(int fd, void (*cb)(int, void*), void* v) { + Fl::add_fd(fd, POLLIN, cb, v); +} + +void Fl::remove_fd(int n, int events) { + int i,j; + for (i=j=0; i<nfds; i++) { + if (fd[i].fd == n) { + short e = fd[i].events & ~events; + if (!e) continue; // if no events left, delete this fd + fd[i].events = e; + } + // move it down in the array if necessary: + if (j<i) { + fd[j]=fd[i]; + } + j++; + } + nfds = j; + +#ifdef USE_ASYNC_SELECT + WSAAsyncSelect(n, 0, 0, 0); +#else + if (events & POLLIN) FD_CLR(unsigned(n), &fdsets[0]); + if (events & POLLOUT) FD_CLR(unsigned(n), &fdsets[1]); + if (events & POLLERR) FD_CLR(unsigned(n), &fdsets[2]); +#endif // USE_ASYNC_SELECT +} + +void Fl::remove_fd(int n) { + remove_fd(n, -1); +} + +// these pointers are set by the Fl::lock() function: +static void nothing() {} +void (*fl_lock_function)() = nothing; +void (*fl_unlock_function)() = nothing; + +static void* thread_message_; +void* Fl::thread_message() { + void* r = thread_message_; + thread_message_ = 0; + return r; +} + +MSG fl_msg; + +// This is never called with time_to_wait < 0.0. +// It *should* return negative on error, 0 if nothing happens before +// timeout, and >0 if any callbacks were done. This version only +// returns zero if nothing happens during a 0.0 timeout, otherwise +// it returns 1. +int fl_wait(double time_to_wait) { + int have_message = 0; + +#ifndef USE_ASYNC_SELECT + if (nfds) { + // For WIN32 we need to poll for socket input FIRST, since + // the event queue is not something we can select() on... + timeval t; + t.tv_sec = 0; + t.tv_usec = 0; + + fd_set fdt[3]; + fdt[0] = fdsets[0]; + fdt[1] = fdsets[1]; + fdt[2] = fdsets[2]; + if (::select(maxfd+1,&fdt[0],&fdt[1],&fdt[2],&t)) { + // We got something - do the callback! + for (int i = 0; i < nfds; i ++) { + int f = fd[i].fd; + short revents = 0; + if (FD_ISSET(f,&fdt[0])) revents |= POLLIN; + if (FD_ISSET(f,&fdt[1])) revents |= POLLOUT; + if (FD_ISSET(f,&fdt[2])) revents |= POLLERR; + if (fd[i].events & revents) fd[i].cb(f, fd[i].arg); + } + time_to_wait = 0.0; // just peek for any messages +#ifdef __CYGWIN__ + } +#else + } else { + // we need to check them periodically, so set a short timeout: + if (time_to_wait > .001) time_to_wait = .001; + } +#endif + } +#endif // USE_ASYNC_SELECT + + if (Fl::idle || Fl::damage()) + time_to_wait = 0.0; + + fl_unlock_function(); + + time_to_wait = (time_to_wait > 10000 ? 10000 : time_to_wait); + int t_msec = (int) (time_to_wait * 1000.0 + 0.5); + int ret_val = MsgWaitForMultipleObjects(0, NULL, FALSE, t_msec, QS_ALLINPUT); + + fl_lock_function(); + + // Execute the message we got, and all other pending messages: + have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE); + if (have_message > 0) { + while (have_message != 0 && have_message != -1) { +#ifdef USE_ASYNC_SELECT + if (fl_msg.message == WM_FLSELECT) { + // Got notification for socket + for (int i = 0; i < nfds; i ++) + if (fd[i].fd == (int)fl_msg.wParam) { + (fd[i].cb)(fd[i].fd, fd[i].arg); + break; + } + // looks like it is best to do the dispatch-message anyway: + } +#endif + + if (fl_msg.message == fl_wake_msg) // Used for awaking wait() from another thread + thread_message_ = (void*)fl_msg.wParam; + + TranslateMessage(&fl_msg); + DispatchMessage(&fl_msg); + have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE); + } + } + Fl::flush(); + + // idle processing + static char in_idle; + if (Fl::idle && !in_idle) { + in_idle = 1; + Fl::idle(); + in_idle = 0; + } + + run_checks(); + + // This should return 0 if only timer events were handled: + return 1; +} + +// fl_ready() is just like fl_wait(0.0) except no callbacks are done: +int fl_ready() { + if (PeekMessage(&fl_msg, NULL, 0, 0, PM_NOREMOVE)) return 1; +#ifdef USE_ASYNC_SELECT + return 0; +#else + timeval t; + t.tv_sec = 0; + t.tv_usec = 0; + fd_set fdt[3]; + fdt[0] = fdsets[0]; + fdt[1] = fdsets[1]; + fdt[2] = fdsets[2]; + return ::select(0,&fdt[0],&fdt[1],&fdt[2],&t); +#endif // USE_ASYNC_SELECT +} + +//////////////////////////////////////////////////////////////// + +int Fl::x() +{ + RECT r; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); + return r.left; +} + +int Fl::y() +{ + RECT r; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); + return r.top; +} + +int Fl::h() +{ + RECT r; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); + return r.bottom - r.top; +} + +int Fl::w() +{ + RECT r; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); + return r.right - r.left; +} + +void Fl::get_mouse(int &x, int &y) { + POINT p; + GetCursorPos(&p); + x = p.x; + y = p.y; +} + +//////////////////////////////////////////////////////////////// +// code used for selections: + +char *fl_selection_buffer[2]; +int fl_selection_length[2]; +int fl_selection_buffer_length[2]; +char fl_i_own_selection[2]; + +// Convert \n -> \r\n +class Lf2CrlfConvert { + char *out; + int outlen; +public: + Lf2CrlfConvert(const char *in, int inlen) { + outlen = 0; + const char *i; + char *o; + int lencount; + // Predict size of \r\n conversion buffer + for ( i=in, lencount = inlen; lencount--; ) { + if ( *i == '\r' && *(i+1) == '\n' ) // leave \r\n untranslated + { i+=2; outlen+=2; } + else if ( *i == '\n' ) // \n by itself? leave room to insert \r + { i++; outlen+=2; } + else + { ++i; ++outlen; } + } + // Alloc conversion buffer + NULL + out = new char[outlen+1]; + // Handle \n -> \r\n conversion + for ( i=in, o=out, lencount = inlen; lencount--; ) { + if ( *i == '\r' && *(i+1) == '\n' ) // leave \r\n untranslated + { *o++ = *i++; *o++ = *i++; } + else if ( *i == '\n' ) // \n by itself? insert \r + { *o++ = '\r'; *o++ = *i++; } + else + { *o++ = *i++; } + } + *o++ = 0; + } + ~Lf2CrlfConvert() { + delete[] out; + } + int GetLength() const { return(outlen); } + const char* GetValue() const { return(out); } +}; + +// call this when you create a selection: +void Fl::copy(const char *stuff, int len, int clipboard) { + if (!stuff || len<0) return; + + // Convert \n -> \r\n (for old apps like Notepad, DOS) + Lf2CrlfConvert buf(stuff, len); + len = buf.GetLength(); + stuff = buf.GetValue(); + + if (len+1 > fl_selection_buffer_length[clipboard]) { + delete[] fl_selection_buffer[clipboard]; + fl_selection_buffer[clipboard] = new char[len+100]; + fl_selection_buffer_length[clipboard] = len+100; + } + memcpy(fl_selection_buffer[clipboard], stuff, len); + fl_selection_buffer[clipboard][len] = 0; // needed for direct paste + fl_selection_length[clipboard] = len; + if (clipboard) { + // set up for "delayed rendering": + if (OpenClipboard(fl_xid(Fl::first_window()))) { + // if the system clipboard works, use it + EmptyClipboard(); + SetClipboardData(CF_TEXT, NULL); + CloseClipboard(); + fl_i_own_selection[clipboard] = 0; + } else { + // only if it fails, instruct paste() to use the internal buffers + fl_i_own_selection[clipboard] = 1; + } + } +} + +// Call this when a "paste" operation happens: +void Fl::paste(Fl_Widget &receiver, int clipboard) { + if (!clipboard || fl_i_own_selection[clipboard]) { + // We already have it, do it quickly without window server. + // Notice that the text is clobbered if set_selection is + // called in response to FL_PASTE! + + // Convert \r\n -> \n + char *i = fl_selection_buffer[clipboard]; + if (i==0L) { + Fl::e_text = 0; + return; + } + Fl::e_text = new char[fl_selection_length[clipboard]+1]; + char *o = Fl::e_text; + while (*i) { + if ( *i == '\r' && *(i+1) == '\n') i++; + else *o++ = *i++; + } + *o = 0; + Fl::e_length = o - Fl::e_text; + receiver.handle(FL_PASTE); + delete [] Fl::e_text; + Fl::e_text = 0; + } else { + if (!OpenClipboard(NULL)) return; + HANDLE h = GetClipboardData(CF_TEXT); + if (h) { + Fl::e_text = (LPSTR)GlobalLock(h); + LPSTR a,b; + a = b = Fl::e_text; + while (*a) { // strip the CRLF pairs ($%$#@^) + if (*a == '\r' && a[1] == '\n') a++; + else *b++ = *a++; + } + *b = 0; + Fl::e_length = b - Fl::e_text; + receiver.handle(FL_PASTE); + GlobalUnlock(h); + } + CloseClipboard(); + } +} + +//////////////////////////////////////////////////////////////// + +HWND fl_capture; + +static int mouse_event(Fl_Window *window, int what, int button, + WPARAM wParam, LPARAM lParam) +{ + static int px, py, pmx, pmy; + POINT pt; + Fl::e_x = pt.x = (signed short)LOWORD(lParam); + Fl::e_y = pt.y = (signed short)HIWORD(lParam); + ClientToScreen(fl_xid(window), &pt); + Fl::e_x_root = pt.x; + Fl::e_y_root = pt.y; + while (window->parent()) { + Fl::e_x += window->x(); + Fl::e_y += window->y(); + window = window->window(); + } + + ulong state = Fl::e_state & 0xff0000; // keep shift key states +#if 0 + // mouse event reports some shift flags, perhaps save them? + if (wParam & MK_SHIFT) state |= FL_SHIFT; + if (wParam & MK_CONTROL) state |= FL_CTRL; +#endif + if (wParam & MK_LBUTTON) state |= FL_BUTTON1; + if (wParam & MK_MBUTTON) state |= FL_BUTTON2; + if (wParam & MK_RBUTTON) state |= FL_BUTTON3; + Fl::e_state = state; + + switch (what) { + case 1: // double-click + if (Fl::e_is_click) {Fl::e_clicks++; goto J1;} + case 0: // single-click + Fl::e_clicks = 0; + J1: + if (!fl_capture) SetCapture(fl_xid(window)); + Fl::e_keysym = FL_Button + button; + Fl::e_is_click = 1; + px = pmx = Fl::e_x_root; py = pmy = Fl::e_y_root; + return Fl::handle(FL_PUSH,window); + + case 2: // release: + if (!fl_capture) ReleaseCapture(); + Fl::e_keysym = FL_Button + button; + return Fl::handle(FL_RELEASE,window); + + case 3: // move: + default: // avoid compiler warning + // MSWindows produces extra events even if mouse does not move, ignore em: + if (Fl::e_x_root == pmx && Fl::e_y_root == pmy) return 1; + pmx = Fl::e_x_root; pmy = Fl::e_y_root; + if (abs(Fl::e_x_root-px)>5 || abs(Fl::e_y_root-py)>5) Fl::e_is_click = 0; + return Fl::handle(FL_MOVE,window); + + } +} + +// convert a MSWindows VK_x to an Fltk (X) Keysym: +// See also the inverse converter in Fl_get_key_win32.cxx +// This table is in numeric order by VK: +static const struct {unsigned short vk, fltk, extended;} vktab[] = { + {VK_BACK, FL_BackSpace}, + {VK_TAB, FL_Tab}, + {VK_CLEAR, FL_KP+'5', 0xff0b/*XK_Clear*/}, + {VK_RETURN, FL_Enter, FL_KP_Enter}, + {VK_SHIFT, FL_Shift_L, FL_Shift_R}, + {VK_CONTROL, FL_Control_L, FL_Control_R}, + {VK_MENU, FL_Alt_L, FL_Alt_R}, + {VK_PAUSE, FL_Pause}, + {VK_CAPITAL, FL_Caps_Lock}, + {VK_ESCAPE, FL_Escape}, + {VK_SPACE, ' '}, + {VK_PRIOR, FL_KP+'9', FL_Page_Up}, + {VK_NEXT, FL_KP+'3', FL_Page_Down}, + {VK_END, FL_KP+'1', FL_End}, + {VK_HOME, FL_KP+'7', FL_Home}, + {VK_LEFT, FL_KP+'4', FL_Left}, + {VK_UP, FL_KP+'8', FL_Up}, + {VK_RIGHT, FL_KP+'6', FL_Right}, + {VK_DOWN, FL_KP+'2', FL_Down}, + {VK_SNAPSHOT, FL_Print}, // does not work on NT + {VK_INSERT, FL_KP+'0', FL_Insert}, + {VK_DELETE, FL_KP+'.', FL_Delete}, + {VK_LWIN, FL_Meta_L}, + {VK_RWIN, FL_Meta_R}, + {VK_APPS, FL_Menu}, + {VK_MULTIPLY, FL_KP+'*'}, + {VK_ADD, FL_KP+'+'}, + {VK_SUBTRACT, FL_KP+'-'}, + {VK_DECIMAL, FL_KP+'.'}, + {VK_DIVIDE, FL_KP+'/'}, + {VK_NUMLOCK, FL_Num_Lock}, + {VK_SCROLL, FL_Scroll_Lock}, + {0xba, ';'}, + {0xbb, '='}, + {0xbc, ','}, + {0xbd, '-'}, + {0xbe, '.'}, + {0xbf, '/'}, + {0xc0, '`'}, + {0xdb, '['}, + {0xdc, '\\'}, + {0xdd, ']'}, + {0xde, '\''} +}; +static int ms2fltk(int vk, int extended) { + static unsigned short vklut[256]; + static unsigned short extendedlut[256]; + if (!vklut[1]) { // init the table + unsigned int i; + for (i = 0; i < 256; i++) vklut[i] = tolower(i); + for (i=VK_F1; i<=VK_F16; i++) vklut[i] = i+(FL_F-(VK_F1-1)); + for (i=VK_NUMPAD0; i<=VK_NUMPAD9; i++) vklut[i] = i+(FL_KP+'0'-VK_NUMPAD0); + for (i = 0; i < sizeof(vktab)/sizeof(*vktab); i++) { + vklut[vktab[i].vk] = vktab[i].fltk; + extendedlut[vktab[i].vk] = vktab[i].extended; + } + for (i = 0; i < 256; i++) if (!extendedlut[i]) extendedlut[i] = vklut[i]; + } + return extended ? extendedlut[vk] : vklut[vk]; +} + +#if USE_COLORMAP +extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx +#endif + + +///////////////////////////////////////////////////////////////////////////// +/// Win32 timers +/// + +struct Win32Timer +{ + UINT_PTR handle; + Fl_Timeout_Handler callback; + void *data; +}; +static Win32Timer* win32_timers; +static int win32_timer_alloc; +static int win32_timer_used; +static HWND s_TimerWnd; + +static void realloc_timers() +{ + if (win32_timer_alloc == 0) { + win32_timer_alloc = 8; + } + size_t size = sizeof(Win32Timer); + Win32Timer* new_timers = new Win32Timer[win32_timer_alloc * 2]; + memmove(new_timers, win32_timers, sizeof(Win32Timer) * win32_timer_used); + Win32Timer* delete_me = win32_timers; + win32_timers = new_timers; + delete [] delete_me; + win32_timer_alloc *= 2; +} + +static void delete_timer(Win32Timer& t) +{ + KillTimer(s_TimerWnd, t.handle); + memset(&t, 0, sizeof(Win32Timer)); +} + +/// END TIMERS +///////////////////////////////////////////////////////////////////////////// + +static Fl_Window* resize_bug_fix; + +extern void fl_save_pen(void); +extern void fl_restore_pen(void); + +static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + // Copy the message to fl_msg so add_handler code can see it, it is + // already there if this is called by DispatchMessage, but not if + // Windows calls this directly. + fl_msg.hwnd = hWnd; + fl_msg.message = uMsg; + fl_msg.wParam = wParam; + fl_msg.lParam = lParam; + //fl_msg.time = ??? + //fl_msg.pt = ??? + //fl_msg.lPrivate = ??? + + Fl_Window *window = fl_find(hWnd); + + if (window) switch (uMsg) { + + case WM_QUIT: // this should not happen? + Fl::fatal("WM_QUIT message"); + + case WM_CLOSE: // user clicked close box + Fl::handle(FL_CLOSE, window); + PostQuitMessage(0); + return 0; + + case WM_SYNCPAINT : + case WM_NCPAINT : + case WM_ERASEBKGND : + // Andreas Weitl - WM_SYNCPAINT needs to be passed to DefWindowProc + // so that Windows can generate the proper paint messages... + // Similarly, WM_NCPAINT and WM_ERASEBKGND need this, too... + break; + + case WM_PAINT: { + Fl_Region R; + Fl_X *i = Fl_X::i(window); + i->wait_for_expose = 0; + char redraw_whole_window = false; + if (!i->region && window->damage()) { + // Redraw the whole window... + i->region = CreateRectRgn(0, 0, window->w(), window->h()); + redraw_whole_window = true; + } + + // We need to merge WIN32's damage into FLTK's damage. + R = CreateRectRgn(0,0,0,0); + int r = GetUpdateRgn(hWnd,R,0); + if (r==NULLREGION && !redraw_whole_window) { + break; + } + + if (i->region) { + // Also tell WIN32 that we are drawing someplace else as well... + InvalidateRgn(hWnd, i->region, FALSE); + CombineRgn(i->region, i->region, R, RGN_OR); + XDestroyRegion(R); + } else { + i->region = R; + } + + window->clear_damage((uchar)(window->damage()|FL_DAMAGE_EXPOSE)); + // These next two statements should not be here, so that all update + // is deferred until Fl::flush() is called during idle. However WIN32 + // apparently is very unhappy if we don't obey it and draw right now. + // Very annoying! + fl_GetDC(hWnd); // Make sure we have a DC for this window... + fl_save_pen(); + i->flush(); + fl_restore_pen(); + if (window->type() == FL_DOUBLE_WINDOW) ValidateRgn(hWnd,0); + else ValidateRgn(hWnd,i->region); + window->clear_damage(); + } return 0; + + case WM_LBUTTONDOWN: mouse_event(window, 0, 1, wParam, lParam); return 0; + case WM_LBUTTONDBLCLK:mouse_event(window, 1, 1, wParam, lParam); return 0; + case WM_LBUTTONUP: mouse_event(window, 2, 1, wParam, lParam); return 0; + case WM_MBUTTONDOWN: mouse_event(window, 0, 2, wParam, lParam); return 0; + case WM_MBUTTONDBLCLK:mouse_event(window, 1, 2, wParam, lParam); return 0; + case WM_MBUTTONUP: mouse_event(window, 2, 2, wParam, lParam); return 0; + case WM_RBUTTONDOWN: mouse_event(window, 0, 3, wParam, lParam); return 0; + case WM_RBUTTONDBLCLK:mouse_event(window, 1, 3, wParam, lParam); return 0; + case WM_RBUTTONUP: mouse_event(window, 2, 3, wParam, lParam); return 0; + + case WM_MOUSEMOVE: +#ifdef USE_TRACK_MOUSE + if (Fl::belowmouse() != window) { + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = hWnd; + _TrackMouseEvent(&tme); + } +#endif // USE_TRACK_MOUSE + mouse_event(window, 3, 0, wParam, lParam); + return 0; + + case WM_MOUSELEAVE: + Fl::belowmouse(0); + if (!window->parent()) Fl::handle(FL_LEAVE, window); + break; + + case WM_SETFOCUS: + Fl::handle(FL_FOCUS, window); + break; + + case WM_KILLFOCUS: + Fl::handle(FL_UNFOCUS, window); + Fl::flush(); // it never returns to main loop when deactivated... + break; + + case WM_SHOWWINDOW: + if (!window->parent()) { + Fl::handle(wParam ? FL_SHOW : FL_HIDE, window); + } + break; + + case WM_ACTIVATEAPP: + // From eric@vfx.sel.sony.com, we should process WM_ACTIVATEAPP + // messages to restore the correct state of the shift/ctrl/alt/lock + // keys... Added control, shift, alt, and meta keys, and changed + // to use GetAsyncKeyState and do it when wParam is 1 + // (that means we have focus...) + if (wParam) + { + ulong state = 0; + if (GetAsyncKeyState(VK_CAPITAL)) state |= FL_CAPS_LOCK; + if (GetAsyncKeyState(VK_NUMLOCK)) state |= FL_NUM_LOCK; + if (GetAsyncKeyState(VK_SCROLL)) state |= FL_SCROLL_LOCK; + if (GetAsyncKeyState(VK_CONTROL)&~1) state |= FL_CTRL; + if (GetAsyncKeyState(VK_SHIFT)&~1) state |= FL_SHIFT; + if (GetAsyncKeyState(VK_MENU)) state |= FL_ALT; + if ((GetAsyncKeyState(VK_LWIN)|GetAsyncKeyState(VK_RWIN))&~1) state |= FL_META; + Fl::e_state = state; + return 0; + } + break; + + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + case WM_KEYUP: + case WM_SYSKEYUP: + // save the keysym until we figure out the characters: + Fl::e_keysym = ms2fltk(wParam,lParam&(1<<24)); + // See if TranslateMessage turned it into a WM_*CHAR message: + if (PeekMessage(&fl_msg, hWnd, WM_CHAR, WM_SYSDEADCHAR, PM_REMOVE)) { + uMsg = fl_msg.message; + wParam = fl_msg.wParam; + lParam = fl_msg.lParam; + } + case WM_DEADCHAR: + case WM_SYSDEADCHAR: + case WM_CHAR: + case WM_SYSCHAR: { + ulong state = Fl::e_state & 0xff000000; // keep the mouse button state + // if GetKeyState is expensive we might want to comment some of these out: + if (GetKeyState(VK_SHIFT)&~1) state |= FL_SHIFT; + if (GetKeyState(VK_CAPITAL)) state |= FL_CAPS_LOCK; + if (GetKeyState(VK_CONTROL)&~1) state |= FL_CTRL; + // Alt gets reported for the Alt-GR switch on foreign keyboards. + // so we need to check the event as well to get it right: + if ((lParam&(1<<29)) //same as GetKeyState(VK_MENU) + && uMsg != WM_CHAR) state |= FL_ALT; + if (GetKeyState(VK_NUMLOCK)) state |= FL_NUM_LOCK; + if ((GetKeyState(VK_LWIN)|GetKeyState(VK_RWIN))&~1) { + // WIN32 bug? GetKeyState returns garbage if the user hit the + // meta key to pop up start menu. Sigh. + if ((GetAsyncKeyState(VK_LWIN)|GetAsyncKeyState(VK_RWIN))&~1) + state |= FL_META; + } + if (GetKeyState(VK_SCROLL)) state |= FL_SCROLL_LOCK; + Fl::e_state = state; + if (lParam & (1<<31)) { // key up events. + if (Fl::handle(FL_KEYUP, window)) return 0; + break; + } + static char buffer[2]; + if (uMsg == WM_CHAR || uMsg == WM_SYSCHAR) { + buffer[0] = char(wParam); + Fl::e_length = 1; + } else if (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last) { + if (state & FL_NUM_LOCK) { + // Convert to regular keypress... + buffer[0] = Fl::e_keysym-FL_KP; + Fl::e_length = 1; + } else { + // Convert to special keypress... + buffer[0] = 0; + Fl::e_length = 0; + switch (Fl::e_keysym) { + case FL_KP + '0' : + Fl::e_keysym = FL_Insert; + break; + case FL_KP + '1' : + Fl::e_keysym = FL_End; + break; + case FL_KP + '2' : + Fl::e_keysym = FL_Down; + break; + case FL_KP + '3' : + Fl::e_keysym = FL_Page_Down; + break; + case FL_KP + '4' : + Fl::e_keysym = FL_Left; + break; + case FL_KP + '6' : + Fl::e_keysym = FL_Right; + break; + case FL_KP + '7' : + Fl::e_keysym = FL_Home; + break; + case FL_KP + '8' : + Fl::e_keysym = FL_Up; + break; + case FL_KP + '9' : + Fl::e_keysym = FL_Page_Up; + break; + case FL_KP + '.' : + Fl::e_keysym = FL_Delete; + break; + case FL_KP + '/' : + case FL_KP + '*' : + case FL_KP + '-' : + case FL_KP + '+' : + buffer[0] = Fl::e_keysym-FL_KP; + Fl::e_length = 1; + break; + } + } + } else { + buffer[0] = 0; + Fl::e_length = 0; + } + Fl::e_text = buffer; + // for (int i = lParam&0xff; i--;) + while (window->parent()) window = window->window(); + if (Fl::handle(FL_KEYBOARD,window)) return 0; + break;} + + case WM_MOUSEWHEEL: { + static int delta = 0; // running total of all motion + delta += (SHORT)(HIWORD(wParam)); + Fl::e_dy = -delta / WHEEL_DELTA; + delta += Fl::e_dy * WHEEL_DELTA; + if (Fl::e_dy) Fl::handle(FL_MOUSEWHEEL, window); + return 0; + } + + case WM_GETMINMAXINFO: + Fl_X::i(window)->set_minmax((LPMINMAXINFO)lParam); + break; + + case WM_SIZE: + if (!window->parent()) { + if (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXHIDE) { + Fl::handle(FL_HIDE, window); + } else { + Fl::handle(FL_SHOW, window); + resize_bug_fix = window; + window->size(LOWORD(lParam), HIWORD(lParam)); + } + } + break; + + case WM_MOVE: { + resize_bug_fix = window; + int nx = LOWORD(lParam); + int ny = HIWORD(lParam); + if (nx & 0x8000) nx -= 65536; + if (ny & 0x8000) ny -= 65536; + window->position(nx, ny); } + break; + + case WM_SETCURSOR: + if (LOWORD(lParam) == HTCLIENT) { + while (window->parent()) window = window->window(); + SetCursor(Fl_X::i(window)->cursor); + return 0; + } + break; + +#if USE_COLORMAP + case WM_QUERYNEWPALETTE : + fl_GetDC(hWnd); + if (fl_select_palette()) InvalidateRect(hWnd, NULL, FALSE); + break; + + case WM_PALETTECHANGED: + fl_GetDC(hWnd); + if ((HWND)wParam != hWnd && fl_select_palette()) UpdateColors(fl_gc); + break; + + case WM_CREATE : + fl_GetDC(hWnd); + fl_select_palette(); + break; +#endif + + case WM_DESTROYCLIPBOARD: + fl_i_own_selection[1] = 0; + return 1; + + case WM_RENDERALLFORMATS: + fl_i_own_selection[1] = 0; + // Windoze seems unhappy unless I do these two steps. Documentation + // seems to vary on whether opening the clipboard is necessary or + // is in fact wrong: + CloseClipboard(); + OpenClipboard(NULL); + // fall through... + case WM_RENDERFORMAT: { + HANDLE h = GlobalAlloc(GHND, fl_selection_length[1]+1); + if (h) { + LPSTR p = (LPSTR)GlobalLock(h); + memcpy(p, fl_selection_buffer[1], fl_selection_length[1]); + p[fl_selection_length[1]] = 0; + GlobalUnlock(h); + SetClipboardData(CF_TEXT, h); + } + // Windoze also seems unhappy if I don't do this. Documentation very + // unclear on what is correct: + if (fl_msg.message == WM_RENDERALLFORMATS) CloseClipboard(); + return 1;} + + default: + if (Fl::handle(0,0)) return 0; + break; + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + +//////////////////////////////////////////////////////////////// +// This function gets the dimensions of the top/left borders and +// the title bar, if there is one, based on the FL_BORDER, FL_MODAL +// and FL_NONMODAL flags, and on the window's size range. +// It returns the following values: +// +// value | border | title bar +// 0 | none | no +// 1 | fix | yes +// 2 | size | yes + +int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) { + int W, H, xoff, yoff, dx, dy; + int ret = bx = by = bt = 0; + + int fallback = 1; + if (!w->parent()) { + HWND hwnd = fl_xid(w); + if (hwnd) { + // The block below calculates the window borders by requesting the + // required decorated window rectangle for a desired client rectangle. + // If any part of the function above fails, we will drop to a + // fallback to get the best guess which is always available. + HWND hwnd = fl_xid(w); + // request the style flags of this window, as WIN32 sees them + LONG style = GetWindowLong(hwnd, GWL_STYLE); + LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE); + RECT r; + r.left = w->x(); + r.top = w->y(); + r.right = w->x()+w->w(); + r.bottom = w->y()+w->h(); + // get the decoration rectangle for the desired client rectangle + BOOL ok = AdjustWindowRectEx(&r, style, FALSE, exstyle); + if (ok) { + X = r.left; + Y = r.top; + W = r.right - r.left; + H = r.bottom - r.top; + bx = w->x() - r.left; + by = r.bottom - w->y() - w->h(); // height of the bootm frame + bt = w->y() - r.top - by; // height of top caption bar + xoff = bx; + yoff = by + bt; + dx = W - w->w(); + dy = H - w->h(); + if (w->size_range_set && (w->maxw != w->minw || w->maxh != w->minh)) + ret = 2; + else + ret = 1; + fallback = 0; + } + } + } + // This is the original (pre 1.1.7) routine to calculate window border sizes. + if (fallback) { + if (w->border() && !w->parent()) { + if (w->size_range_set && (w->maxw != w->minw || w->maxh != w->minh)) { + ret = 2; + bx = GetSystemMetrics(SM_CXSIZEFRAME); + by = GetSystemMetrics(SM_CYSIZEFRAME); + } else { + ret = 1; + bx = GetSystemMetrics(SM_CXFIXEDFRAME); + by = GetSystemMetrics(SM_CYFIXEDFRAME); + } + bt = GetSystemMetrics(SM_CYCAPTION); + } + //The coordinates of the whole window, including non-client area + xoff = bx; + yoff = by + bt; + dx = 2*bx; + dy = 2*by + bt; + X = w->x()-xoff; + Y = w->y()-yoff; + W = w->w()+dx; + H = w->h()+dy; + } + + //Proceed to positioning the window fully inside the screen, if possible + //Make border's lower right corner visible + int scr_x, scr_y, scr_w, scr_h; + Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h, X, Y); + if (scr_x+scr_w < X+W) X = scr_x+scr_w - W; + if (scr_y+scr_h < Y+H) Y = scr_y+scr_h - H; + //Make border's upper left corner visible + if (X<scr_x) X = scr_x; + if (Y<scr_y) Y = scr_y; + //Make client area's lower right corner visible + if (scr_x+scr_w < X+dx+ w->w()) X = scr_x+scr_w - w->w() - dx; + if (scr_y+scr_h < Y+dy+ w->h()) Y = scr_y+scr_h - w->h() - dy; + //Make client area's upper left corner visible + if (X+xoff < scr_x) X = scr_x-xoff; + if (Y+yoff < scr_y) Y = scr_y-yoff; + //Return the client area's top left corner in (X,Y) + X+=xoff; + Y+=yoff; + + return ret; +} + +//////////////////////////////////////////////////////////////// + +void Fl_Window::resize(int X,int Y,int W,int H) { + UINT flags = SWP_NOSENDCHANGING | SWP_NOZORDER + | SWP_NOACTIVATE | SWP_NOOWNERZORDER; + int is_a_resize = (W != w() || H != h()); + int resize_from_program = (this != resize_bug_fix); + if (!resize_from_program) resize_bug_fix = 0; + if (X != x() || Y != y()) { + set_flag(FL_FORCE_POSITION); + } else { + if (!is_a_resize) return; + flags |= SWP_NOMOVE; + } + if (is_a_resize) { + Fl_Group::resize(X,Y,W,H); + if (shown()) {redraw(); i->wait_for_expose = 1;} + } else { + x(X); y(Y); + flags |= SWP_NOSIZE; + } + if (!border()) flags |= SWP_NOACTIVATE; + if (resize_from_program && shown()) { + if (!resizable()) size_range(w(),h(),w(),h()); + int dummy_x, dummy_y, bt, bx, by; + //Ignore window managing when resizing, so that windows (and more + //specifically menus) can be moved offscreen. + if (Fl_X::fake_X_wm(this, dummy_x, dummy_y, bt, bx, by)) { + X -= bx; + Y -= by+bt; + W += 2*bx; + H += 2*by+bt; + } + SetWindowPos(i->xid, 0, X, Y, W, H, flags); + } +} + +//////////////////////////////////////////////////////////////// + +/* + * This silly little class remembers the name of all window classes + * we register to avoid double registration. It has the added bonus + * of freeing everything on application colse as well. + */ +class NameList { +public: + NameList() { name = (char**)malloc(sizeof(char**)); NName = 1; nName = 0; } + ~NameList() { + int i; + for (i=0; i<nName; i++) free(name[i]); + if (name) free(name); + } + void add_name(const char *n) { + if (NName==nName) { + NName += 5; + name = (char**)realloc(name, NName * sizeof(char*)); + } + name[nName++] = strdup(n); + } + char has_name(const char *n) { + int i; + for (i=0; i<nName; i++) { + if (strcmp(name[i], n)==0) return 1; + } + return 0; + } +private: + char **name; + int nName, NName; +}; + +void fl_fix_focus(); // in Fl.cxx + +char fl_show_iconic; // hack for Fl_Window::iconic() +// int fl_background_pixel = -1; // color to use for background +HCURSOR fl_default_cursor; +UINT fl_wake_msg = 0; +int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR + +Fl_X* Fl_X::make(Fl_Window* w) { + Fl_Group::current(0); // get rid of very common user bug: forgot end() + + static NameList class_name_list; + static const char *first_class_name = 0L; + const char *class_name = w->xclass(); + if (!class_name) class_name = first_class_name; // reuse first class name used + if (!class_name) class_name = "FLTK"; // default to create a "FLTK" WNDCLASS + if (!first_class_name) { + first_class_name = class_name; + } + + if (!class_name_list.has_name(class_name)) { + WNDCLASSEX wc; + memset(&wc, 0, sizeof(wc)); + wc.cbSize = sizeof(WNDCLASSEX); + // Documentation states a device context consumes about 800 bytes + // of memory... so who cares? If 800 bytes per window is what it + // takes to speed things up, I'm game. + //wc.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC | CS_DBLCLKS; + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; + wc.lpfnWndProc = (WNDPROC)WndProc; + wc.hInstance = fl_display; + if (!w->icon()) + w->icon((void *)LoadIcon(NULL, IDI_APPLICATION)); + wc.hIcon = wc.hIconSm = (HICON)w->icon(); + wc.hCursor = fl_default_cursor = LoadCursor(NULL, IDC_ARROW); + //uchar r,g,b; Fl::get_color(FL_GRAY,r,g,b); + //wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(r,g,b)); + wc.lpszClassName = class_name; + RegisterClassEx(&wc); + class_name_list.add_name(class_name); + } + + const char* message_name = "FLTK::ThreadWakeup"; + if (!fl_wake_msg) fl_wake_msg = RegisterWindowMessage(message_name); + + HWND parent; + DWORD style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS; + DWORD styleEx = WS_EX_LEFT; + + int xp = w->x(); + int yp = w->y(); + int wp = w->w(); + int hp = w->h(); + + int showit = 1; + + if (w->parent()) { + style |= WS_CHILD; + styleEx |= WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT; + parent = fl_xid(w->window()); + } else { + if (!w->size_range_set) { + if (w->resizable()) { + Fl_Widget *o = w->resizable(); + int minw = o->w(); if (minw > 100) minw = 100; + int minh = o->h(); if (minh > 100) minh = 100; + w->size_range(w->w() - o->w() + minw, w->h() - o->h() + minh, 0, 0); + } else { + w->size_range(w->w(), w->h(), w->w(), w->h()); + } + } + styleEx |= WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT; + int xwm = xp , ywm = yp , bt, bx, by; + switch (fake_X_wm(w, xwm, ywm, bt, bx, by)) { + // No border (used for menus) + case 0: style |= WS_POPUP; + styleEx |= WS_EX_TOOLWINDOW; + break; + + // Thin border and title bar + case 1: style |= WS_DLGFRAME | WS_CAPTION; break; + + // Thick, resizable border and title bar, with maximize button + case 2: style |= WS_THICKFRAME | WS_MAXIMIZEBOX | WS_CAPTION ; break; + } + if (by+bt) { + if (!w->modal()) style |= WS_SYSMENU | WS_MINIMIZEBOX; + wp += 2*bx; + hp += 2*by+bt; + } + if (!(w->flags() & Fl_Window::FL_FORCE_POSITION)) { + xp = yp = CW_USEDEFAULT; + } else { + if (!Fl::grab()) { + xp = xwm; yp = ywm; + w->x(xp);w->y(yp); + } + xp -= bx; + yp -= by+bt; + } + + parent = 0; + if (w->non_modal() && Fl_X::first && !fl_disable_transient_for) { + // find some other window to be "transient for": + Fl_Window* w = Fl_X::first->w; + while (w->parent()) w = w->window(); + parent = fl_xid(w); + if (!w->visible()) showit = 0; + } else if (Fl::grab()) parent = fl_xid(Fl::grab()); + } + + Fl_X* x = new Fl_X; + x->other_xid = 0; + x->setwindow(w); + x->region = 0; + x->private_dc = 0; + x->cursor = fl_default_cursor; + x->xid = CreateWindowEx( + styleEx, + class_name, w->label(), style, + xp, yp, wp, hp, + parent, + NULL, // menu + fl_display, + NULL // creation parameters + ); + x->next = Fl_X::first; + Fl_X::first = x; + + x->wait_for_expose = 1; + if (fl_show_iconic) {showit = 0; fl_show_iconic = 0;} + if (showit) { + w->set_visible(); + int old_event = Fl::e_number; + w->handle(Fl::e_number = FL_SHOW); // get child windows to appear + Fl::e_number = old_event; + w->redraw(); // force draw to happen + } + // If we've captured the mouse, we dont want do activate any + // other windows from the code, or we loose the capture. + ShowWindow(x->xid, !showit ? SW_SHOWMINNOACTIVE : + (Fl::grab() || (style & WS_POPUP)) ? SW_SHOWNOACTIVATE : SW_SHOWNORMAL); + + // Drag-n-drop requires GCC 3.x or a non-GNU compiler... +#if !defined(__GNUC__) || __GNUC__ >= 3 + // Register all windows for potential drag'n'drop operations + static char oleInitialized = 0; + if (!oleInitialized) { OleInitialize(0L); oleInitialized=1; } + + RegisterDragDrop(x->xid, flIDropTarget); +#endif // !__GNUC__ || __GNUC__ >= 3 + + if (w->modal()) {Fl::modal_ = w; fl_fix_focus();} + return x; +} + + + + +///////////////////////////////////////////////////////////////////////////// +/// Win32 timers +/// + + +static LRESULT CALLBACK s_TimerProc(HWND hwnd, UINT msg, + WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_TIMER: + { + unsigned int id = wParam - 1; + if (id < win32_timer_used && win32_timers[id].handle) { + Fl_Timeout_Handler cb = win32_timers[id].callback; + void* data = win32_timers[id].data; + delete_timer(win32_timers[id]); + if (cb) { + (*cb)(data); + } + } + } + return 0; + + default: + break; + } + + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void* data) +{ + repeat_timeout(time, cb, data); +} + +void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void* data) +{ + int timer_id = -1; + for (int i = 0; i < win32_timer_used; ++i) { + if ( !win32_timers[i].handle ) { + timer_id = i; + break; + } + } + if (timer_id == -1) { + if (win32_timer_used == win32_timer_alloc) { + realloc_timers(); + } + timer_id = win32_timer_used++; + } + unsigned int elapsed = (unsigned int)(time * 1000); + + if ( !s_TimerWnd ) { + const char* timer_class = "FLTimer"; + WNDCLASSEX wc; + memset(&wc, 0, sizeof(wc)); + wc.cbSize = sizeof (wc); + wc.style = CS_CLASSDC; + wc.lpfnWndProc = (WNDPROC)s_TimerProc; + wc.hInstance = fl_display; + wc.lpszClassName = timer_class; + ATOM atom = RegisterClassEx(&wc); + // create a zero size window to handle timer events + s_TimerWnd = CreateWindowEx(WS_EX_LEFT | WS_EX_TOOLWINDOW, + timer_class, "", + WS_POPUP, + 0, 0, 0, 0, + NULL, NULL, fl_display, NULL); + // just in case this OS won't let us create a 0x0 size window: + if (!s_TimerWnd) + s_TimerWnd = CreateWindowEx(WS_EX_LEFT | WS_EX_TOOLWINDOW, + timer_class, "", + WS_POPUP, + 0, 0, 1, 1, + NULL, NULL, fl_display, NULL); + ShowWindow(s_TimerWnd, SW_SHOWNOACTIVATE); + } + + win32_timers[timer_id].callback = cb; + win32_timers[timer_id].data = data; + + win32_timers[timer_id].handle = + SetTimer(s_TimerWnd, timer_id + 1, elapsed, NULL); +} + +int Fl::has_timeout(Fl_Timeout_Handler cb, void* data) +{ + for (int i = 0; i < win32_timer_used; ++i) { + Win32Timer& t = win32_timers[i]; + if (t.handle && t.callback == cb && t.data == data) { + return 1; + } + } + return 0; +} + +void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data) +{ + int i; + for (i = 0; i < win32_timer_used; ++i) { + Win32Timer& t = win32_timers[i]; + if (t.handle && t.callback == cb && + (t.data == data || data == NULL)) { + delete_timer(t); + } + } +} + +/// END TIMERS +///////////////////////////////////////////////////////////////////////////// + + + +//////////////////////////////////////////////////////////////// + +HINSTANCE fl_display = GetModuleHandle(NULL); + +void Fl_Window::size_range_() { + size_range_set = 1; +} + +void Fl_X::set_minmax(LPMINMAXINFO minmax) +{ + int td, wd, hd, dummy_x, dummy_y; + + fake_X_wm(w, dummy_x, dummy_y, td, wd, hd); + wd *= 2; + hd *= 2; + hd += td; + + minmax->ptMinTrackSize.x = w->minw + wd; + minmax->ptMinTrackSize.y = w->minh + hd; + if (w->maxw) { + minmax->ptMaxTrackSize.x = w->maxw + wd; + minmax->ptMaxSize.x = w->maxw + wd; + } + if (w->maxh) { + minmax->ptMaxTrackSize.y = w->maxh + hd; + minmax->ptMaxSize.y = w->maxh + hd; + } +} + +//////////////////////////////////////////////////////////////// + +#include <FL/filename.H> // need so FL_EXPORT fl_filename_name works + +// returns pointer to the filename, or null if name ends with '/' +const char *fl_filename_name(const char *name) { + const char *p,*q; + if (!name) return (0); + q = name; + if (q[0] && q[1]==':') q += 2; // skip leading drive letter + for (p = q; *p; p++) if (*p == '/' || *p == '\\') q = p+1; + return q; +} + +void Fl_Window::label(const char *name,const char *iname) { + Fl_Widget::label(name); + iconlabel_ = iname; + if (shown() && !parent()) { + if (!name) name = ""; + SetWindowText(i->xid, name); + // if (!iname) iname = fl_filename_name(name); + // should do something with iname here... + } +} + +//////////////////////////////////////////////////////////////// +// Implement the virtual functions for the base Fl_Window class: + +// If the box is a filled rectangle, we can make the redisplay *look* +// faster by using X's background pixel erasing. We can make it +// actually *be* faster by drawing the frame only, this is done by +// setting fl_boxcheat, which is seen by code in fl_drawbox.cxx: +// For WIN32 it looks like all windows share a background color, so +// I use FL_GRAY for this and only do this cheat for windows that are +// that color. +// Actually it is totally disabled. +// Fl_Widget *fl_boxcheat; +//static inline int can_boxcheat(uchar b) {return (b==1 || (b&2) && b<=15);} + +void Fl_Window::show() { + image(Fl::scheme_bg_); + if (Fl::scheme_bg_) { + labeltype(FL_NORMAL_LABEL); + align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP); + } else { + labeltype(FL_NO_LABEL); + } + if (!shown()) { + // if (can_boxcheat(box())) fl_background_pixel = fl_xpixel(color()); + Fl_X::make(this); + } else { + // Once again, we would lose the capture if we activated the window. + if (IsIconic(i->xid)) OpenIcon(i->xid); + if (!fl_capture) BringWindowToTop(i->xid); + //ShowWindow(i->xid,fl_capture?SW_SHOWNOACTIVATE:SW_RESTORE); + } +} + +Fl_Window *Fl_Window::current_; +// the current context +HDC fl_gc = 0; +// the current window handle, initially set to -1 so we can correctly +// allocate fl_GetDC(0) +HWND fl_window = NULL; + +// Here we ensure only one GetDC is ever in place. +HDC fl_GetDC(HWND w) { + if (fl_gc) { + if (w == fl_window && fl_window != NULL) return fl_gc; + if (fl_window) fl_release_dc(fl_window, fl_gc); // ReleaseDC + } + fl_gc = GetDC(w); + fl_save_dc(w, fl_gc); + fl_window = w; + // calling GetDC seems to always reset these: (?) + SetTextAlign(fl_gc, TA_BASELINE|TA_LEFT); + SetBkMode(fl_gc, TRANSPARENT); + return fl_gc; +} + +// make X drawing go into this window (called by subclass flush() impl.) +void Fl_Window::make_current() { + fl_GetDC(fl_xid(this)); + +#if USE_COLORMAP + // Windows maintains a hardware and software color palette; the + // SelectPalette() call updates the current soft->hard mapping + // for all drawing calls, so we must select it here before any + // code does any drawing... + + fl_select_palette(); +#endif // USE_COLORMAP + + current_ = this; + fl_clip_region(0); +} + +/* Make sure that all allocated fonts are released. This works only if + Fl::run() is allowed to exit by closing all windows. Calling 'exit(int)' + will not automatically free any fonts. */ +void fl_free_fonts(void) +{ +// remove the Fl_FontSize chains + int i; + Fl_Fontdesc * s; + Fl_FontSize * f; + Fl_FontSize * ff; + for (i=0; i<FL_FREE_FONT; i++) { + s = fl_fonts + i; + for (f=s->first; f; f=ff) { + ff = f->next; + delete(f); + s->first = ff; + } + } +} + + +/////////////////////////////////////////////////////////////////////// +// +// The following routines help fix a problem with the leaking of Windows +// Device Context (DC) objects. The 'proper' protocol is for a program to +// acquire a DC, save its state, do the modifications needed for drawing, +// perform the drawing, restore the initial state, and release the DC. In +// FLTK, the save and restore steps have previously been omitted and DCs are +// not properly released, leading to a great number of DC leaks. As some +// Windows "OSs" will hang when any process exceeds roughly 10,000 GDI objects, +// it is important to control GDI leaks, which are much more important than memory +// leaks. The following struct, global variable, and routines help implement +// the above protocol for those cases where the GetDC and RestoreDC are not in +// the same routine. For each GetDC, fl_save_dc is used to create an entry in +// a linked list that saves the window handle, the DC handle, and the initial +// state. When the DC is to be released, 'fl_release_dc' is called. It restores +// the initial state and releases the DC. When the program exits, 'fl_cleanup_dc_list' +// frees any remaining nodes in the list. + +struct Win_DC_List { // linked list + HWND window; // window handle + HDC dc; // device context handle + int saved_dc; // initial state of DC + Win_DC_List * next; // pointer to next item +}; + +static Win_DC_List * win_DC_list = 0; + +void fl_save_dc( HWND w, HDC dc) { + Win_DC_List * t; + t = new Win_DC_List; + t->window = w; + t->dc = dc; + t->saved_dc = SaveDC(dc); + if (win_DC_list) + t->next = win_DC_list; + else + t->next = NULL; + win_DC_list = t; +} + +void fl_release_dc(HWND w, HDC dc) { + Win_DC_List * t= win_DC_list; + Win_DC_List * prev = 0; + if (!t) + return; + do { + if (t->dc == dc) { + RestoreDC(dc, t->saved_dc); + ReleaseDC(w, dc); + if (!prev) { + win_DC_list = t->next; // delete first item + } else { + prev->next = t->next; // one in the middle + } + delete (t); + return; + } + prev = t; + t = t->next; + } while (t); +} + +void fl_cleanup_dc_list(void) { // clean up the list + Win_DC_List * t = win_DC_list; + if (!t)return; + do { + RestoreDC(t->dc, t->saved_dc); + ReleaseDC(t->window, t->dc); + win_DC_list = t->next; + delete (t); + t = win_DC_list; + } while(t); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/Fl_x.cxx b/Utilities/FLTK/src/Fl_x.cxx new file mode 100644 index 0000000000..cde677408d --- /dev/null +++ b/Utilities/FLTK/src/Fl_x.cxx @@ -0,0 +1,1354 @@ +// +// "$Id$" +// +// X specific code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2006 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifdef WIN32 +//# include "Fl_win32.cxx" +#elif defined(__APPLE__) +//# include "Fl_mac.cxx" +#else + +# define CONSOLIDATE_MOTION 1 +/**** Define this if your keyboard lacks a backspace key... ****/ +/* #define BACKSPACE_HACK 1 */ + +# include <FL/Fl.H> +# include <FL/x.H> +# include <FL/Fl_Window.H> +# include <stdio.h> +# include <stdlib.h> +# include "flstring.h" +# include <unistd.h> +# include <sys/time.h> + +//////////////////////////////////////////////////////////////// +// interface to poll/select call: + +# if USE_POLL + +# include <poll.h> +static pollfd *pollfds = 0; + +# else +# if HAVE_SYS_SELECT_H +# include <sys/select.h> +# endif /* HAVE_SYS_SELECT_H */ + +// The following #define is only needed for HP-UX 9.x and earlier: +//#define select(a,b,c,d,e) select((a),(int *)(b),(int *)(c),(int *)(d),(e)) + +static fd_set fdsets[3]; +static int maxfd; +# define POLLIN 1 +# define POLLOUT 4 +# define POLLERR 8 + +# endif /* USE_POLL */ + +static int nfds = 0; +static int fd_array_size = 0; +struct FD { +# if !USE_POLL + int fd; + short events; +# endif + void (*cb)(int, void*); + void* arg; +}; + +static FD *fd = 0; + +void Fl::add_fd(int n, int events, void (*cb)(int, void*), void *v) { + remove_fd(n,events); + int i = nfds++; + if (i >= fd_array_size) { + FD *temp; + fd_array_size = 2*fd_array_size+1; + + if (!fd) temp = (FD*)malloc(fd_array_size*sizeof(FD)); + else temp = (FD*)realloc(fd, fd_array_size*sizeof(FD)); + + if (!temp) return; + fd = temp; + +# if USE_POLL + pollfd *tpoll; + + if (!pollfds) tpoll = (pollfd*)malloc(fd_array_size*sizeof(pollfd)); + else tpoll = (pollfd*)realloc(pollfds, fd_array_size*sizeof(pollfd)); + + if (!tpoll) return; + pollfds = tpoll; +# endif + } + fd[i].cb = cb; + fd[i].arg = v; +# if USE_POLL + pollfds[i].fd = n; + pollfds[i].events = events; +# else + fd[i].fd = n; + fd[i].events = events; + if (events & POLLIN) FD_SET(n, &fdsets[0]); + if (events & POLLOUT) FD_SET(n, &fdsets[1]); + if (events & POLLERR) FD_SET(n, &fdsets[2]); + if (n > maxfd) maxfd = n; +# endif +} + +void Fl::add_fd(int n, void (*cb)(int, void*), void* v) { + Fl::add_fd(n, POLLIN, cb, v); +} + +void Fl::remove_fd(int n, int events) { + int i,j; + maxfd = -1; // recalculate maxfd on the fly + for (i=j=0; i<nfds; i++) { +# if USE_POLL + if (pollfds[i].fd == n) { + int e = pollfds[i].events & ~events; + if (!e) continue; // if no events left, delete this fd + pollfds[j].events = e; + } +# else + if (fd[i].fd == n) { + int e = fd[i].events & ~events; + if (!e) continue; // if no events left, delete this fd + fd[i].events = e; + } +# endif + if (fd[i].fd > maxfd) maxfd = fd[i].fd; + // move it down in the array if necessary: + if (j<i) { + fd[j] = fd[i]; +# if USE_POLL + pollfds[j] = pollfds[i]; +# endif + } + j++; + } + nfds = j; +# if !USE_POLL + if (events & POLLIN) FD_CLR(n, &fdsets[0]); + if (events & POLLOUT) FD_CLR(n, &fdsets[1]); + if (events & POLLERR) FD_CLR(n, &fdsets[2]); +# endif +} + +void Fl::remove_fd(int n) { + remove_fd(n, -1); +} + +#if CONSOLIDATE_MOTION +static Fl_Window* send_motion; +extern Fl_Window* fl_xmousewin; +#endif +static bool in_a_window; // true if in any of our windows, even destroyed ones +static void do_queued_events() { + in_a_window = true; + while (XEventsQueued(fl_display,QueuedAfterReading)) { + XEvent xevent; + XNextEvent(fl_display, &xevent); + fl_handle(xevent); + } + // we send FL_LEAVE only if the mouse did not enter some other window: + if (!in_a_window) Fl::handle(FL_LEAVE, 0); +#if CONSOLIDATE_MOTION + else if (send_motion == fl_xmousewin) { + send_motion = 0; + Fl::handle(FL_MOVE, fl_xmousewin); + } +#endif +} + +// these pointers are set by the Fl::lock() function: +static void nothing() {} +void (*fl_lock_function)() = nothing; +void (*fl_unlock_function)() = nothing; + +// This is never called with time_to_wait < 0.0: +// It should return negative on error, 0 if nothing happens before +// timeout, and >0 if any callbacks were done. +int fl_wait(double time_to_wait) { + + // OpenGL and other broken libraries call XEventsQueued + // unnecessarily and thus cause the file descriptor to not be ready, + // so we must check for already-read events: + if (fl_display && XQLength(fl_display)) {do_queued_events(); return 1;} + +# if !USE_POLL + fd_set fdt[3]; + fdt[0] = fdsets[0]; + fdt[1] = fdsets[1]; + fdt[2] = fdsets[2]; +# endif + int n; + + fl_unlock_function(); + + if (time_to_wait < 2147483.648) { +# if USE_POLL + n = ::poll(pollfds, nfds, int(time_to_wait*1000 + .5)); +# else + timeval t; + t.tv_sec = int(time_to_wait); + t.tv_usec = int(1000000 * (time_to_wait-t.tv_sec)); + n = ::select(maxfd+1,&fdt[0],&fdt[1],&fdt[2],&t); +# endif + } else { +# if USE_POLL + n = ::poll(pollfds, nfds, -1); +# else + n = ::select(maxfd+1,&fdt[0],&fdt[1],&fdt[2],0); +# endif + } + + fl_lock_function(); + + if (n > 0) { + for (int i=0; i<nfds; i++) { +# if USE_POLL + if (pollfds[i].revents) fd[i].cb(pollfds[i].fd, fd[i].arg); +# else + int f = fd[i].fd; + short revents = 0; + if (FD_ISSET(f,&fdt[0])) revents |= POLLIN; + if (FD_ISSET(f,&fdt[1])) revents |= POLLOUT; + if (FD_ISSET(f,&fdt[2])) revents |= POLLERR; + if (fd[i].events & revents) fd[i].cb(f, fd[i].arg); +# endif + } + } + return n; +} + +// fl_ready() is just like fl_wait(0.0) except no callbacks are done: +int fl_ready() { + if (XQLength(fl_display)) return 1; +# if USE_POLL + return ::poll(pollfds, nfds, 0); +# else + timeval t; + t.tv_sec = 0; + t.tv_usec = 0; + fd_set fdt[3]; + fdt[0] = fdsets[0]; + fdt[1] = fdsets[1]; + fdt[2] = fdsets[2]; + return ::select(maxfd+1,&fdt[0],&fdt[1],&fdt[2],&t); +# endif +} + +//////////////////////////////////////////////////////////////// + +Display *fl_display; +Window fl_message_window; +int fl_screen; +XVisualInfo *fl_visual; +Colormap fl_colormap; + +static Atom WM_DELETE_WINDOW; +static Atom WM_PROTOCOLS; +static Atom fl_MOTIF_WM_HINTS; +static Atom TARGETS; +static Atom CLIPBOARD; +Atom fl_XdndAware; +Atom fl_XdndSelection; +Atom fl_XdndEnter; +Atom fl_XdndTypeList; +Atom fl_XdndPosition; +Atom fl_XdndLeave; +Atom fl_XdndDrop; +Atom fl_XdndStatus; +Atom fl_XdndActionCopy; +Atom fl_XdndFinished; +//Atom fl_XdndProxy; +Atom fl_XdndURIList; + + +static void fd_callback(int,void *) { + do_queued_events(); +} + +extern "C" { + static int io_error_handler(Display*) { + Fl::fatal("X I/O error"); + return 0; + } + + static int xerror_handler(Display* d, XErrorEvent* e) { + char buf1[128], buf2[128]; + sprintf(buf1, "XRequest.%d", e->request_code); + XGetErrorDatabaseText(d,"",buf1,buf1,buf2,128); + XGetErrorText(d, e->error_code, buf1, 128); + Fl::warning("%s: %s 0x%lx", buf2, buf1, e->resourceid); + return 0; + } +} + +void fl_open_display() { + if (fl_display) return; + + XSetIOErrorHandler(io_error_handler); + XSetErrorHandler(xerror_handler); + + Display *d = XOpenDisplay(0); + if (!d) Fl::fatal("Can't open display: %s",XDisplayName(0)); + + fl_open_display(d); +} + +void fl_open_display(Display* d) { + fl_display = d; + + WM_DELETE_WINDOW = XInternAtom(d, "WM_DELETE_WINDOW", 0); + WM_PROTOCOLS = XInternAtom(d, "WM_PROTOCOLS", 0); + fl_MOTIF_WM_HINTS = XInternAtom(d, "_MOTIF_WM_HINTS", 0); + TARGETS = XInternAtom(d, "TARGETS", 0); + CLIPBOARD = XInternAtom(d, "CLIPBOARD", 0); + fl_XdndAware = XInternAtom(d, "XdndAware", 0); + fl_XdndSelection = XInternAtom(d, "XdndSelection", 0); + fl_XdndEnter = XInternAtom(d, "XdndEnter", 0); + fl_XdndTypeList = XInternAtom(d, "XdndTypeList", 0); + fl_XdndPosition = XInternAtom(d, "XdndPosition", 0); + fl_XdndLeave = XInternAtom(d, "XdndLeave", 0); + fl_XdndDrop = XInternAtom(d, "XdndDrop", 0); + fl_XdndStatus = XInternAtom(d, "XdndStatus", 0); + fl_XdndActionCopy = XInternAtom(d, "XdndActionCopy", 0); + fl_XdndFinished = XInternAtom(d, "XdndFinished", 0); + //fl_XdndProxy = XInternAtom(d, "XdndProxy", 0); + fl_XdndEnter = XInternAtom(d, "XdndEnter", 0); + fl_XdndURIList = XInternAtom(d, "text/uri-list", 0); + + Fl::add_fd(ConnectionNumber(d), POLLIN, fd_callback); + + fl_screen = DefaultScreen(d); + + fl_message_window = + XCreateSimpleWindow(d, RootWindow(d,fl_screen), 0,0,1,1,0, 0, 0); + +// construct an XVisualInfo that matches the default Visual: + XVisualInfo templt; int num; + templt.visualid = XVisualIDFromVisual(DefaultVisual(d, fl_screen)); + fl_visual = XGetVisualInfo(d, VisualIDMask, &templt, &num); + fl_colormap = DefaultColormap(d, fl_screen); + +#if !USE_COLORMAP + Fl::visual(FL_RGB); +#endif +} + +void fl_close_display() { + Fl::remove_fd(ConnectionNumber(fl_display)); + XCloseDisplay(fl_display); +} + +int Fl::h() { + fl_open_display(); + return DisplayHeight(fl_display,fl_screen); +} + +int Fl::w() { + fl_open_display(); + return DisplayWidth(fl_display,fl_screen); +} + +void Fl::get_mouse(int &xx, int &yy) { + fl_open_display(); + Window root = RootWindow(fl_display, fl_screen); + Window c; int mx,my,cx,cy; unsigned int mask; + XQueryPointer(fl_display,root,&root,&c,&mx,&my,&cx,&cy,&mask); + xx = mx; + yy = my; +} + +//////////////////////////////////////////////////////////////// +// Code used for paste and DnD into the program: + +Fl_Widget *fl_selection_requestor; +char *fl_selection_buffer[2]; +int fl_selection_length[2]; +int fl_selection_buffer_length[2]; +char fl_i_own_selection[2]; + +// Call this when a "paste" operation happens: +void Fl::paste(Fl_Widget &receiver, int clipboard) { + if (fl_i_own_selection[clipboard]) { + // We already have it, do it quickly without window server. + // Notice that the text is clobbered if set_selection is + // called in response to FL_PASTE! + Fl::e_text = fl_selection_buffer[clipboard]; + Fl::e_length = fl_selection_length[clipboard]; + if (!Fl::e_text) Fl::e_text = (char *)""; + receiver.handle(FL_PASTE); + return; + } + // otherwise get the window server to return it: + fl_selection_requestor = &receiver; + Atom property = clipboard ? CLIPBOARD : XA_PRIMARY; + XConvertSelection(fl_display, property, XA_STRING, property, + fl_xid(Fl::first_window()), fl_event_time); +} + +Window fl_dnd_source_window; +Atom *fl_dnd_source_types; // null-terminated list of data types being supplied +Atom fl_dnd_type; +Atom fl_dnd_source_action; +Atom fl_dnd_action; + +void fl_sendClientMessage(Window window, Atom message, + unsigned long d0, + unsigned long d1=0, + unsigned long d2=0, + unsigned long d3=0, + unsigned long d4=0) +{ + XEvent e; + e.xany.type = ClientMessage; + e.xany.window = window; + e.xclient.message_type = message; + e.xclient.format = 32; + e.xclient.data.l[0] = (long)d0; + e.xclient.data.l[1] = (long)d1; + e.xclient.data.l[2] = (long)d2; + e.xclient.data.l[3] = (long)d3; + e.xclient.data.l[4] = (long)d4; + XSendEvent(fl_display, window, 0, 0, &e); +} + +//////////////////////////////////////////////////////////////// +// Code for copying to clipboard and DnD out of the program: + +void Fl::copy(const char *stuff, int len, int clipboard) { + if (!stuff || len<0) return; + if (len+1 > fl_selection_buffer_length[clipboard]) { + delete[] fl_selection_buffer[clipboard]; + fl_selection_buffer[clipboard] = new char[len+100]; + fl_selection_buffer_length[clipboard] = len+100; + } + memcpy(fl_selection_buffer[clipboard], stuff, len); + fl_selection_buffer[clipboard][len] = 0; // needed for direct paste + fl_selection_length[clipboard] = len; + fl_i_own_selection[clipboard] = 1; + Atom property = clipboard ? CLIPBOARD : XA_PRIMARY; + XSetSelectionOwner(fl_display, property, fl_message_window, fl_event_time); +} + +//////////////////////////////////////////////////////////////// + +const XEvent* fl_xevent; // the current x event +ulong fl_event_time; // the last timestamp from an x event + +char fl_key_vector[32]; // used by Fl::get_key() + +// Record event mouse position and state from an XEvent: + +static int px, py; +static ulong ptime; + +static void set_event_xy() { +# if CONSOLIDATE_MOTION + send_motion = 0; +# endif + Fl::e_x_root = fl_xevent->xbutton.x_root; + Fl::e_x = fl_xevent->xbutton.x; + Fl::e_y_root = fl_xevent->xbutton.y_root; + Fl::e_y = fl_xevent->xbutton.y; + Fl::e_state = fl_xevent->xbutton.state << 16; + fl_event_time = fl_xevent->xbutton.time; +# ifdef __sgi + // get the meta key off PC keyboards: + if (fl_key_vector[18]&0x18) Fl::e_state |= FL_META; +# endif + // turn off is_click if enough time or mouse movement has passed: + if (abs(Fl::e_x_root-px)+abs(Fl::e_y_root-py) > 3 || + fl_event_time >= ptime+1000) + Fl::e_is_click = 0; +} + +// if this is same event as last && is_click, increment click count: +static inline void checkdouble() { + if (Fl::e_is_click == Fl::e_keysym) + Fl::e_clicks++; + else { + Fl::e_clicks = 0; + Fl::e_is_click = Fl::e_keysym; + } + px = Fl::e_x_root; + py = Fl::e_y_root; + ptime = fl_event_time; +} + +static Fl_Window* resize_bug_fix; + +extern "C" { + static Bool fake_keyup_test(Display*, XEvent* event, char* previous) { + return + event->type == KeyPress && + event->xkey.keycode == ((XKeyEvent*)previous)->keycode && + event->xkey.time == ((XKeyEvent*)previous)->time; + } +} + +//////////////////////////////////////////////////////////////// + +static char unknown[] = "<unknown>"; +const int unknown_len = 10; + +int fl_handle(const XEvent& thisevent) +{ + XEvent xevent = thisevent; + fl_xevent = &thisevent; + Window xid = xevent.xany.window; + + switch (xevent.type) { + + case KeymapNotify: + memcpy(fl_key_vector, xevent.xkeymap.key_vector, 32); + return 0; + + case MappingNotify: + XRefreshKeyboardMapping((XMappingEvent*)&xevent.xmapping); + return 0; + + case SelectionNotify: { + if (!fl_selection_requestor) return 0; + static unsigned char* buffer; + if (buffer) {XFree(buffer); buffer = 0;} + long bytesread = 0; + if (fl_xevent->xselection.property) for (;;) { + // The Xdnd code pastes 64K chunks together, possibly to avoid + // bugs in X servers, or maybe to avoid an extra round-trip to + // get the property length. I copy this here: + Atom actual; int format; unsigned long count, remaining; + unsigned char* portion; + if (XGetWindowProperty(fl_display, + fl_xevent->xselection.requestor, + fl_xevent->xselection.property, + bytesread/4, 65536, 1, 0, + &actual, &format, &count, &remaining, + &portion)) break; // quit on error + if (bytesread) { // append to the accumulated buffer + buffer = (unsigned char*)realloc(buffer, bytesread+count*format/8+remaining); + memcpy(buffer+bytesread, portion, count*format/8); + XFree(portion); + } else { // Use the first section without moving the memory: + buffer = portion; + } + bytesread += count*format/8; + if (!remaining) break; + } + Fl::e_text = buffer ? (char*)buffer : (char *)""; + Fl::e_length = bytesread; + int old_event = Fl::e_number; + fl_selection_requestor->handle(Fl::e_number = FL_PASTE); + Fl::e_number = old_event; + // Detect if this paste is due to Xdnd by the property name (I use + // XA_SECONDARY for that) and send an XdndFinished message. It is not + // clear if this has to be delayed until now or if it can be done + // immediatly after calling XConvertSelection. + if (fl_xevent->xselection.property == XA_SECONDARY && + fl_dnd_source_window) { + fl_sendClientMessage(fl_dnd_source_window, fl_XdndFinished, + fl_xevent->xselection.requestor); + fl_dnd_source_window = 0; // don't send a second time + } + return 1;} + + case SelectionClear: { + int clipboard = fl_xevent->xselectionclear.selection == CLIPBOARD; + fl_i_own_selection[clipboard] = 0; + return 1;} + + case SelectionRequest: { + XSelectionEvent e; + e.type = SelectionNotify; + e.requestor = fl_xevent->xselectionrequest.requestor; + e.selection = fl_xevent->xselectionrequest.selection; + int clipboard = e.selection == CLIPBOARD; + e.target = fl_xevent->xselectionrequest.target; + e.time = fl_xevent->xselectionrequest.time; + e.property = fl_xevent->xselectionrequest.property; + if (e.target == TARGETS) { + Atom a = XA_STRING; + XChangeProperty(fl_display, e.requestor, e.property, + XA_ATOM, sizeof(Atom)*8, 0, (unsigned char*)&a, + sizeof(Atom)); + } else if (/*e.target == XA_STRING &&*/ fl_selection_length[clipboard]) { + XChangeProperty(fl_display, e.requestor, e.property, + e.target, 8, 0, + (unsigned char *)fl_selection_buffer[clipboard], + fl_selection_length[clipboard]); + } else { +// char* x = XGetAtomName(fl_display,e.target); +// fprintf(stderr,"selection request of %s\n",x); +// XFree(x); + e.property = 0; + } + XSendEvent(fl_display, e.requestor, 0, 0, (XEvent *)&e);} + return 1; + + // events where interesting window id is in a different place: + case CirculateNotify: + case CirculateRequest: + case ConfigureNotify: + case ConfigureRequest: + case CreateNotify: + case DestroyNotify: + case GravityNotify: + case MapNotify: + case MapRequest: + case ReparentNotify: + case UnmapNotify: + xid = xevent.xmaprequest.window; + break; + } + + int event = 0; + Fl_Window* window = fl_find(xid); + + if (window) switch (xevent.type) { + + case ClientMessage: { + Atom message = fl_xevent->xclient.message_type; + const long* data = fl_xevent->xclient.data.l; + if ((Atom)(data[0]) == WM_DELETE_WINDOW) { + event = FL_CLOSE; + } else if (message == fl_XdndEnter) { + fl_xmousewin = window; + in_a_window = true; + fl_dnd_source_window = data[0]; + // version number is data[1]>>24 +// printf("XdndEnter, version %ld\n", data[1] >> 24); + if (data[1]&1) { + // get list of data types: + Atom actual; int format; unsigned long count, remaining; + unsigned char *buffer = 0; + XGetWindowProperty(fl_display, fl_dnd_source_window, fl_XdndTypeList, + 0, 0x8000000L, False, XA_ATOM, &actual, &format, + &count, &remaining, &buffer); + if (actual != XA_ATOM || format != 32 || count<4 || !buffer) + goto FAILED; + delete [] fl_dnd_source_types; + fl_dnd_source_types = new Atom[count+1]; + for (unsigned i = 0; i < count; i++) + fl_dnd_source_types[i] = ((Atom*)buffer)[i]; + fl_dnd_source_types[count] = 0; + } else { + FAILED: + // less than four data types, or if the above messes up: + if (!fl_dnd_source_types) fl_dnd_source_types = new Atom[4]; + fl_dnd_source_types[0] = data[2]; + fl_dnd_source_types[1] = data[3]; + fl_dnd_source_types[2] = data[4]; + fl_dnd_source_types[3] = 0; + } + + // Loop through the source types and pick the first text type... + int i; + + for (i = 0; fl_dnd_source_types[i]; i ++) + { +// printf("fl_dnd_source_types[%d] = %ld (%s)\n", i, +// fl_dnd_source_types[i], +// XGetAtomName(fl_display, fl_dnd_source_types[i])); + + if (!strncmp(XGetAtomName(fl_display, fl_dnd_source_types[i]), + "text/", 5)) + break; + } + + if (fl_dnd_source_types[i]) + fl_dnd_type = fl_dnd_source_types[i]; + else + fl_dnd_type = fl_dnd_source_types[0]; + + event = FL_DND_ENTER; + Fl::e_text = unknown; + Fl::e_length = unknown_len; + break; + + } else if (message == fl_XdndPosition) { + fl_xmousewin = window; + in_a_window = true; + fl_dnd_source_window = data[0]; + Fl::e_x_root = data[2]>>16; + Fl::e_y_root = data[2]&0xFFFF; + if (window) { + Fl::e_x = Fl::e_x_root-window->x(); + Fl::e_y = Fl::e_y_root-window->y(); + } + fl_event_time = data[3]; + fl_dnd_source_action = data[4]; + fl_dnd_action = fl_XdndActionCopy; + Fl::e_text = unknown; + Fl::e_length = unknown_len; + int accept = Fl::handle(FL_DND_DRAG, window); + fl_sendClientMessage(data[0], fl_XdndStatus, + fl_xevent->xclient.window, + accept ? 1 : 0, + 0, // used for xy rectangle to not send position inside + 0, // used for width+height of rectangle + accept ? fl_dnd_action : None); + return 1; + + } else if (message == fl_XdndLeave) { + fl_dnd_source_window = 0; // don't send a finished message to it + event = FL_DND_LEAVE; + Fl::e_text = unknown; + Fl::e_length = unknown_len; + break; + + } else if (message == fl_XdndDrop) { + fl_xmousewin = window; + in_a_window = true; + fl_dnd_source_window = data[0]; + fl_event_time = data[2]; + Window to_window = fl_xevent->xclient.window; + Fl::e_text = unknown; + Fl::e_length = unknown_len; + if (Fl::handle(FL_DND_RELEASE, window)) { + fl_selection_requestor = Fl::belowmouse(); + XConvertSelection(fl_display, fl_XdndSelection, + fl_dnd_type, XA_SECONDARY, + to_window, fl_event_time); + } else { + // Send the finished message if I refuse the drop. + // It is not clear whether I can just send finished always, + // or if I have to wait for the SelectionNotify event as the + // code is currently doing. + fl_sendClientMessage(fl_dnd_source_window, fl_XdndFinished, to_window); + fl_dnd_source_window = 0; + } + return 1; + + } + break;} + + case UnmapNotify: + event = FL_HIDE; + break; + + case Expose: + Fl_X::i(window)->wait_for_expose = 0; +# if 0 + // try to keep windows on top even if WM_TRANSIENT_FOR does not work: + // opaque move/resize window managers do not like this, so I disabled it. + if (Fl::first_window()->non_modal() && window != Fl::first_window()) + Fl::first_window()->show(); +# endif + + case GraphicsExpose: + window->damage(FL_DAMAGE_EXPOSE, xevent.xexpose.x, xevent.xexpose.y, + xevent.xexpose.width, xevent.xexpose.height); + return 1; + + case FocusIn: + event = FL_FOCUS; + break; + + case FocusOut: + event = FL_UNFOCUS; + break; + + case KeyPress: + case KeyRelease: { + KEYPRESS: + int keycode = xevent.xkey.keycode; + fl_key_vector[keycode/8] |= (1 << (keycode%8)); + static char buffer[21]; + int len; + KeySym keysym; + if (xevent.type == KeyPress) { + event = FL_KEYDOWN; + //static XComposeStatus compose; + len = XLookupString((XKeyEvent*)&(xevent.xkey), + buffer, 20, &keysym, 0/*&compose*/); + if (keysym && keysym < 0x400) { // a character in latin-1,2,3,4 sets + // force it to type a character (not sure if this ever is needed): + if (!len) {buffer[0] = char(keysym); len = 1;} + // ignore all effects of shift on the keysyms, which makes it a lot + // easier to program shortcuts and is Windoze-compatable: + keysym = XKeycodeToKeysym(fl_display, keycode, 0); + } + // MRS: Can't use Fl::event_state(FL_CTRL) since the state is not + // set until set_event_xy() is called later... + if ((xevent.xkey.state & ControlMask) && keysym == '-') buffer[0] = 0x1f; // ^_ + buffer[len] = 0; + Fl::e_text = buffer; + Fl::e_length = len; + } else { + // Stupid X sends fake key-up events when a repeating key is held + // down, probably due to some back compatability problem. Fortunately + // we can detect this because the repeating KeyPress event is in + // the queue, get it and execute it instead: + XEvent temp; + if (XCheckIfEvent(fl_display,&temp,fake_keyup_test,(char*)(&xevent))){ + xevent = temp; + goto KEYPRESS; + } + event = FL_KEYUP; + fl_key_vector[keycode/8] &= ~(1 << (keycode%8)); + // keyup events just get the unshifted keysym: + keysym = XKeycodeToKeysym(fl_display, keycode, 0); + } +# ifdef __sgi + // You can plug a microsoft keyboard into an sgi but the extra shift + // keys are not translated. Make them translate like XFree86 does: + if (!keysym) switch(keycode) { + case 147: keysym = FL_Meta_L; break; + case 148: keysym = FL_Meta_R; break; + case 149: keysym = FL_Menu; break; + } +# endif +# if BACKSPACE_HACK + // Attempt to fix keyboards that send "delete" for the key in the + // upper-right corner of the main keyboard. But it appears that + // very few of these remain? + static int got_backspace; + if (!got_backspace) { + if (keysym == FL_Delete) keysym = FL_BackSpace; + else if (keysym == FL_BackSpace) got_backspace = 1; + } +# endif + // We have to get rid of the XK_KP_function keys, because they are + // not produced on Windoze and thus case statements tend not to check + // for them. There are 15 of these in the range 0xff91 ... 0xff9f + if (keysym >= 0xff91 && keysym <= 0xff9f) { + // Map keypad keysym to character or keysym depending on + // numlock state... + unsigned long keysym1 = XKeycodeToKeysym(fl_display, keycode, 1); + if ((xevent.xkey.state & Mod2Mask) && + (keysym1 <= 0x7f || (keysym1 > 0xff9f && keysym1 <= FL_KP_Last))) { + // Store ASCII numeric keypad value... + keysym = keysym1 | FL_KP; + buffer[0] = char(keysym1) & 0x7F; + len = 1; + } else { + // Map keypad to special key... + static const unsigned short table[15] = { + FL_F+1, FL_F+2, FL_F+3, FL_F+4, + FL_Home, FL_Left, FL_Up, FL_Right, + FL_Down, FL_Page_Up, FL_Page_Down, FL_End, + 0xff0b/*XK_Clear*/, FL_Insert, FL_Delete}; + keysym = table[keysym-0xff91]; + } + } + Fl::e_keysym = int(keysym); + set_event_xy(); + Fl::e_is_click = 0; + break;} + + case ButtonPress: + Fl::e_keysym = FL_Button + xevent.xbutton.button; + set_event_xy(); + if (xevent.xbutton.button == Button4) { + Fl::e_dy = -1; // Up + event = FL_MOUSEWHEEL; + } else if (xevent.xbutton.button == Button5) { + Fl::e_dy = +1; // Down + event = FL_MOUSEWHEEL; + } else { + Fl::e_state |= (FL_BUTTON1 << (xevent.xbutton.button-1)); + event = FL_PUSH; + checkdouble(); + } + + fl_xmousewin = window; + in_a_window = true; + break; + + case MotionNotify: + set_event_xy(); +# if CONSOLIDATE_MOTION + send_motion = fl_xmousewin = window; + in_a_window = true; + return 0; +# else + event = FL_MOVE; + fl_xmousewin = window; + in_a_window = true; + break; +# endif + + case ButtonRelease: + Fl::e_keysym = FL_Button + xevent.xbutton.button; + set_event_xy(); + Fl::e_state &= ~(FL_BUTTON1 << (xevent.xbutton.button-1)); + if (xevent.xbutton.button == Button4 || + xevent.xbutton.button == Button5) return 0; + event = FL_RELEASE; + + fl_xmousewin = window; + in_a_window = true; + break; + + case EnterNotify: + if (xevent.xcrossing.detail == NotifyInferior) break; + // XInstallColormap(fl_display, Fl_X::i(window)->colormap); + set_event_xy(); + Fl::e_state = xevent.xcrossing.state << 16; + event = FL_ENTER; + + fl_xmousewin = window; + in_a_window = true; + break; + + case LeaveNotify: + if (xevent.xcrossing.detail == NotifyInferior) break; + set_event_xy(); + Fl::e_state = xevent.xcrossing.state << 16; + fl_xmousewin = 0; + in_a_window = false; // make do_queued_events produce FL_LEAVE event + return 0; + + // We cannot rely on the x,y position in the configure notify event. + // I now think this is an unavoidable problem with X: it is impossible + // for a window manager to prevent the "real" notify event from being + // sent when it resizes the contents, even though it can send an + // artificial event with the correct position afterwards (and some + // window managers do not send this fake event anyway) + // So anyway, do a round trip to find the correct x,y: + case MapNotify: + event = FL_SHOW; + + case ConfigureNotify: { + if (window->parent()) break; // ignore child windows + + // figure out where OS really put window + XWindowAttributes actual; + XGetWindowAttributes(fl_display, fl_xid(window), &actual); + Window cr; int X, Y, W = actual.width, H = actual.height; + XTranslateCoordinates(fl_display, fl_xid(window), actual.root, + 0, 0, &X, &Y, &cr); + + // tell Fl_Window about it and set flag to prevent echoing: + resize_bug_fix = window; + window->resize(X, Y, W, H); + break; // allow add_handler to do something too + } + + case ReparentNotify: { + int xpos, ypos; + Window junk; + + //ReparentNotify gives the new position of the window relative to + //the new parent. FLTK cares about the position on the root window. + XTranslateCoordinates(fl_display, xevent.xreparent.parent, + XRootWindow(fl_display, fl_screen), + xevent.xreparent.x, xevent.xreparent.y, + &xpos, &ypos, &junk); + + // tell Fl_Window about it and set flag to prevent echoing: + resize_bug_fix = window; + window->position(xpos, ypos); + break; + } + } + + return Fl::handle(event, window); +} + +//////////////////////////////////////////////////////////////// + +void Fl_Window::resize(int X,int Y,int W,int H) { + int is_a_move = (X != x() || Y != y()); + int is_a_resize = (W != w() || H != h()); + int resize_from_program = (this != resize_bug_fix); + if (!resize_from_program) resize_bug_fix = 0; + if (is_a_move && resize_from_program) set_flag(FL_FORCE_POSITION); + else if (!is_a_resize && !is_a_move) return; + if (is_a_resize) { + Fl_Group::resize(X,Y,W,H); + if (shown()) {redraw(); i->wait_for_expose = 1;} + } else { + x(X); y(Y); + } + + if (resize_from_program && is_a_resize && !resizable()) { + size_range(w(), h(), w(), h()); + } + + if (resize_from_program && shown()) { + if (is_a_resize) { + if (!resizable()) size_range(w(),h(),w(),h()); + if (is_a_move) { + XMoveResizeWindow(fl_display, i->xid, X, Y, W>0 ? W : 1, H>0 ? H : 1); + } else { + XResizeWindow(fl_display, i->xid, W>0 ? W : 1, H>0 ? H : 1); + } + } else + XMoveWindow(fl_display, i->xid, X, Y); + } +} + +//////////////////////////////////////////////////////////////// + +// A subclass of Fl_Window may call this to associate an X window it +// creates with the Fl_Window: + +void fl_fix_focus(); // in Fl.cxx + +Fl_X* Fl_X::set_xid(Fl_Window* win, Window winxid) { + Fl_X* xp = new Fl_X; + xp->xid = winxid; + xp->other_xid = 0; + xp->setwindow(win); + xp->next = Fl_X::first; + xp->region = 0; + xp->wait_for_expose = 1; + xp->backbuffer_bad = 1; + Fl_X::first = xp; + if (win->modal()) {Fl::modal_ = win; fl_fix_focus();} + return xp; +} + +// More commonly a subclass calls this, because it hides the really +// ugly parts of X and sets all the stuff for a window that is set +// normally. The global variables like fl_show_iconic are so that +// subclasses of *that* class may change the behavior... + +char fl_show_iconic; // hack for iconize() +int fl_background_pixel = -1; // hack to speed up bg box drawing +int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR + +static const int childEventMask = ExposureMask; + +static const int XEventMask = +ExposureMask|StructureNotifyMask +|KeyPressMask|KeyReleaseMask|KeymapStateMask|FocusChangeMask +|ButtonPressMask|ButtonReleaseMask +|EnterWindowMask|LeaveWindowMask +|PointerMotionMask; + +void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap) +{ + Fl_Group::current(0); // get rid of very common user bug: forgot end() + + int X = win->x(); + int Y = win->y(); + int W = win->w(); + if (W <= 0) W = 1; // X don't like zero... + int H = win->h(); + if (H <= 0) H = 1; // X don't like zero... + if (!win->parent() && !Fl::grab()) { + // center windows in case window manager does not do anything: +#ifdef FL_CENTER_WINDOWS + if (!(win->flags() & Fl_Window::FL_FORCE_POSITION)) { + win->x(X = scr_x+(scr_w-W)/2); + win->y(Y = scr_y+(scr_h-H)/2); + } +#endif // FL_CENTER_WINDOWS + + // force the window to be on-screen. Usually the X window manager + // does this, but a few don't, so we do it here for consistency: + int scr_x, scr_y, scr_w, scr_h; + Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h, X, Y); + + if (win->border()) { + // ensure border is on screen: + // (assumme extremely minimal dimensions for this border) + const int top = 20; + const int left = 1; + const int right = 1; + const int bottom = 1; + if (X+W+right > scr_x+scr_w) X = scr_x+scr_w-right-W; + if (X-left < scr_x) X = scr_x+left; + if (Y+H+bottom > scr_y+scr_h) Y = scr_y+scr_h-bottom-H; + if (Y-top < scr_y) Y = scr_y+top; + } + // now insure contents are on-screen (more important than border): + if (X+W > scr_x+scr_w) X = scr_x+scr_w-W; + if (X < scr_x) X = scr_x; + if (Y+H > scr_y+scr_h) Y = scr_y+scr_h-H; + if (Y < scr_y) Y = scr_y; + } + + ulong root = win->parent() ? + fl_xid(win->window()) : RootWindow(fl_display, fl_screen); + + XSetWindowAttributes attr; + int mask = CWBorderPixel|CWColormap|CWEventMask|CWBitGravity; + attr.event_mask = win->parent() ? childEventMask : XEventMask; + attr.colormap = colormap; + attr.border_pixel = 0; + attr.bit_gravity = 0; // StaticGravity; + if (win->override()) { + attr.override_redirect = 1; + attr.save_under = 1; + mask |= CWOverrideRedirect | CWSaveUnder; + } else attr.override_redirect = 0; + if (Fl::grab()) { + attr.save_under = 1; mask |= CWSaveUnder; + if (!win->border()) {attr.override_redirect = 1; mask |= CWOverrideRedirect;} + } + if (fl_background_pixel >= 0) { + attr.background_pixel = fl_background_pixel; + fl_background_pixel = -1; + mask |= CWBackPixel; + } + + Fl_X* xp = + set_xid(win, XCreateWindow(fl_display, + root, + X, Y, W, H, + 0, // borderwidth + visual->depth, + InputOutput, + visual->visual, + mask, &attr)); + int showit = 1; + + if (!win->parent() && !attr.override_redirect) { + // Communicate all kinds 'o junk to the X Window Manager: + + win->label(win->label(), win->iconlabel()); + + XChangeProperty(fl_display, xp->xid, WM_PROTOCOLS, + XA_ATOM, 32, 0, (uchar*)&WM_DELETE_WINDOW, 1); + + // send size limits and border: + xp->sendxjunk(); + + // set the class property, which controls the icon used: + if (win->xclass()) { + char buffer[1024]; + char *p; const char *q; + // truncate on any punctuation, because they break XResource lookup: + for (p = buffer, q = win->xclass(); isalnum(*q)||(*q&128);) *p++ = *q++; + *p++ = 0; + // create the capitalized version: + q = buffer; + *p = toupper(*q++); if (*p++ == 'X') *p++ = toupper(*q++); + while ((*p++ = *q++)); + XChangeProperty(fl_display, xp->xid, XA_WM_CLASS, XA_STRING, 8, 0, + (unsigned char *)buffer, p-buffer-1); + } + + if (win->non_modal() && xp->next && !fl_disable_transient_for) { + // find some other window to be "transient for": + Fl_Window* wp = xp->next->w; + while (wp->parent()) wp = wp->window(); + XSetTransientForHint(fl_display, xp->xid, fl_xid(wp)); + if (!wp->visible()) showit = 0; // guess that wm will not show it + } + + // Make sure that borderless windows do not show in the task bar + if (!win->border()) { + Atom net_wm_state = XInternAtom (fl_display, "_NET_WM_STATE", 0); + Atom net_wm_state_skip_taskbar = XInternAtom (fl_display, "_NET_WM_STATE_SKIP_TASKBAR", 0); + XChangeProperty (fl_display, xp->xid, net_wm_state, XA_ATOM, 32, + PropModeAppend, (unsigned char*) &net_wm_state_skip_taskbar, 1); + } + + // Make it receptive to DnD: + long version = 4; + XChangeProperty(fl_display, xp->xid, fl_XdndAware, + XA_ATOM, sizeof(int)*8, 0, (unsigned char*)&version, 1); + + XWMHints *hints = XAllocWMHints(); + hints->input = True; + hints->flags = InputHint; + if (fl_show_iconic) { + hints->flags |= StateHint; + hints->initial_state = IconicState; + fl_show_iconic = 0; + showit = 0; + } + if (win->icon()) { + hints->icon_pixmap = (Pixmap)win->icon(); + hints->flags |= IconPixmapHint; + } + XSetWMHints(fl_display, xp->xid, hints); + XFree(hints); + } + + XMapWindow(fl_display, xp->xid); + if (showit) { + win->set_visible(); + int old_event = Fl::e_number; + win->handle(Fl::e_number = FL_SHOW); // get child windows to appear + Fl::e_number = old_event; + win->redraw(); + } +} + +//////////////////////////////////////////////////////////////// +// Send X window stuff that can be changed over time: + +void Fl_X::sendxjunk() { + if (w->parent() || w->override()) return; // it's not a window manager window! + + if (!w->size_range_set) { // default size_range based on resizable(): + if (w->resizable()) { + Fl_Widget *o = w->resizable(); + int minw = o->w(); if (minw > 100) minw = 100; + int minh = o->h(); if (minh > 100) minh = 100; + w->size_range(w->w() - o->w() + minw, w->h() - o->h() + minh, 0, 0); + } else { + w->size_range(w->w(), w->h(), w->w(), w->h()); + } + return; // because this recursively called here + } + + XSizeHints *hints = XAllocSizeHints(); + // memset(&hints, 0, sizeof(hints)); jreiser suggestion to fix purify? + hints->min_width = w->minw; + hints->min_height = w->minh; + hints->max_width = w->maxw; + hints->max_height = w->maxh; + hints->width_inc = w->dw; + hints->height_inc = w->dh; + hints->win_gravity = StaticGravity; + + // see the file /usr/include/X11/Xm/MwmUtil.h: + // fill all fields to avoid bugs in kwm and perhaps other window managers: + // 0, MWM_FUNC_ALL, MWM_DECOR_ALL + long prop[5] = {0, 1, 1, 0, 0}; + + if (hints->min_width != hints->max_width || + hints->min_height != hints->max_height) { // resizable + hints->flags = PMinSize|PWinGravity; + if (hints->max_width >= hints->min_width || + hints->max_height >= hints->min_height) { + hints->flags = PMinSize|PMaxSize|PWinGravity; + // unfortunately we can't set just one maximum size. Guess a + // value for the other one. Some window managers will make the + // window fit on screen when maximized, others will put it off screen: + if (hints->max_width < hints->min_width) hints->max_width = Fl::w(); + if (hints->max_height < hints->min_height) hints->max_height = Fl::h(); + } + if (hints->width_inc && hints->height_inc) hints->flags |= PResizeInc; + if (w->aspect) { + // stupid X! It could insist that the corner go on the + // straight line between min and max... + hints->min_aspect.x = hints->max_aspect.x = hints->min_width; + hints->min_aspect.y = hints->max_aspect.y = hints->min_height; + hints->flags |= PAspect; + } + } else { // not resizable: + hints->flags = PMinSize|PMaxSize|PWinGravity; + prop[0] = 1; // MWM_HINTS_FUNCTIONS + prop[1] = 1|2|16; // MWM_FUNC_ALL | MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE + } + + if (w->flags() & Fl_Window::FL_FORCE_POSITION) { + hints->flags |= USPosition; + hints->x = w->x(); + hints->y = w->y(); + } + + if (!w->border()) { + prop[0] |= 2; // MWM_HINTS_DECORATIONS + prop[2] = 0; // no decorations + } + + XSetWMNormalHints(fl_display, xid, hints); + XChangeProperty(fl_display, xid, + fl_MOTIF_WM_HINTS, fl_MOTIF_WM_HINTS, + 32, 0, (unsigned char *)prop, 5); + XFree(hints); +} + +void Fl_Window::size_range_() { + size_range_set = 1; + if (shown()) i->sendxjunk(); +} + +//////////////////////////////////////////////////////////////// + +// returns pointer to the filename, or null if name ends with '/' +const char *fl_filename_name(const char *name) { + const char *p,*q; + if (!name) return (0); + for (p=q=name; *p;) if (*p++ == '/') q = p; + return q; +} + +void Fl_Window::label(const char *name,const char *iname) { + Fl_Widget::label(name); + iconlabel_ = iname; + if (shown() && !parent()) { + if (!name) name = ""; + XChangeProperty(fl_display, i->xid, XA_WM_NAME, + XA_STRING, 8, 0, (uchar*)name, strlen(name)); + if (!iname) iname = fl_filename_name(name); + XChangeProperty(fl_display, i->xid, XA_WM_ICON_NAME, + XA_STRING, 8, 0, (uchar*)iname, strlen(iname)); + } +} + +//////////////////////////////////////////////////////////////// +// Implement the virtual functions for the base Fl_Window class: + +// If the box is a filled rectangle, we can make the redisplay *look* +// faster by using X's background pixel erasing. We can make it +// actually *be* faster by drawing the frame only, this is done by +// setting fl_boxcheat, which is seen by code in fl_drawbox.cxx: +// +// On XFree86 (and prehaps all X's) this has a problem if the window +// is resized while a save-behind window is atop it. The previous +// contents are restored to the area, but this assummes the area +// is cleared to background color. So this is disabled in this version. +// Fl_Window *fl_boxcheat; +static inline int can_boxcheat(uchar b) {return (b==1 || (b&2) && b<=15);} + +void Fl_Window::show() { + image(Fl::scheme_bg_); + if (Fl::scheme_bg_) { + labeltype(FL_NORMAL_LABEL); + align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP); + } else { + labeltype(FL_NO_LABEL); + } + if (!shown()) { + fl_open_display(); + if (can_boxcheat(box())) fl_background_pixel = int(fl_xpixel(color())); + Fl_X::make_xid(this); + } else { + XMapRaised(fl_display, i->xid); + } +} + +Window fl_window; +Fl_Window *Fl_Window::current_; +GC fl_gc; + +// make X drawing go into this window (called by subclass flush() impl.) +void Fl_Window::make_current() { + static GC gc; // the GC used by all X windows + if (!gc) gc = XCreateGC(fl_display, i->xid, 0, 0); + fl_window = i->xid; + fl_gc = gc; + current_ = this; + fl_clip_region(0); +} + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/allfiles.xbm b/Utilities/FLTK/src/allfiles.xbm new file mode 100644 index 0000000000..26373b60b1 --- /dev/null +++ b/Utilities/FLTK/src/allfiles.xbm @@ -0,0 +1,6 @@ +#define allfiles_width 16 +#define allfiles_height 16 +static unsigned char allfiles_bits[] = { + 0xfc, 0x3f, 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0x84, 0x21, 0xa4, 0x25, + 0xc4, 0x23, 0xf4, 0x2f, 0xf4, 0x2f, 0xc4, 0x23, 0xa4, 0x25, 0x84, 0x21, + 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0xfc, 0x3f}; diff --git a/Utilities/FLTK/src/cmap.cxx b/Utilities/FLTK/src/cmap.cxx new file mode 100644 index 0000000000..12f477abf7 --- /dev/null +++ b/Utilities/FLTK/src/cmap.cxx @@ -0,0 +1,179 @@ +// +// "$Id$" +// +// Colormap generation program for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to "fltk-bugs@easysw.com". +// + +// This program produces the contents of "fl_cmap.h" as stdout + +// #include <gl/gl.h> +#include <stdio.h> + +// This table is initialized with color values I got by reading the +// colormap on an IRIX 4.3 machine: + +// "full intensity colors" have been turned down some to make white +// background less intense by default. The hope is that this will make +// fltk programs more friendly on color-adjusted screens. If you want +// pure colors you should get them out of the colormap. + +//#define III 244 // maximum intensity of the basic colors + +// that results in errors and unshared colormap entries, so full intensity: +#define III 255 // maximum intensity of the basic colors + +static short cmap[256][3] = { +// 3-bit colormap: + { 0, 0, 0}, // black + {III, 0, 0}, // red + { 0,III, 0}, // green + {III,III, 0}, // yellow + { 0, 0,III}, // blue + {III, 0,III}, // magenta + { 0,III,III}, // cyan + {III,III,III}, // white +// pastel versions of those colors, from SGI's standard color map: + { 85, 85, 85}, // 1/3 gray + {198,113,113}, // salmon? pale red? + {113,198,113}, // pale green + {142,142, 56}, // khaki + {113,113,198}, // pale blue + {142, 56,142}, // purple, orchid, pale magenta + { 56,142,142}, // cadet blue, aquamarine, pale cyan +// The next location is used for FL_SELECTION_COLOR. It formerly was 2/3 gray +// but this is changed to be the Windows blue color. This allows the default +// behavior on both X and Windows to match: + { 0, 0,128}, +//{170,170,170}, // old 2/3 gray color +// These next 16 are the FL_FREE_COLOR area. In some versions of fltk +// these were filled with random colors that a Irix 5.3 machine placed +// in these locations. Other versions of fltk filled this with the 1/3 +// gray above to discourage their use. This newest version uses colors +// that NewTek has assigned for their GUI: +#if 0 + // The Irix 5.3 colors: + { 16, 16, 16}, + {128, 40,128}, + {198, 30, 30}, + { 66, 30, 30}, + {176,140,140}, + { 0, 20, 20}, + { 20, 10, 10}, + { 40, 20, 20}, + { 60, 30, 30}, + { 0, 80, 80}, + { 0, 40, 40}, + { 20, 20, 0}, + { 40, 40, 0}, + { 80, 80, 10}, + {150,150, 20}, + {160, 10, 10}, +#else + // The NewTek colors: (from George Yohng) + {168,168,152}, + {232,232,216}, + {104,104, 88}, + {152,168,168}, + {216,232,232}, + { 88,104,104}, + {156,156,168}, + {220,220,232}, + { 92, 92,104}, + {156,168,156}, + {220,232,220}, + { 92,104, 92}, + {144,144,144}, + {192,192,192}, + { 80, 80, 80}, + {160,160,160}, +#endif +// The rest of the colormap is a gray ramp and table, filled in below: +}; + +// This is Fl::background from Fl_get_system_colors.cxx, with modifications: + +#define FL_GRAY_RAMP 32 +#define FL_NUM_GRAY 24 +#define FL_GRAY 49 // old value is 47 +typedef unsigned char uchar; +#include <math.h> + +void background(uchar r, uchar g, uchar b) { + // replace the gray ramp so that color 47 (by default 2/3) is this color + if (!r) r = 1; else if (r==255) r = 254; + double powr = log(r/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0)); + if (!g) g = 1; else if (g==255) g = 254; + double powg = log(g/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0)); + if (!b) b = 1; else if (b==255) b = 254; + double powb = log(b/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0)); + for (int i = 0; i < FL_NUM_GRAY; i++) { + double gray = i/(FL_NUM_GRAY-1.0); + cmap[i+FL_GRAY_RAMP][0] = uchar(pow(gray,powr)*255+.5); + cmap[i+FL_GRAY_RAMP][1] = uchar(pow(gray,powg)*255+.5); + cmap[i+FL_GRAY_RAMP][2] = uchar(pow(gray,powb)*255+.5); + } +} + +int main() { + int i,r,g,b; +#if 0 + /* Read colormap colors into internal table */ + long cmwin; + noport(); + cmwin = winopen("CM"); + for (i=0; i<256; i++) + getmcolor(i,&cmap[i][0],&cmap[i][1],&cmap[i][2]); + winclose(cmwin); +#endif +// overwrite the X allocation area with one color so people are +// discouraged from using it: + //for (i=16; i<32; i++) {cmap[i][0]=cmap[i][1]=cmap[i][2] = 85;} + + // fill in the gray ramp: + background(0xc0, 0xc0, 0xc0); // microsoft colors + // background(170, 170, 170); // old fltk colors + // copy the 1/3 and 2/3 gray to the closest locations in gray ramp: + cmap[39][0] = cmap[39][1] = cmap[39][2] = 85; + cmap[47][0] = cmap[47][1] = cmap[47][2] = 170; + + // fill in the color cube + i = 56; + for (b=0; b<5; b++) + for (r=0; r<5; r++) + for (g=0; g<8; g++) { + cmap[i][0] = r*255/4; + cmap[i][1] = g*255/7; + cmap[i][2] = b*255/4; + i++; + } + + for (i=0; i<256; i++) { + printf("\t0x%02x%02x%02x00",cmap[i][0],cmap[i][1],cmap[i][2]); + if (i < 255) printf(",\n"); + } + printf("\n"); + return 0; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/d1.xbm b/Utilities/FLTK/src/d1.xbm new file mode 100644 index 0000000000..a0e67f0290 --- /dev/null +++ b/Utilities/FLTK/src/d1.xbm @@ -0,0 +1,6 @@ +#define d1_width 16 +#define d1_height 16 +static unsigned char d1_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x38, 0x00, 0x78, 0x00, + 0xe8, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x1c, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/Utilities/FLTK/src/d1_mask.xbm b/Utilities/FLTK/src/d1_mask.xbm new file mode 100644 index 0000000000..6b1e14daca --- /dev/null +++ b/Utilities/FLTK/src/d1_mask.xbm @@ -0,0 +1,6 @@ +#define d1_mask_width 16 +#define d1_mask_height 16 +static unsigned char d1_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x7c, 0x00, 0xfc, 0x00, + 0xfc, 0x01, 0xec, 0x03, 0xc0, 0x37, 0x80, 0x3f, 0x00, 0x3f, 0x00, 0x3e, + 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00}; diff --git a/Utilities/FLTK/src/dump_compose.c b/Utilities/FLTK/src/dump_compose.c new file mode 100644 index 0000000000..fe41991cf9 --- /dev/null +++ b/Utilities/FLTK/src/dump_compose.c @@ -0,0 +1,26 @@ +/* write out the documentation for the compose key */ + +/* copy the string from Fl_Input.C */ +static const char* const compose_pairs = +" ! @ # $ y=| & : c a <<~ - r _ * +-2 3 ' u p . , 1 o >>141234? " +"A`A'A^A~A:A*AEC,E`E'E^E:I`I'I^I:D-N~O`O'O^O~O:x O/U`U'U^U:Y'DDss" +"a`a'a^a~a:a*aec,e`e'e^e:i`i'i^i:d-n~o`o'o^o~o:-:o/u`u'u^u:y'ddy:"; + +#include <stdio.h> + +int main() { + int x,y; + for (x = 0; x<16; x++) { + for (y = 0; y<6; y++) { + const char *p = compose_pairs + (16*y+x)*2; + if (p[1] == ' ') + printf("<td><code>%c </code>   %c\n", + p[0],(p-compose_pairs)/2+0xA0); + else + printf("<td><code>%c%c</code>   %c\n", + p[0],p[1],(p-compose_pairs)/2+0xA0); + } + printf("<tr>"); + } + return 0; +} diff --git a/Utilities/FLTK/src/ew.xbm b/Utilities/FLTK/src/ew.xbm new file mode 100644 index 0000000000..1ff835cd57 --- /dev/null +++ b/Utilities/FLTK/src/ew.xbm @@ -0,0 +1,8 @@ +#define ew_width 16 +#define ew_height 16 +#define ew_x_hot 8 +#define ew_y_hot 8 +static unsigned char ew_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, + 0x0c, 0x30, 0xfe, 0x7f, 0xfe, 0x7f, 0x0c, 0x30, 0x08, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/Utilities/FLTK/src/ew_mask.xbm b/Utilities/FLTK/src/ew_mask.xbm new file mode 100644 index 0000000000..49dc1df881 --- /dev/null +++ b/Utilities/FLTK/src/ew_mask.xbm @@ -0,0 +1,8 @@ +#define ew_mask_width 16 +#define ew_mask_height 16 +#define ew_mask_x_hot 8 +#define ew_mask_y_hot 8 +static unsigned char ew_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1c, 0x38, + 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0x1c, 0x38, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/Utilities/FLTK/src/fastarrow.h b/Utilities/FLTK/src/fastarrow.h new file mode 100644 index 0000000000..e381acdced --- /dev/null +++ b/Utilities/FLTK/src/fastarrow.h @@ -0,0 +1,6 @@ +#define fastarrow_width 16 +#define fastarrow_height 16 +static unsigned char fastarrow_bits[] = { + 0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xfc, 0x03, 0xff, 0xff, 0xfc, 0x03, + 0xe0, 0x07, 0x00, 0x07, 0xe0, 0x00, 0xe0, 0x07, 0xc0, 0x3f, 0xff, 0xff, + 0xc0, 0x3f, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x00}; diff --git a/Utilities/FLTK/src/filename_absolute.cxx b/Utilities/FLTK/src/filename_absolute.cxx new file mode 100644 index 0000000000..d4101cfec0 --- /dev/null +++ b/Utilities/FLTK/src/filename_absolute.cxx @@ -0,0 +1,197 @@ +// +// "$Id$" +// +// Filename expansion routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/* expand a file name by prepending current directory, deleting . and + .. (not really correct for symbolic links) between the prepended + current directory. Use $PWD if it exists. + Returns true if any changes were made. +*/ + +#include <FL/filename.H> +#include <stdlib.h> +#include "flstring.h" +#include <ctype.h> +#if defined(WIN32) && !defined(__CYGWIN__) +# include <direct.h> +// Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs +// on Windows, which is supposed to be POSIX compliant... +# define getcwd _getcwd +#else +# include <unistd.h> +# ifdef __EMX__ +# define getcwd _getcwd2 +# endif +#endif + +#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__) +inline int isdirsep(char c) {return c=='/' || c=='\\';} +#else +#define isdirsep(c) ((c)=='/') +#endif + +int fl_filename_absolute(char *to, int tolen, const char *from) { + if (isdirsep(*from) || *from == '|' +#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__) + || from[1]==':' +#endif + ) { + strlcpy(to, from, tolen); + return 0; + } + + char *a; + char *temp = new char[tolen]; + const char *start = from; + + a = getcwd(temp, tolen); + if (!a) { + strlcpy(to, from, tolen); + delete[] temp; + return 0; + } +#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__) + for (a = temp; *a; a++) if (*a=='\\') *a = '/'; // ha ha +#else + a = temp+strlen(temp); +#endif + if (isdirsep(*(a-1))) a--; + /* remove intermediate . and .. names: */ + while (*start == '.') { + if (start[1]=='.' && isdirsep(start[2])) { + char *b; + for (b = a-1; b >= temp && !isdirsep(*b); b--); + if (b < temp) break; + a = b; + start += 3; + } else if (isdirsep(start[1])) { + start += 2; + } else if (!start[1]) { + start ++; // Skip lone "." + break; + } else + break; + } + + *a++ = '/'; + strlcpy(a,start,tolen - (a - temp)); + + strlcpy(to, temp, tolen); + + delete[] temp; + + return 1; +} + +/* + * 'fl_filename_relative()' - Make a filename relative to the current working directory. + */ + +int // O - 0 if no change, 1 if changed +fl_filename_relative(char *to, // O - Relative filename + int tolen, // I - Size of "to" buffer + const char *from) {// I - Absolute filename + char *newslash; // Directory separator + const char *slash; // Directory separator + char cwd[1024]; // Current directory + + +#if defined(WIN32) || defined(__EMX__) + if (from[0] == '\0' || + (!isdirsep(*from) && !isalpha(*from) && from[1] != ':' && + !isdirsep(from[2]))) { +#else + if (from[0] == '\0' || !isdirsep(*from)) { +#endif // WIN32 || __EMX__ + strlcpy(to, from, tolen); + return 0; + } + + if (!getcwd(cwd, sizeof(cwd))) { + strlcpy(to, from, tolen); + return 0; + } + +#if defined(WIN32) || defined(__EMX__) + for (newslash = strchr(cwd, '\\'); newslash; newslash = strchr(newslash + 1, '\\')) + *newslash = '/'; + + if (!strcasecmp(from, cwd)) { + strlcpy(to, ".", tolen); + return (1); + } + + if (tolower(*from & 255) != tolower(*cwd & 255)) { + // Not the same drive... + strlcpy(to, from, tolen); + return 0; + } + for (slash = from + 2, newslash = cwd + 2; +#else + if (!strcmp(from, cwd)) { + strlcpy(to, ".", tolen); + return (1); + } + + for (slash = from, newslash = cwd; +#endif // WIN32 || __EMX__ + *slash != '\0' && *newslash != '\0'; + slash ++, newslash ++) + if (isdirsep(*slash) && isdirsep(*newslash)) continue; +#if defined(WIN32) || defined(__EMX__) || defined(__APPLE__) + else if (tolower(*slash & 255) != tolower(*newslash & 255)) break; +#else + else if (*slash != *newslash) break; +#endif // WIN32 || __EMX__ || __APPLE__ + + if (*newslash == '\0' && *slash != '\0' && !isdirsep(*slash)) + newslash--; + + while (!isdirsep(*slash) && slash > from) slash --; + + if (isdirsep(*slash)) slash ++; + + if (*newslash != '\0') + while (!isdirsep(*newslash) && newslash > cwd) newslash --; + + to[0] = '\0'; + to[tolen - 1] = '\0'; + + while (*newslash != '\0') { + if (isdirsep(*newslash)) strlcat(to, "../", tolen); + + newslash ++; + } + + strlcat(to, slash, tolen); + + return 1; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/filename_expand.cxx b/Utilities/FLTK/src/filename_expand.cxx new file mode 100644 index 0000000000..3f040a7e33 --- /dev/null +++ b/Utilities/FLTK/src/filename_expand.cxx @@ -0,0 +1,110 @@ +// +// "$Id$" +// +// Filename expansion routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/* expand a file name by substuting environment variables and + home directories. Returns true if any changes were made. + to & from may be the same buffer. +*/ + +#include <FL/filename.H> +#include <stdlib.h> +#include "flstring.h" +#if defined(WIN32) && !defined(__CYGWIN__) +#else +# include <unistd.h> +# include <pwd.h> +#endif + +#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__) +static inline int isdirsep(char c) {return c=='/' || c=='\\';} +#else +#define isdirsep(c) ((c)=='/') +#endif + +int fl_filename_expand(char *to,int tolen, const char *from) { + + char *temp = new char[tolen]; + strlcpy(temp,from, tolen); + char *start = temp; + char *end = temp+strlen(temp); + + int ret = 0; + + for (char *a=temp; a<end; ) { // for each slash component + char *e; for (e=a; e<end && !isdirsep(*e); e++); // find next slash + const char *value = 0; // this will point at substitute value + switch (*a) { + case '~': // a home directory name + if (e <= a+1) { // current user's directory + value = getenv("HOME"); +#ifndef WIN32 + } else { // another user's directory + struct passwd *pwd; + char t = *e; *(char *)e = 0; + pwd = getpwnam(a+1); + *(char *)e = t; + if (pwd) value = pwd->pw_dir; +#endif + } + break; + case '$': /* an environment variable */ + {char t = *e; *(char *)e = 0; value = getenv(a+1); *(char *)e = t;} + break; + } + if (value) { + // substitutions that start with slash delete everything before them: + if (isdirsep(value[0])) start = a; +#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__) + // also if it starts with "A:" + if (value[0] && value[1]==':') start = a; +#endif + int t = strlen(value); if (isdirsep(value[t-1])) t--; + if ((end+1-e+t) >= tolen) end += tolen - (end+1-e+t); + memmove(a+t, e, end+1-e); + end = a+t+(end-e); + *end = '\0'; + memcpy(a, value, t); + ret++; + } else { + a = e+1; +#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__) + if (*e == '\\') {*e = '/'; ret++;} // ha ha! +#endif + } + } + + strlcpy(to, start, tolen); + + delete[] temp; + + return ret; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/filename_ext.cxx b/Utilities/FLTK/src/filename_ext.cxx new file mode 100644 index 0000000000..2500853343 --- /dev/null +++ b/Utilities/FLTK/src/filename_ext.cxx @@ -0,0 +1,47 @@ +// +// "$Id$" +// +// Filename extension routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// returns pointer to the last '.' or to the null if none: + +#include <FL/filename.H> + +const char *fl_filename_ext(const char *buf) { + const char *q = 0; + const char *p = buf; + for (p=buf; *p; p++) { + if (*p == '/') q = 0; +#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__) + else if (*p == '\\') q = 0; +#endif + else if (*p == '.') q = p; + } + return q ? q : p; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/filename_isdir.cxx b/Utilities/FLTK/src/filename_isdir.cxx new file mode 100644 index 0000000000..f1a3d29095 --- /dev/null +++ b/Utilities/FLTK/src/filename_isdir.cxx @@ -0,0 +1,77 @@ +// +// "$Id$" +// +// Directory detection routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Used by fl_file_chooser + +#include "flstring.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <ctype.h> +#include <FL/filename.H> + + +#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__) +static inline int isdirsep(char c) {return c=='/' || c=='\\';} +#else +#define isdirsep(c) ((c)=='/') +#endif + +int fl_filename_isdir(const char* n) { + struct stat s; + + // Do a quick optimization for filenames with a trailing slash... + if (*n && isdirsep(n[strlen(n) - 1])) return 1; + +#ifdef WIN32 + char fn[1024]; + int length; + // This workaround brought to you by the fine folks at Microsoft! + // (read lots of sarcasm in that...) + length = strlen(n); + if (length < (int)(sizeof(fn) - 1)) { + if (length < 4 && isalpha(n[0]) && n[1] == ':' && + (isdirsep(n[2]) || !n[2])) { + // Always use D:/ for drive letters + fn[0] = n[0]; + strcpy(fn + 1, ":/"); + n = fn; + } else if (length > 0 && isdirsep(n[length - 1])) { + // Strip trailing slash from name... + length --; + memcpy(fn, n, length); + fn[length] = '\0'; + n = fn; + } + } +#endif + + return !stat(n, &s) && (s.st_mode&0170000)==0040000; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/filename_list.cxx b/Utilities/FLTK/src/filename_list.cxx new file mode 100644 index 0000000000..7e16b5ffe3 --- /dev/null +++ b/Utilities/FLTK/src/filename_list.cxx @@ -0,0 +1,108 @@ +// +// "$Id$" +// +// Filename list routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Wrapper for scandir with const-correct function prototypes. + +#include <FL/filename.H> +#include "flstring.h" +#include <stdlib.h> +#include "fltk-config.h" + + +extern "C" { +#ifndef HAVE_SCANDIR + int fl_scandir (const char *dir, dirent ***namelist, + int (*select)(dirent *), + int (*compar)(dirent **, dirent **)); +# define scandir fl_scandir +#endif +} + +int fl_alphasort(struct dirent **a, struct dirent **b) { + return strcmp((*a)->d_name, (*b)->d_name); +} + +int fl_casealphasort(struct dirent **a, struct dirent **b) { + return strcasecmp((*a)->d_name, (*b)->d_name); +} + + +int fl_filename_list(const char *d, dirent ***list, + Fl_File_Sort_F *sort) { +#ifndef HAVE_SCANDIR + int n = scandir(d, list, 0, sort); +#elif defined(__hpux) || defined(__CYGWIN__) + // HP-UX, Cygwin define the comparison function like this: + int n = scandir(d, list, 0, (int(*)(const dirent **, const dirent **))sort); +#elif defined(__osf__) + // OSF, DU 4.0x + int n = scandir(d, list, 0, (int(*)(dirent **, dirent **))sort); +#elif defined(_AIX) + // AIX is almost standard... + int n = scandir(d, list, 0, (int(*)(void*, void*))sort); +#elif !defined(__sgi) + // The vast majority of UNIX systems want the sort function to have this + // prototype, most likely so that it can be passed to qsort without any + // changes: + int n = scandir(d, list, 0, (int(*)(const void*,const void*))sort); +#else + // This version is when we define our own scandir (WIN32 and perhaps + // some Unix systems) and apparently on IRIX: + int n = scandir(d, list, 0, sort); +#endif + +#if defined(WIN32) && !defined(__CYGWIN__) + // we did this already during fl_scandir/win32 +#else + // append a '/' to all filenames that are directories + int i, dirlen = strlen(d); + char *fullname = (char*)malloc(dirlen+FL_PATH_MAX+3); // Add enough extra for two /'s and a nul + // Use memcpy for speed since we already know the length of the string... + memcpy(fullname, d, dirlen+1); + char *name = fullname + dirlen; + if (name!=fullname && name[-1]!='/') *name++ = '/'; + for (i=0; i<n; i++) { + dirent *de = (*list)[i]; + int len = strlen(de->d_name); + if (de->d_name[len-1]=='/' || len>FL_PATH_MAX) continue; + // Use memcpy for speed since we already know the length of the string... + memcpy(name, de->d_name, len+1); + if (fl_filename_isdir(fullname)) { + (*list)[i] = de = (dirent*)realloc(de, de->d_name - (char*)de + len + 2); + char *dst = de->d_name + len; + *dst++ = '/'; + *dst = 0; + } + } + free(fullname); +#endif + return n; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/filename_match.cxx b/Utilities/FLTK/src/filename_match.cxx new file mode 100644 index 0000000000..990ede5c48 --- /dev/null +++ b/Utilities/FLTK/src/filename_match.cxx @@ -0,0 +1,106 @@ +// +// "$Id$" +// +// Pattern matching routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/* Adapted from Rich Salz. */ +#include <FL/filename.H> +#include <ctype.h> + +int fl_filename_match(const char *s, const char *p) { + int matched; + + for (;;) { + switch(*p++) { + + case '?' : // match any single character + if (!*s++) return 0; + break; + + case '*' : // match 0-n of any characters + if (!*p) return 1; // do trailing * quickly + while (!fl_filename_match(s, p)) if (!*s++) return 0; + return 1; + + case '[': { // match one character in set of form [abc-d] or [^a-b] + if (!*s) return 0; + int reverse = (*p=='^' || *p=='!'); if (reverse) p++; + matched = 0; + char last = 0; + while (*p) { + if (*p=='-' && last) { + if (*s <= *++p && *s >= last ) matched = 1; + last = 0; + } else { + if (*s == *p) matched = 1; + } + last = *p++; + if (*p==']') break; + } + if (matched == reverse) return 0; + s++; p++;} + break; + + case '{' : // {pattern1|pattern2|pattern3} + NEXTCASE: + if (fl_filename_match(s,p)) return 1; + for (matched = 0;;) { + switch (*p++) { + case '\\': if (*p) p++; break; + case '{': matched++; break; + case '}': if (!matched--) return 0; break; + case '|': case ',': if (matched==0) goto NEXTCASE; + case 0: return 0; + } + } + case '|': // skip rest of |pattern|pattern} when called recursively + case ',': + for (matched = 0; *p && matched >= 0;) { + switch (*p++) { + case '\\': if (*p) p++; break; + case '{': matched++; break; + case '}': matched--; break; + } + } + break; + case '}': + break; + + case 0: // end of pattern + return !*s; + + case '\\': // quote next character + if (*p) p++; + default: + if (tolower(*s) != tolower(*(p-1))) return 0; + s++; + break; + } + } +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/filename_setext.cxx b/Utilities/FLTK/src/filename_setext.cxx new file mode 100644 index 0000000000..17ce987705 --- /dev/null +++ b/Utilities/FLTK/src/filename_setext.cxx @@ -0,0 +1,46 @@ +// +// "$Id$" +// +// Filename extension routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Replace .ext with new extension +// If no . in name, append new extension +// If new extension is null, act like it is "" + +#include <FL/filename.H> +#include "flstring.h" + +char *fl_filename_setext(char *buf, int buflen, const char *ext) { + char *q = (char *)fl_filename_ext(buf); + if (ext) { + strlcpy(q,ext,buflen - (q - buf)); + } else *q = 0; + return(buf); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_arc.cxx b/Utilities/FLTK/src/fl_arc.cxx new file mode 100644 index 0000000000..08cc416bfe --- /dev/null +++ b/Utilities/FLTK/src/fl_arc.cxx @@ -0,0 +1,86 @@ +// +// "$Id$" +// +// Arc functions for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Utility for drawing arcs and circles. They are added to +// the current fl_begin/fl_vertex/fl_end path. +// Incremental math implementation: + +#include <FL/fl_draw.H> +#include <FL/math.h> + +#if defined(WIN32) && !defined(__CYGWIN__) +// Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs +// on Windows, which is supposed to be POSIX compliant... +# define hypot _hypot +#endif // WIN32 && !__CYGWIN__ + +void fl_arc(double x, double y, double r, double start, double end) { + + // draw start point accurately: + + double A = start*(M_PI/180); // Initial angle (radians) + double X = r*cos(A); // Initial displacement, (X,Y) + double Y = -r*sin(A); // from center to initial point + fl_vertex(x+X,y+Y); // Insert initial point + + // Maximum arc length to approximate with chord with error <= 0.125 + + double epsilon; { + double r1 = hypot(fl_transform_dx(r,0), // Horizontal "radius" + fl_transform_dy(r,0)); + double r2 = hypot(fl_transform_dx(0,r), // Vertical "radius" + fl_transform_dy(0,r)); + + if (r1 > r2) r1 = r2; // r1 = minimum "radius" + if (r1 < 2.) r1 = 2.; // radius for circa 9 chords/circle + + epsilon = 2*acos(1.0 - 0.125/r1); // Maximum arc angle + } + A = end*(M_PI/180) - A; // Displacement angle (radians) + int i = int(ceil(fabs(A)/epsilon)); // Segments in approximation + + if (i) { + epsilon = A/i; // Arc length for equal-size steps + double cos_e = cos(epsilon); // Rotation coefficients + double sin_e = sin(epsilon); + do { + double Xnew = cos_e*X + sin_e*Y; + Y = -sin_e*X + cos_e*Y; + fl_vertex(x + (X=Xnew), y + Y); + } while (--i); + } +} + +#if 0 // portable version. X-specific one in fl_vertex.cxx +void fl_circle(double x,double y,double r) { + _fl_arc(x, y, r, r, 0, 360); +} +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_arci.cxx b/Utilities/FLTK/src/fl_arci.cxx new file mode 100644 index 0000000000..0ff9368b9f --- /dev/null +++ b/Utilities/FLTK/src/fl_arci.cxx @@ -0,0 +1,119 @@ +// +// "$Id$" +// +// Arc (integer) drawing functions for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// "integer" circle drawing functions. These draw the limited +// circle types provided by X and NT graphics. The advantage of +// these is that small ones draw quite nicely (probably due to stored +// hand-drawn bitmaps of small circles!) and may be implemented by +// hardware and thus are fast. + +// Probably should add fl_chord. + +// 3/10/98: created + +#include <FL/fl_draw.H> +#include <FL/x.H> +#ifdef WIN32 +#include <FL/math.h> +#endif +#ifdef __APPLE__ +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#endif + +void fl_arc(int x,int y,int w,int h,double a1,double a2) { + if (w <= 0 || h <= 0) return; +#ifdef WIN32 + int xa = x+w/2+int(w*cos(a1/180.0*M_PI)); + int ya = y+h/2-int(h*sin(a1/180.0*M_PI)); + int xb = x+w/2+int(w*cos(a2/180.0*M_PI)); + int yb = y+h/2-int(h*sin(a2/180.0*M_PI)); + Arc(fl_gc, x, y, x+w, y+h, xa, ya, xb, yb); +#elif defined(__APPLE_QD__) + Rect r; r.left=x; r.right=x+w; r.top=y; r.bottom=y+h; + a1 = a2-a1; a2 = 450-a2; + FrameArc(&r, (short int)a2, (short int)a1); +#elif defined(__APPLE_QUARTZ__) + a1 = (-a1)/180.0f*M_PI; a2 = (-a2)/180.0f*M_PI; + float cx = x + 0.5f*w - 0.5f, cy = y + 0.5f*h - 0.5f; + if (w!=h) { + CGContextSaveGState(fl_gc); + CGContextTranslateCTM(fl_gc, cx, cy); + CGContextScaleCTM(fl_gc, w-1.0f, h-1.0f); + CGContextAddArc(fl_gc, 0, 0, 0.5, a1, a2, 1); + CGContextRestoreGState(fl_gc); + } else { + float r = (w+h)*0.25f-0.5f; + CGContextAddArc(fl_gc, cx, cy, r, a1, a2, 1); + } + CGContextStrokePath(fl_gc); +#else + XDrawArc(fl_display, fl_window, fl_gc, x,y,w-1,h-1, int(a1*64),int((a2-a1)*64)); +#endif +} + +void fl_pie(int x,int y,int w,int h,double a1,double a2) { + if (w <= 0 || h <= 0) return; +#ifdef WIN32 + if (a1 == a2) return; + int xa = x+w/2+int(w*cos(a1/180.0*M_PI)); + int ya = y+h/2-int(h*sin(a1/180.0*M_PI)); + int xb = x+w/2+int(w*cos(a2/180.0*M_PI)); + int yb = y+h/2-int(h*sin(a2/180.0*M_PI)); + SelectObject(fl_gc, fl_brush()); + Pie(fl_gc, x, y, x+w, y+h, xa, ya, xb, yb); +#elif defined(__APPLE_QD__) + Rect r; r.left=x; r.right=x+w; r.top=y; r.bottom=y+h; + a1 = a2-a1; a2 = 450-a2; + PaintArc(&r, (short int)a2, (short int)a1); +#elif defined(__APPLE_QUARTZ__) + a1 = (-a1)/180.0f*M_PI; a2 = (-a2)/180.0f*M_PI; + float cx = x + 0.5f*w - 0.5f, cy = y + 0.5f*h - 0.5f; + if (w!=h) { + CGContextSaveGState(fl_gc); + CGContextTranslateCTM(fl_gc, cx, cy); + CGContextScaleCTM(fl_gc, w, h); + CGContextAddArc(fl_gc, 0, 0, 0.5, a1, a2, 1); + CGContextAddLineToPoint(fl_gc, 0, 0); + CGContextClosePath(fl_gc); + CGContextRestoreGState(fl_gc); + } else { + float r = (w+h)*0.25f; + CGContextAddArc(fl_gc, cx, cy, r, a1, a2, 1); + CGContextAddLineToPoint(fl_gc, cx, cy); + CGContextClosePath(fl_gc); + } + CGContextFillPath(fl_gc); +#else + XFillArc(fl_display, fl_window, fl_gc, x,y,w-1,h-1, int(a1*64),int((a2-a1)*64)); +#endif +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_ask.cxx b/Utilities/FLTK/src/fl_ask.cxx new file mode 100644 index 0000000000..454ecff777 --- /dev/null +++ b/Utilities/FLTK/src/fl_ask.cxx @@ -0,0 +1,357 @@ +// +// "$Id$" +// +// Standard dialog functions for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Implementation of fl_message, fl_ask, fl_choice, fl_input +// The three-message fl_show_x functions are for forms compatibility +// mostly. In most cases it is easier to get a multi-line message +// by putting newlines in the message. + +#include <stdio.h> +#include <stdarg.h> +#include "flstring.h" + +#include <FL/Fl.H> + +#include <FL/fl_ask.H> + +#include <FL/Fl_Box.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Return_Button.H> +#include <FL/Fl_Window.H> +#include <FL/Fl_Input.H> +#include <FL/Fl_Secret_Input.H> +#include <FL/x.H> +#include <FL/fl_draw.H> + +static Fl_Window *message_form; +static Fl_Box *message; +static Fl_Box *icon; +static Fl_Button *button[3]; +static Fl_Input *input; +static const char *iconlabel = "?"; +Fl_Font fl_message_font_ = FL_HELVETICA; +uchar fl_message_size_ = 14; + +static Fl_Window *makeform() { + if (message_form) { + message_form->size(410,103); + return message_form; + } + // make sure that the dialog does not become the child of some + // current group + Fl_Group *previously_current_group = Fl_Group::current(); + Fl_Group::current(0); + // create a new top level window + Fl_Window *w = message_form = new Fl_Window(410,103,""); + // w->clear_border(); + // w->box(FL_UP_BOX); + (message = new Fl_Box(60, 25, 340, 20)) + ->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_WRAP); + (input = new Fl_Input(60, 37, 340, 23))->hide(); + {Fl_Box* o = icon = new Fl_Box(10, 10, 50, 50); + o->box(FL_THIN_UP_BOX); + o->labelfont(FL_TIMES_BOLD); + o->labelsize(34); + o->color(FL_WHITE); + o->labelcolor(FL_BLUE); + } + button[0] = new Fl_Button(310, 70, 90, 23); + button[0]->shortcut("^["); + button[0]->align(FL_ALIGN_INSIDE|FL_ALIGN_WRAP); + button[1] = new Fl_Return_Button(210, 70, 90, 23); + button[1]->align(FL_ALIGN_INSIDE|FL_ALIGN_WRAP); + button[2] = new Fl_Button(110, 70, 90, 23); + button[2]->align(FL_ALIGN_INSIDE|FL_ALIGN_WRAP); + w->resizable(new Fl_Box(60,10,110-60,27)); + w->end(); + w->set_modal(); + Fl_Group::current(previously_current_group); + return w; +} + +/* + * 'resizeform()' - Resize the form and widgets so that they hold everything + * that is asked of them... + */ + +void resizeform() { + int i; + int message_w, message_h; + int icon_size; + int button_w[3], button_h[3]; + int x, w, h, max_w, max_h; + + fl_font(fl_message_font_, fl_message_size_); + message_w = message_h = 0; + fl_measure(message->label(), message_w, message_h); + + message_w += 10; + message_h += 10; + if (message_w < 340) + message_w = 340; + if (message_h < 30) + message_h = 30; + + fl_font(button[0]->labelfont(), button[0]->labelsize()); + + memset(button_w, 0, sizeof(button_w)); + memset(button_h, 0, sizeof(button_h)); + + for (max_h = 25, i = 0; i < 3; i ++) + if (button[i]->visible()) + { + fl_measure(button[i]->label(), button_w[i], button_h[i]); + + if (i == 1) + button_w[1] += 20; + + button_w[i] += 30; + button_h[i] += 10; + + if (button_h[i] > max_h) + max_h = button_h[i]; + } + + if (input->visible()) icon_size = message_h + 25; + else icon_size = message_h; + + max_w = message_w + 10 + icon_size; + w = button_w[0] + button_w[1] + button_w[2] - 10; + + if (w > max_w) + max_w = w; + + message_w = max_w - 10 - icon_size; + + w = max_w + 20; + h = max_h + 30 + icon_size; + + message_form->size(w, h); + message_form->size_range(w, h, w, h); + + message->resize(20 + icon_size, 10, message_w, message_h); + icon->resize(10, 10, icon_size, icon_size); + icon->labelsize((uchar)(icon_size - 10)); + input->resize(20 + icon_size, 10 + message_h, message_w, 25); + + for (x = w, i = 0; i < 3; i ++) + if (button_w[i]) + { + x -= button_w[i]; + button[i]->resize(x, h - 10 - max_h, button_w[i] - 10, max_h); + +// printf("button %d (%s) is %dx%d+%d,%d\n", i, button[i]->label(), +// button[i]->w(), button[i]->h(), +// button[i]->x(), button[i]->y()); + } +} + +static int innards(const char* fmt, va_list ap, + const char *b0, + const char *b1, + const char *b2) +{ + makeform(); + char buffer[1024]; + if (!strcmp(fmt,"%s")) { + message->label(va_arg(ap, const char*)); + } else { + //: matt: MacOS provides two equally named vsnprintf's... + ::vsnprintf(buffer, 1024, fmt, ap); + message->label(buffer); + } + + message->labelfont(fl_message_font_); + message->labelsize(fl_message_size_); + if (b0) {button[0]->show(); button[0]->label(b0); button[1]->position(210,70);} + else {button[0]->hide(); button[1]->position(310,70);} + if (b1) {button[1]->show(); button[1]->label(b1);} + else button[1]->hide(); + if (b2) {button[2]->show(); button[2]->label(b2);} + else button[2]->hide(); + const char* prev_icon_label = icon->label(); + if (!prev_icon_label) icon->label(iconlabel); + + resizeform(); + + message_form->hotspot(button[0]); + message_form->show(); + int r; + for (;;) { + Fl_Widget *o = Fl::readqueue(); + if (!o) Fl::wait(); + else if (o == button[0]) {r = 0; break;} + else if (o == button[1]) {r = 1; break;} + else if (o == button[2]) {r = 2; break;} + else if (o == message_form) {r = 0; break;} + } + message_form->hide(); + icon->label(prev_icon_label); + return r; +} + +// pointers you can use to change FLTK to a foreign language: +const char* fl_no = "No"; +const char* fl_yes= "Yes"; +const char* fl_ok = "OK"; +const char* fl_cancel= "Cancel"; +const char* fl_close= "Close"; + +// fltk functions: +void fl_beep(int type) { +#ifdef WIN32 + switch (type) { + case FL_BEEP_QUESTION : + case FL_BEEP_PASSWORD : + MessageBeep(MB_ICONQUESTION); + break; + case FL_BEEP_MESSAGE : + MessageBeep(MB_ICONASTERISK); + break; + case FL_BEEP_NOTIFICATION : + MessageBeep(MB_ICONASTERISK); + break; + case FL_BEEP_ERROR : + MessageBeep(MB_ICONERROR); + break; + default : + MessageBeep(0xFFFFFFFF); + break; + } +#elif defined(__APPLE__) + switch (type) { + case FL_BEEP_DEFAULT : + case FL_BEEP_ERROR : + SysBeep(30); + break; + default : + break; + } +#else + switch (type) { + case FL_BEEP_DEFAULT : + case FL_BEEP_ERROR : + if (!fl_display) fl_open_display(); + + XBell(fl_display, 100); + break; + default : + if (!fl_display) fl_open_display(); + + XBell(fl_display, 50); + break; + } +#endif // WIN32 +} + +void fl_message(const char *fmt, ...) { + va_list ap; + + fl_beep(FL_BEEP_MESSAGE); + + va_start(ap, fmt); + iconlabel = "i"; + innards(fmt, ap, 0, fl_close, 0); + va_end(ap); + iconlabel = "?"; +} + +void fl_alert(const char *fmt, ...) { + va_list ap; + + fl_beep(FL_BEEP_ERROR); + + va_start(ap, fmt); + iconlabel = "!"; + innards(fmt, ap, 0, fl_close, 0); + va_end(ap); + iconlabel = "?"; +} + +int fl_ask(const char *fmt, ...) { + va_list ap; + + fl_beep(FL_BEEP_QUESTION); + + va_start(ap, fmt); + int r = innards(fmt, ap, fl_no, fl_yes, 0); + va_end(ap); + + return r; +} + +int fl_choice(const char*fmt,const char *b0,const char *b1,const char *b2,...){ + va_list ap; + + fl_beep(FL_BEEP_QUESTION); + + va_start(ap, b2); + int r = innards(fmt, ap, b0, b1, b2); + va_end(ap); + return r; +} + +Fl_Widget *fl_message_icon() {makeform(); return icon;} + +static const char* input_innards(const char* fmt, va_list ap, + const char* defstr, uchar type) { + makeform(); + message->position(60,10); + input->type(type); + input->show(); + input->value(defstr); + input->take_focus(); + + int r = innards(fmt, ap, fl_cancel, fl_ok, 0); + input->hide(); + message->position(60,25); + return r ? input->value() : 0; +} + +const char* fl_input(const char *fmt, const char *defstr, ...) { + fl_beep(FL_BEEP_QUESTION); + + va_list ap; + va_start(ap, defstr); + const char* r = input_innards(fmt, ap, defstr, FL_NORMAL_INPUT); + va_end(ap); + return r; +} + +const char *fl_password(const char *fmt, const char *defstr, ...) { + fl_beep(FL_BEEP_PASSWORD); + + va_list ap; + va_start(ap, defstr); + const char* r = input_innards(fmt, ap, defstr, FL_SECRET_INPUT); + va_end(ap); + return r; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_boxtype.cxx b/Utilities/FLTK/src/fl_boxtype.cxx new file mode 100644 index 0000000000..727385369b --- /dev/null +++ b/Utilities/FLTK/src/fl_boxtype.cxx @@ -0,0 +1,311 @@ +// +// "$Id$" +// +// Box drawing code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Box drawing code for the common box types and the table of +// boxtypes. Other box types are in seperate files so they are not +// linked in if not used. + +#include <FL/Fl.H> +#include <FL/Fl_Widget.H> +#include <FL/fl_draw.H> +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +//////////////////////////////////////////////////////////////// + +static uchar active_ramp[24] = { + FL_GRAY_RAMP+0, FL_GRAY_RAMP+1, FL_GRAY_RAMP+2, FL_GRAY_RAMP+3, + FL_GRAY_RAMP+4, FL_GRAY_RAMP+5, FL_GRAY_RAMP+6, FL_GRAY_RAMP+7, + FL_GRAY_RAMP+8, FL_GRAY_RAMP+9, FL_GRAY_RAMP+10,FL_GRAY_RAMP+11, + FL_GRAY_RAMP+12,FL_GRAY_RAMP+13,FL_GRAY_RAMP+14,FL_GRAY_RAMP+15, + FL_GRAY_RAMP+16,FL_GRAY_RAMP+17,FL_GRAY_RAMP+18,FL_GRAY_RAMP+19, + FL_GRAY_RAMP+20,FL_GRAY_RAMP+21,FL_GRAY_RAMP+22,FL_GRAY_RAMP+23}; +static uchar inactive_ramp[24] = { + 43, 43, 44, 44, + 44, 45, 45, 46, + 46, 46, 47, 47, + 48, 48, 48, 49, + 49, 49, 50, 50, + 51, 51, 52, 52}; +static int draw_it_active = 1; + +int Fl::draw_box_active() { return draw_it_active; } + +uchar *fl_gray_ramp() {return (draw_it_active?active_ramp:inactive_ramp)-'A';} + +void fl_frame(const char* s, int x, int y, int w, int h) { + uchar *g = fl_gray_ramp(); + if (h > 0 && w > 0) for (;*s;) { + // draw top line: + fl_color(g[*s++]); + fl_xyline(x, y, x+w-1); + y++; if (--h <= 0) break; + // draw left line: + fl_color(g[*s++]); + fl_yxline(x, y+h-1, y); + x++; if (--w <= 0) break; + // draw bottom line: + fl_color(g[*s++]); + fl_xyline(x, y+h-1, x+w-1); + if (--h <= 0) break; + // draw right line: + fl_color(g[*s++]); + fl_yxline(x+w-1, y+h-1, y); + if (--w <= 0) break; + } +} + +void fl_frame2(const char* s, int x, int y, int w, int h) { + uchar *g = fl_gray_ramp(); + if (h > 0 && w > 0) for (;*s;) { + // draw bottom line: + fl_color(g[*s++]); + fl_xyline(x, y+h-1, x+w-1); + if (--h <= 0) break; + // draw right line: + fl_color(g[*s++]); + fl_yxline(x+w-1, y+h-1, y); + if (--w <= 0) break; + // draw top line: + fl_color(g[*s++]); + fl_xyline(x, y, x+w-1); + y++; if (--h <= 0) break; + // draw left line: + fl_color(g[*s++]); + fl_yxline(x, y+h-1, y); + x++; if (--w <= 0) break; + } +} + +void fl_no_box(int, int, int, int, Fl_Color) {} + +void fl_thin_down_frame(int x, int y, int w, int h, Fl_Color) { + fl_frame2("WWHH",x,y,w,h); +} + +void fl_thin_down_box(int x, int y, int w, int h, Fl_Color c) { + fl_thin_down_frame(x,y,w,h,c); + fl_color(draw_it_active ? c : fl_inactive(c)); + fl_rectf(x+1, y+1, w-2, h-2); +} + +void fl_thin_up_frame(int x, int y, int w, int h, Fl_Color) { + fl_frame2("HHWW",x,y,w,h); +} + +void fl_thin_up_box(int x, int y, int w, int h, Fl_Color c) { + fl_thin_up_frame(x,y,w,h,c); + fl_color(draw_it_active ? c : fl_inactive(c)); + fl_rectf(x+1, y+1, w-2, h-2); +} + +void fl_up_frame(int x, int y, int w, int h, Fl_Color) { +#if BORDER_WIDTH == 1 + fl_frame2("HHWW",x,y,w,h); +#else +#if BORDER_WIDTH == 2 + fl_frame2("AAWWMMTT",x,y,w,h); +#else + fl_frame("AAAAWWJJUTNN",x,y,w,h); +#endif +#endif +} + +#define D1 BORDER_WIDTH +#define D2 (BORDER_WIDTH+BORDER_WIDTH) + +void fl_up_box(int x, int y, int w, int h, Fl_Color c) { + fl_up_frame(x,y,w,h,c); + fl_color(draw_it_active ? c : fl_inactive(c)); + fl_rectf(x+D1, y+D1, w-D2, h-D2); +} + +void fl_down_frame(int x, int y, int w, int h, Fl_Color) { +#if BORDER_WIDTH == 1 + fl_frame2("WWHH",x,y,w,h); +#else +#if BORDER_WIDTH == 2 + fl_frame2("WWMMPPAA",x,y,w,h); +#else + fl_frame("NNTUJJWWAAAA",x,y,w,h); +#endif +#endif +} + +void fl_down_box(int x, int y, int w, int h, Fl_Color c) { + fl_down_frame(x,y,w,h,c); + fl_color(c); fl_rectf(x+D1, y+D1, w-D2, h-D2); +} + +void fl_engraved_frame(int x, int y, int w, int h, Fl_Color) { + fl_frame("HHWWWWHH",x,y,w,h); +} + +void fl_engraved_box(int x, int y, int w, int h, Fl_Color c) { + fl_engraved_frame(x,y,w,h,c); + fl_color(draw_it_active ? c : fl_inactive(c)); + fl_rectf(x+2, y+2, w-4, h-4); +} + +void fl_embossed_frame(int x, int y, int w, int h, Fl_Color) { + fl_frame("WWHHHHWW",x,y,w,h); +} + +void fl_embossed_box(int x, int y, int w, int h, Fl_Color c) { + fl_embossed_frame(x,y,w,h,c); + fl_color(draw_it_active ? c : fl_inactive(c)); + fl_rectf(x+2, y+2, w-4, h-4); +} + +void fl_rectbound(int x, int y, int w, int h, Fl_Color bgcolor) { + fl_color(draw_it_active ? FL_BLACK : fl_inactive(FL_BLACK)); + fl_rect(x, y, w, h); + fl_color(draw_it_active ? bgcolor : fl_inactive(bgcolor)); + fl_rectf(x+1, y+1, w-2, h-2); +} +#define fl_border_box fl_rectbound + +void fl_border_frame(int x, int y, int w, int h, Fl_Color c) { + fl_color(draw_it_active ? c : fl_inactive(c)); + fl_rect(x, y, w, h); +} + +//////////////////////////////////////////////////////////////// + +static struct { + Fl_Box_Draw_F *f; + uchar dx, dy, dw, dh; + int set; +} fl_box_table[256] = { +// must match list in Enumerations.H!!! + {fl_no_box, 0,0,0,0,1}, + {fl_rectf, 0,0,0,0,1}, // FL_FLAT_BOX + {fl_up_box, D1,D1,D2,D2,1}, + {fl_down_box, D1,D1,D2,D2,1}, + {fl_up_frame, D1,D1,D2,D2,1}, + {fl_down_frame, D1,D1,D2,D2,1}, + {fl_thin_up_box, 1,1,2,2,1}, + {fl_thin_down_box, 1,1,2,2,1}, + {fl_thin_up_frame, 1,1,2,2,1}, + {fl_thin_down_frame, 1,1,2,2,1}, + {fl_engraved_box, 2,2,4,4,1}, + {fl_embossed_box, 2,2,4,4,1}, + {fl_engraved_frame, 2,2,4,4,1}, + {fl_embossed_frame, 2,2,4,4,1}, + {fl_border_box, 1,1,2,2,1}, + {fl_border_box, 1,1,5,5,0}, // _FL_SHADOW_BOX, + {fl_border_frame, 1,1,2,2,1}, + {fl_border_frame, 1,1,5,5,0}, // _FL_SHADOW_FRAME, + {fl_border_box, 1,1,2,2,0}, // _FL_ROUNDED_BOX, + {fl_border_box, 1,1,2,2,0}, // _FL_RSHADOW_BOX, + {fl_border_frame, 1,1,2,2,0}, // _FL_ROUNDED_FRAME + {fl_rectf, 0,0,0,0,0}, // _FL_RFLAT_BOX, + {fl_up_box, 3,3,6,6,0}, // _FL_ROUND_UP_BOX + {fl_down_box, 3,3,6,6,0}, // _FL_ROUND_DOWN_BOX, + {fl_up_box, 0,0,0,0,0}, // _FL_DIAMOND_UP_BOX + {fl_down_box, 0,0,0,0,0}, // _FL_DIAMOND_DOWN_BOX + {fl_border_box, 1,1,2,2,0}, // _FL_OVAL_BOX, + {fl_border_box, 1,1,2,2,0}, // _FL_OVAL_SHADOW_BOX, + {fl_border_frame, 1,1,2,2,0}, // _FL_OVAL_FRAME + {fl_rectf, 0,0,0,0,0}, // _FL_OVAL_FLAT_BOX, + {fl_up_box, 4,4,8,8,0}, // _FL_PLASTIC_UP_BOX, + {fl_down_box, 2,2,4,4,0}, // _FL_PLASTIC_DOWN_BOX, + {fl_up_frame, 2,2,4,4,0}, // _FL_PLASTIC_UP_FRAME, + {fl_down_frame, 2,2,4,4,0}, // _FL_PLASTIC_DOWN_FRAME, + {fl_up_box, 2,2,4,4,0}, // _FL_PLASTIC_THIN_UP_BOX, + {fl_down_box, 2,2,4,4,0}, // _FL_PLASTIC_THIN_DOWN_BOX, + {fl_up_box, 3,3,6,6,0}, // FL_FREE_BOX+0 + {fl_down_box, 3,3,6,6,0}, // FL_FREE_BOX+1 + {fl_up_box, 3,3,6,6,0}, // FL_FREE_BOX+2 + {fl_down_box, 3,3,6,6,0}, // FL_FREE_BOX+3 + {fl_up_box, 3,3,6,6,0}, // FL_FREE_BOX+4 + {fl_down_box, 3,3,6,6,0}, // FL_FREE_BOX+5 + {fl_up_box, 3,3,6,6,0}, // FL_FREE_BOX+6 + {fl_down_box, 3,3,6,6,0}, // FL_FREE_BOX+7 +}; + +int Fl::box_dx(Fl_Boxtype t) {return fl_box_table[t].dx;} +int Fl::box_dy(Fl_Boxtype t) {return fl_box_table[t].dy;} +int Fl::box_dw(Fl_Boxtype t) {return fl_box_table[t].dw;} +int Fl::box_dh(Fl_Boxtype t) {return fl_box_table[t].dh;} + +void fl_internal_boxtype(Fl_Boxtype t, Fl_Box_Draw_F* f) { + if (!fl_box_table[t].set) { + fl_box_table[t].f = f; + fl_box_table[t].set = 1; + } +} + +Fl_Box_Draw_F *Fl::get_boxtype(Fl_Boxtype t) { + return fl_box_table[t].f; +} + +void Fl::set_boxtype(Fl_Boxtype t, Fl_Box_Draw_F* f, + uchar a, uchar b, uchar c, uchar d) { + fl_box_table[t].f = f; + fl_box_table[t].set = 1; + fl_box_table[t].dx = a; + fl_box_table[t].dy = b; + fl_box_table[t].dw = c; + fl_box_table[t].dh = d; +} + +void Fl::set_boxtype(Fl_Boxtype t, Fl_Boxtype f) { + fl_box_table[t] = fl_box_table[f]; +} + +void fl_draw_box(Fl_Boxtype t, int x, int y, int w, int h, Fl_Color c) { + if (t && fl_box_table[t].f) fl_box_table[t].f(x,y,w,h,c); +} + +//extern Fl_Widget *fl_boxcheat; // hack set by Fl_Window.cxx + +void Fl_Widget::draw_box() const { + int t = box_; + if (!t) return; +// if (this == fl_boxcheat) { +// fl_boxcheat = 0; +// if (t == FL_FLAT_BOX) return; +// t += 2; // convert box to frame +// } + draw_box((Fl_Boxtype)t, x_, y_, w_, h_, (Fl_Color)color_); +} + +void Fl_Widget::draw_box(Fl_Boxtype b, Fl_Color c) const { + draw_box(b, x_, y_, w_, h_, c); +} + +void Fl_Widget::draw_box(Fl_Boxtype b, int X, int Y, int W, int H, Fl_Color c) +const { + draw_it_active = active_r(); + fl_box_table[b].f(X, Y, W, H, c); + draw_it_active = 1; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_call_main.c b/Utilities/FLTK/src/fl_call_main.c new file mode 100644 index 0000000000..81c1baef68 --- /dev/null +++ b/Utilities/FLTK/src/fl_call_main.c @@ -0,0 +1,107 @@ +/* + * "$Id$" + * + * Copyright 1998-2005 by Bill Spitzak and others. + * + * fl_call_main() calls main() for you Windows people. Needs to be done in C + * because Borland C++ won't let you call main() from C++. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems on the following page: + * + * http://www.fltk.org/str.php + */ + +/* + * This WinMain() function can be overridden by an application and + * is provided for compatibility with programs written for other + * operating systems that conform to the ANSI standard entry point + * "main()". This will allow you to build a WIN32 Application + * without any special settings. + * + * Because of problems with the Microsoft Visual C++ header files + * and/or compiler, you cannot have a WinMain function in a DLL. + * I don't know why. Thus, this nifty feature is only available + * if you link to the static library. + * + * Currently the debug version of this library will create a + * console window for your application so you can put printf() + * statements for debugging or informational purposes. Ultimately + * we want to update this to always use the parent's console, + * but at present we have not identified a function or API in + * Microsoft(r) Windows(r) that allows for it. + */ + +#if defined(WIN32) && !defined(FL_DLL) && !defined (__GNUC__) + +#include <windows.h> +#include <stdio.h> +#include <stdlib.h> + +#ifdef __MWERKS__ +# include <crtl.h> +#endif + +extern int main(int, char *[]); + +#ifdef BORLAND5 +# define __argc _argc +# define __argv _argv +#endif + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPSTR lpCmdLine, int nCmdShow) { + int rc; + +#ifdef _DEBUG + /* + * If we are using compiling in debug mode, open a console window so + * we can see any printf's, etc... + * + * While we can detect if the program was run from the command-line - + * look at the CMDLINE environment variable, it will be "WIN" for + * programs started from the GUI - the shell seems to run all WIN32 + * applications in the background anyways... + */ + + AllocConsole(); + freopen("conin$", "r", stdin); + freopen("conout$", "w", stdout); + freopen("conout$", "w", stderr); +#endif /* _DEBUG */ + + /* Run the standard main entry point function... */ + rc = main(__argc, __argv); + +#ifdef _DEBUG + fclose(stdin); + fclose(stdout); + fclose(stderr); +#endif /* _DEBUG */ + + return rc; +} + +#else +/* This code to prevent "empty translation unit" or similar warnings... */ +static void dummy(void) {dummy();} +#endif + +/* + * End of "$Id$". + */ + diff --git a/Utilities/FLTK/src/fl_cmap.h b/Utilities/FLTK/src/fl_cmap.h new file mode 100644 index 0000000000..3b05ee7cf5 --- /dev/null +++ b/Utilities/FLTK/src/fl_cmap.h @@ -0,0 +1,256 @@ + 0x00000000, + 0xff000000, + 0x00ff0000, + 0xffff0000, + 0x0000ff00, + 0xff00ff00, + 0x00ffff00, + 0xffffff00, + 0x55555500, + 0xc6717100, + 0x71c67100, + 0x8e8e3800, + 0x7171c600, + 0x8e388e00, + 0x388e8e00, + 0x00008000, + 0xa8a89800, + 0xe8e8d800, + 0x68685800, + 0x98a8a800, + 0xd8e8e800, + 0x58686800, + 0x9c9ca800, + 0xdcdce800, + 0x5c5c6800, + 0x9ca89c00, + 0xdce8dc00, + 0x5c685c00, + 0x90909000, + 0xc0c0c000, + 0x50505000, + 0xa0a0a000, + 0x00000000, + 0x0d0d0d00, + 0x1a1a1a00, + 0x26262600, + 0x31313100, + 0x3d3d3d00, + 0x48484800, + 0x55555500, + 0x5f5f5f00, + 0x6a6a6a00, + 0x75757500, + 0x80808000, + 0x8a8a8a00, + 0x95959500, + 0xa0a0a000, + 0xaaaaaa00, + 0xb5b5b500, + 0xc0c0c000, + 0xcbcbcb00, + 0xd5d5d500, + 0xe0e0e000, + 0xeaeaea00, + 0xf5f5f500, + 0xffffff00, + 0x00000000, + 0x00240000, + 0x00480000, + 0x006d0000, + 0x00910000, + 0x00b60000, + 0x00da0000, + 0x00ff0000, + 0x3f000000, + 0x3f240000, + 0x3f480000, + 0x3f6d0000, + 0x3f910000, + 0x3fb60000, + 0x3fda0000, + 0x3fff0000, + 0x7f000000, + 0x7f240000, + 0x7f480000, + 0x7f6d0000, + 0x7f910000, + 0x7fb60000, + 0x7fda0000, + 0x7fff0000, + 0xbf000000, + 0xbf240000, + 0xbf480000, + 0xbf6d0000, + 0xbf910000, + 0xbfb60000, + 0xbfda0000, + 0xbfff0000, + 0xff000000, + 0xff240000, + 0xff480000, + 0xff6d0000, + 0xff910000, + 0xffb60000, + 0xffda0000, + 0xffff0000, + 0x00003f00, + 0x00243f00, + 0x00483f00, + 0x006d3f00, + 0x00913f00, + 0x00b63f00, + 0x00da3f00, + 0x00ff3f00, + 0x3f003f00, + 0x3f243f00, + 0x3f483f00, + 0x3f6d3f00, + 0x3f913f00, + 0x3fb63f00, + 0x3fda3f00, + 0x3fff3f00, + 0x7f003f00, + 0x7f243f00, + 0x7f483f00, + 0x7f6d3f00, + 0x7f913f00, + 0x7fb63f00, + 0x7fda3f00, + 0x7fff3f00, + 0xbf003f00, + 0xbf243f00, + 0xbf483f00, + 0xbf6d3f00, + 0xbf913f00, + 0xbfb63f00, + 0xbfda3f00, + 0xbfff3f00, + 0xff003f00, + 0xff243f00, + 0xff483f00, + 0xff6d3f00, + 0xff913f00, + 0xffb63f00, + 0xffda3f00, + 0xffff3f00, + 0x00007f00, + 0x00247f00, + 0x00487f00, + 0x006d7f00, + 0x00917f00, + 0x00b67f00, + 0x00da7f00, + 0x00ff7f00, + 0x3f007f00, + 0x3f247f00, + 0x3f487f00, + 0x3f6d7f00, + 0x3f917f00, + 0x3fb67f00, + 0x3fda7f00, + 0x3fff7f00, + 0x7f007f00, + 0x7f247f00, + 0x7f487f00, + 0x7f6d7f00, + 0x7f917f00, + 0x7fb67f00, + 0x7fda7f00, + 0x7fff7f00, + 0xbf007f00, + 0xbf247f00, + 0xbf487f00, + 0xbf6d7f00, + 0xbf917f00, + 0xbfb67f00, + 0xbfda7f00, + 0xbfff7f00, + 0xff007f00, + 0xff247f00, + 0xff487f00, + 0xff6d7f00, + 0xff917f00, + 0xffb67f00, + 0xffda7f00, + 0xffff7f00, + 0x0000bf00, + 0x0024bf00, + 0x0048bf00, + 0x006dbf00, + 0x0091bf00, + 0x00b6bf00, + 0x00dabf00, + 0x00ffbf00, + 0x3f00bf00, + 0x3f24bf00, + 0x3f48bf00, + 0x3f6dbf00, + 0x3f91bf00, + 0x3fb6bf00, + 0x3fdabf00, + 0x3fffbf00, + 0x7f00bf00, + 0x7f24bf00, + 0x7f48bf00, + 0x7f6dbf00, + 0x7f91bf00, + 0x7fb6bf00, + 0x7fdabf00, + 0x7fffbf00, + 0xbf00bf00, + 0xbf24bf00, + 0xbf48bf00, + 0xbf6dbf00, + 0xbf91bf00, + 0xbfb6bf00, + 0xbfdabf00, + 0xbfffbf00, + 0xff00bf00, + 0xff24bf00, + 0xff48bf00, + 0xff6dbf00, + 0xff91bf00, + 0xffb6bf00, + 0xffdabf00, + 0xffffbf00, + 0x0000ff00, + 0x0024ff00, + 0x0048ff00, + 0x006dff00, + 0x0091ff00, + 0x00b6ff00, + 0x00daff00, + 0x00ffff00, + 0x3f00ff00, + 0x3f24ff00, + 0x3f48ff00, + 0x3f6dff00, + 0x3f91ff00, + 0x3fb6ff00, + 0x3fdaff00, + 0x3fffff00, + 0x7f00ff00, + 0x7f24ff00, + 0x7f48ff00, + 0x7f6dff00, + 0x7f91ff00, + 0x7fb6ff00, + 0x7fdaff00, + 0x7fffff00, + 0xbf00ff00, + 0xbf24ff00, + 0xbf48ff00, + 0xbf6dff00, + 0xbf91ff00, + 0xbfb6ff00, + 0xbfdaff00, + 0xbfffff00, + 0xff00ff00, + 0xff24ff00, + 0xff48ff00, + 0xff6dff00, + 0xff91ff00, + 0xffb6ff00, + 0xffdaff00, + 0xffffff00 diff --git a/Utilities/FLTK/src/fl_color.cxx b/Utilities/FLTK/src/fl_color.cxx new file mode 100644 index 0000000000..d2dcefb1c1 --- /dev/null +++ b/Utilities/FLTK/src/fl_color.cxx @@ -0,0 +1,389 @@ +// +// "$Id$" +// +// Color functions for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Implementation of fl_color(i), fl_color(r,g,b). + +#ifdef WIN32 +# include "fl_color_win32.cxx" +#elif defined(__APPLE__) +# include "fl_color_mac.cxx" +#else + +// Also code to look at the X visual and figure out the best way to turn +// a color into a pixel value. + +// SGI compiler seems to have problems with unsigned char arguments +// being used to index arrays. So I always copy them to an integer +// before use. + +# include "Fl_XColor.H" +# include <FL/Fl.H> +# include <FL/x.H> +# include <FL/fl_draw.H> + +//////////////////////////////////////////////////////////////// +// figure_out_visual() calculates masks & shifts for generating +// pixels in true-color visuals: + +uchar fl_redmask, fl_greenmask, fl_bluemask; +int fl_redshift, fl_greenshift, fl_blueshift, fl_extrashift; +static uchar beenhere; + +static void figure_out_visual() { + beenhere = 1; + if (!fl_visual->red_mask || !fl_visual->green_mask || !fl_visual->blue_mask){ +# if USE_COLORMAP + fl_redmask = 0; + return; +# else + Fl::fatal("Requires true color visual"); +# endif + } + + // get the bit masks into a more useful form: + int i,j,m; + + for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->red_mask & m) break; + for (j = i; m; j++, m<<=1) if (!(fl_visual->red_mask & m)) break; + fl_redshift = j-8; + fl_redmask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i)); + + for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->green_mask & m) break; + for (j = i; m; j++, m<<=1) if (!(fl_visual->green_mask & m)) break; + fl_greenshift = j-8; + fl_greenmask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i)); + + for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->blue_mask & m) break; + for (j = i; m; j++, m<<=1) if (!(fl_visual->blue_mask & m)) break; + fl_blueshift = j-8; + fl_bluemask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i)); + + i = fl_redshift; + if (fl_greenshift < i) i = fl_greenshift; + if (fl_blueshift < i) i = fl_blueshift; + if (i < 0) { + fl_extrashift = -i; + fl_redshift -= i; fl_greenshift -= i; fl_blueshift -= i; + } else + fl_extrashift = 0; + +} + +static unsigned fl_cmap[256] = { +#include "fl_cmap.h" // this is a file produced by "cmap.cxx": +}; + +# if HAVE_OVERLAY +Fl_XColor fl_xmap[2][256]; +uchar fl_overlay; +Colormap fl_overlay_colormap; +XVisualInfo* fl_overlay_visual; +ulong fl_transparent_pixel; +# else +Fl_XColor fl_xmap[1][256]; +# define fl_overlay 0 +# endif + +//////////////////////////////////////////////////////////////// +// Get an rgb color. This is easy for a truecolor visual. For +// colormapped it picks the closest color out of the cube in the +// fltk colormap. However if this color cube entry has been +// requested before, you will get the earlier requested color, and +// even this may be approximated if the X colormap was full. + +ulong fl_xpixel(uchar r,uchar g,uchar b) { + if (!beenhere) figure_out_visual(); +# if USE_COLORMAP + if (!fl_redmask) { + // find closest entry in the colormap: + Fl_Color i = + fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256); + Fl_XColor &xmap = fl_xmap[fl_overlay][i]; + if (xmap.mapped) return xmap.pixel; + // if not black or white, change the entry to be an exact match: + if (i != FL_COLOR_CUBE && i != 0xFF) + fl_cmap[i] = (r<<24)|(g<<16)|(b<<8); + return fl_xpixel(i); // allocate an X color + } +# endif + return + (((r&fl_redmask) << fl_redshift)+ + ((g&fl_greenmask)<<fl_greenshift)+ + ((b&fl_bluemask)<< fl_blueshift) + ) >> fl_extrashift; +} + +void fl_color(uchar r,uchar g,uchar b) { + fl_color_ = fl_rgb_color(r, g, b); + XSetForeground(fl_display, fl_gc, fl_xpixel(r,g,b)); +} + +//////////////////////////////////////////////////////////////// +// Get a color out of the the fltk colormap. Again for truecolor +// visuals this is easy. For colormap this actually tries to allocate +// an X color, and does a least-squares match to find the closest +// color if X cannot allocate that color. + +// calculate what color is actually on the screen for a mask: +static inline uchar realcolor(uchar color, uchar mask) { +# if 0 + // accurate version if the display has linear gamma, but fl_draw_image + // works better with the simpler version on most screens... + uchar m = mask; + uchar result = color&m; + for (;;) { + while (m&mask) {m>>=1; color>>=1;} + if (!m) break; + mask = m; + result |= color&m; + } + return result; +# else + return (color&mask) | (~mask)&(mask>>1); +# endif +} + +ulong fl_xpixel(Fl_Color i) { + if (i & 0xffffff00) { + return fl_xpixel((i >> 24) & 255, (i >> 16) & 255, (i >> 8) & 255); + } + + Fl_XColor &xmap = fl_xmap[fl_overlay][i]; + if (xmap.mapped) return xmap.pixel; + + if (!beenhere) figure_out_visual(); + + uchar r,g,b; + {unsigned c = fl_cmap[i]; r=uchar(c>>24); g=uchar(c>>16); b=uchar(c>>8);} + +# if USE_COLORMAP + Colormap colormap = fl_colormap; +# if HAVE_OVERLAY + if (fl_overlay) colormap = fl_overlay_colormap; else +# endif + if (fl_redmask) { +# endif + // return color for a truecolor visual: + xmap.mapped = 2; // 2 prevents XFreeColor from being called + xmap.r = realcolor(r, fl_redmask); + xmap.g = realcolor(g, fl_greenmask); + xmap.b = realcolor(b, fl_bluemask); + return xmap.pixel = + (((r&fl_redmask) << fl_redshift)+ + ((g&fl_greenmask)<<fl_greenshift)+ + ((b&fl_bluemask)<< fl_blueshift) + ) >> fl_extrashift; +# if USE_COLORMAP + } +# if HAVE_OVERLAY + static XColor* ac[2]; + XColor*& allcolors = ac[fl_overlay]; + static int nc[2]; + int& numcolors = nc[fl_overlay]; +# else + static XColor *allcolors; + static int numcolors; +# endif + + // I don't try to allocate colors with XAllocColor once it fails + // with any color. It is possible that it will work, since a color + // may have been freed, but some servers are extremely slow and this + // avoids one round trip: + if (!numcolors) { // don't try after a failure + XColor xcol; + xcol.red = r<<8; xcol.green = g<<8; xcol.blue = b<<8; + if (XAllocColor(fl_display, colormap, &xcol)) { + xmap.mapped = 1; + xmap.r = xcol.red>>8; + xmap.g = xcol.green>>8; + xmap.b = xcol.blue>>8; + return xmap.pixel = xcol.pixel; + } + + // I only read the colormap once. Again this is due to the slowness + // of round-trips to the X server, even though other programs may alter + // the colormap after this and make decisions here wrong. +# if HAVE_OVERLAY + if (fl_overlay) numcolors = fl_overlay_visual->colormap_size; else +# endif + numcolors = fl_visual->colormap_size; + if (!allcolors) allcolors = new XColor[numcolors]; + for (int p = numcolors; p--;) allcolors[p].pixel = p; + XQueryColors(fl_display, colormap, allcolors, numcolors); + } + + // find least-squares match: + int mindist = 0x7FFFFFFF; + unsigned int bestmatch = 0; + for (unsigned int n = numcolors; n--;) { +# if HAVE_OVERLAY + if (fl_overlay && n == fl_transparent_pixel) continue; +# endif + XColor &a = allcolors[n]; + int d, t; + t = int(r)-int(a.red>>8); d = t*t; + t = int(g)-int(a.green>>8); d += t*t; + t = int(b)-int(a.blue>>8); d += t*t; + if (d <= mindist) {bestmatch = n; mindist = d;} + } + XColor &p = allcolors[bestmatch]; + + // It appears to "work" to not call this XAllocColor, which will + // avoid another round-trip to the server. But then X does not + // know that this program "owns" this value, and can (and will) + // change it when the program that did allocate it exits: + if (XAllocColor(fl_display, colormap, &p)) { + xmap.mapped = 1; + xmap.pixel = p.pixel; + } else { + // However, if that XAllocColor fails, I have to give up and + // assumme the pixel is ok for the duration of the program. This + // is due to bugs (?) in the Solaris X and some X terminals + // where XAllocColor *always* fails when the colormap is full, + // even if we ask for a color already in it... + xmap.mapped = 2; // 2 prevents XFreeColor from being called + xmap.pixel = bestmatch; + } + xmap.r = p.red>>8; + xmap.g = p.green>>8; + xmap.b = p.blue>>8; + return xmap.pixel; +# endif +} + +Fl_Color fl_color_; + +void fl_color(Fl_Color i) { + if (i & 0xffffff00) { + unsigned rgb = (unsigned)i; + fl_color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8)); + } else { + fl_color_ = i; + XSetForeground(fl_display, fl_gc, fl_xpixel(i)); + } +} + +void Fl::free_color(Fl_Color i, int overlay) { +# if HAVE_OVERLAY +# else + if (overlay) return; +# endif + if (fl_xmap[overlay][i].mapped) { +# if USE_COLORMAP +# if HAVE_OVERLAY + Colormap colormap = overlay ? fl_overlay_colormap : fl_colormap; +# else + Colormap colormap = fl_colormap; +# endif + if (fl_xmap[overlay][i].mapped == 1) + XFreeColors(fl_display, colormap, &(fl_xmap[overlay][i].pixel), 1, 0); +# endif + fl_xmap[overlay][i].mapped = 0; + } +} + +void Fl::set_color(Fl_Color i, unsigned c) { + if (fl_cmap[i] != c) { + free_color(i,0); +# if HAVE_OVERLAY + free_color(i,1); +# endif + fl_cmap[i] = c; + } +} + +#endif // end of X-specific code + +unsigned Fl::get_color(Fl_Color i) { + if (i & 0xffffff00) return (i); + else return fl_cmap[i]; +} + +void Fl::set_color(Fl_Color i, uchar red, uchar green, uchar blue) { + Fl::set_color((Fl_Color)(i & 255), + ((unsigned)red<<24)+((unsigned)green<<16)+((unsigned)blue<<8)); +} + +void Fl::get_color(Fl_Color i, uchar &red, uchar &green, uchar &blue) { + unsigned c; + + if (i & 0xffffff00) c = (unsigned)i; + else c = fl_cmap[i]; + + red = uchar(c>>24); + green = uchar(c>>16); + blue = uchar(c>>8); +} + +Fl_Color fl_color_average(Fl_Color color1, Fl_Color color2, float weight) { + unsigned rgb1; + unsigned rgb2; + uchar r, g, b; + + if (color1 & 0xffffff00) rgb1 = color1; + else rgb1 = fl_cmap[color1 & 255]; + + if (color2 & 0xffffff00) rgb2 = color2; + else rgb2 = fl_cmap[color2 & 255]; + + r = (uchar)(((uchar)(rgb1>>24))*weight + ((uchar)(rgb2>>24))*(1-weight)); + g = (uchar)(((uchar)(rgb1>>16))*weight + ((uchar)(rgb2>>16))*(1-weight)); + b = (uchar)(((uchar)(rgb1>>8))*weight + ((uchar)(rgb2>>8))*(1-weight)); + + return fl_rgb_color(r, g, b); +} + +Fl_Color fl_inactive(Fl_Color c) { + return fl_color_average(c, FL_GRAY, .33f); +} + +Fl_Color fl_contrast(Fl_Color fg, Fl_Color bg) { + unsigned c1, c2; // RGB colors + int l1, l2; // Luminosities + + + // Get the RGB values for each color... + if (fg & 0xffffff00) c1 = (unsigned)fg; + else c1 = fl_cmap[fg]; + + if (bg & 0xffffff00) c2 = (unsigned)bg; + else c2 = fl_cmap[bg]; + + // Compute the luminosity... + l1 = ((c1 >> 24) * 31 + ((c1 >> 16) & 255) * 61 + ((c1 >> 8) & 255) * 8) / 100; + l2 = ((c2 >> 24) * 31 + ((c2 >> 16) & 255) * 61 + ((c2 >> 8) & 255) * 8) / 100; + + // Compare and return the contrasting color... + if ((l1 - l2) > 127) return fg; + else if ((l2 - l1) > 127) return fg; + else if (l2 > 127) return FL_BLACK; + else return FL_WHITE; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_color_mac.cxx b/Utilities/FLTK/src/fl_color_mac.cxx new file mode 100644 index 0000000000..a69dc42fe0 --- /dev/null +++ b/Utilities/FLTK/src/fl_color_mac.cxx @@ -0,0 +1,115 @@ +// +// "$Id$" +// +// MacOS color functions for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// The fltk "colormap". This allows ui colors to be stored in 8-bit +// locations, and provides a level of indirection so that global color +// changes can be made. Not to be confused with the X colormap, which +// I try to hide completely. + +// matt: Neither Quartz nor Quickdraw support colormaps in this implementation +// matt: Quartz support done + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#include <FL/x.H> +#include <FL/fl_draw.H> + +static unsigned fl_cmap[256] = { +#include "fl_cmap.h" // this is a file produced by "cmap.cxx": +}; + +// Translations to mac data structures: +Fl_XMap fl_xmap[256]; + +Fl_XMap* fl_current_xmap; + +Fl_Color fl_color_; + +void fl_color(Fl_Color i) { + fl_color_ = i; + int index; + uchar r, g, b; + if (i & 0xFFFFFF00) { + // translate rgb colors into color index + r = i>>24; + g = i>>16; + b = i>> 8; + } else { + // translate index into rgb: + index = i; + unsigned c = fl_cmap[i]; + r = c>>24; + g = c>>16; + b = c>> 8; + } +#ifdef __APPLE_QD__ + RGBColor rgb; + rgb.red = (r<<8)|r; + rgb.green = (g<<8)|g; + rgb.blue = (b<<8)|b; + RGBForeColor(&rgb); +#elif defined(__APPLE_QUARTZ__) + if (!fl_gc) return; // no context yet? We will assign the color later. + float fr = r/255.0f; + float fg = g/255.0f; + float fb = b/255.0f; + CGContextSetRGBFillColor(fl_gc, fr, fg, fb, 1.0f); + CGContextSetRGBStrokeColor(fl_gc, fr, fg, fb, 1.0f); +#else +# error : neither Quickdraw nor Quartz defined +#endif +} + +void fl_color(uchar r, uchar g, uchar b) { + fl_color_ = fl_rgb_color(r, g, b); +#ifdef __APPLE_QD__ + RGBColor rgb; + rgb.red = (r<<8)|r; + rgb.green = (g<<8)|g; + rgb.blue = (b<<8)|b; + RGBForeColor(&rgb); +#elif defined(__APPLE_QUARTZ__) + float fr = r/255.0f; + float fg = g/255.0f; + float fb = b/255.0f; + CGContextSetRGBFillColor(fl_gc, fr, fg, fb, 1.0f); + CGContextSetRGBStrokeColor(fl_gc, fr, fg, fb, 1.0f); +#else +# error : neither Quickdraw nor Quartz defined +#endif +} + +void Fl::set_color(Fl_Color i, unsigned c) { + if (fl_cmap[i] != c) { + fl_cmap[i] = c; + } +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_color_win32.cxx b/Utilities/FLTK/src/fl_color_win32.cxx new file mode 100644 index 0000000000..faee2335a5 --- /dev/null +++ b/Utilities/FLTK/src/fl_color_win32.cxx @@ -0,0 +1,255 @@ +// +// "$Id$" +// +// WIN32 color functions for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// The fltk "colormap". This allows ui colors to be stored in 8-bit +// locations, and provides a level of indirection so that global color +// changes can be made. Not to be confused with the X colormap, which +// I try to hide completely. + +// SGI compiler seems to have problems with unsigned char arguments +// being used to index arrays. So I always copy them to an integer +// before use. + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#include <FL/x.H> +#include <FL/fl_draw.H> + +static unsigned fl_cmap[256] = { +#include "fl_cmap.h" // this is a file produced by "cmap.cxx": +}; + +// Translations to win32 data structures: +Fl_XMap fl_xmap[256]; + +Fl_XMap* fl_current_xmap; + +HPALETTE fl_palette; +static HGDIOBJ tmppen=0; +static HPEN savepen=0; + +void fl_cleanup_pens(void) { + for (int i=0; i<256; i++) { + if (fl_xmap[i].pen) DeleteObject(fl_xmap[i].pen); + } +} + +void fl_save_pen(void) { + if(!tmppen) tmppen = CreatePen(PS_SOLID, 1, 0); + savepen = (HPEN)SelectObject(fl_gc, tmppen); +} + +void fl_restore_pen(void) { + if (savepen) SelectObject(fl_gc, savepen); + DeleteObject(tmppen); + tmppen = 0; + savepen = 0; +} + +static void clear_xmap(Fl_XMap& xmap) { + if (xmap.pen) { + HGDIOBJ tmppen = GetStockObject(BLACK_PEN); + HGDIOBJ oldpen = SelectObject(fl_gc, tmppen); // Push out the current pen of the gc + if(oldpen != xmap.pen) SelectObject(fl_gc, oldpen); // Put it back if it is not the one we are about to delete + DeleteObject((HGDIOBJ)(xmap.pen)); + xmap.pen = 0; + xmap.brush = -1; + } +} + +static void set_xmap(Fl_XMap& xmap, COLORREF c) { + xmap.rgb = c; + if (xmap.pen) { + HGDIOBJ oldpen = SelectObject(fl_gc,GetStockObject(BLACK_PEN)); // replace current pen with safe one + if (oldpen != xmap.pen)SelectObject(fl_gc,oldpen); // if old one not xmap.pen, need to put it back + DeleteObject(xmap.pen); // delete pen + } + xmap.pen = CreatePen(PS_SOLID, 1, xmap.rgb); // get a pen into xmap.pen + xmap.brush = -1; +} + +Fl_Color fl_color_; + +void fl_color(Fl_Color i) { + if (i & 0xffffff00) { + unsigned rgb = (unsigned)i; + fl_color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8)); + } else { + fl_color_ = i; + Fl_XMap &xmap = fl_xmap[i]; + if (!xmap.pen) { +#if USE_COLORMAP + if (fl_palette) { + set_xmap(xmap, PALETTEINDEX(i)); + } else { +#endif + unsigned c = fl_cmap[i]; + set_xmap(xmap, RGB(uchar(c>>24), uchar(c>>16), uchar(c>>8))); +#if USE_COLORMAP + } +#endif + } + fl_current_xmap = ⟼ + SelectObject(fl_gc, (HGDIOBJ)(xmap.pen)); + } +} + +void fl_color(uchar r, uchar g, uchar b) { + static Fl_XMap xmap; + COLORREF c = RGB(r,g,b); + fl_color_ = fl_rgb_color(r, g, b); + if (!xmap.pen || c != xmap.rgb) { + clear_xmap(xmap); + set_xmap(xmap, c); + } + fl_current_xmap = ⟼ + SelectObject(fl_gc, (HGDIOBJ)(xmap.pen)); +} + +HBRUSH fl_brush() { + return fl_brush_action(0); +} + +HBRUSH fl_brush_action(int action) { + Fl_XMap *xmap = fl_current_xmap; + // Wonko: we use some statistics to cache only a limited number + // of brushes: +#define FL_N_BRUSH 16 + static struct Fl_Brush { + HBRUSH brush; + unsigned short usage; + Fl_XMap* backref; + } brushes[FL_N_BRUSH]; + + if (action) { + SelectObject(fl_gc, GetStockObject(BLACK_BRUSH)); // Load stock object + for (int i=0; i<FL_N_BRUSH; i++) { + if (brushes[i].brush) + DeleteObject(brushes[i].brush); // delete all brushes in array + } + return NULL; + } + + int i = xmap->brush; // find the associated brush + if (i != -1) { // if the brush was allready allocated + if (brushes[i].brush == NULL) goto CREATE_BRUSH; + if ( (++brushes[i].usage) > 32000 ) { // keep a usage statistic + for (int j=0; j<FL_N_BRUSH; j++) { + if (brushes[j].usage>16000) + brushes[j].usage -= 16000; + else + brushes[j].usage = 0; + } + } + return brushes[i].brush; + } else { + int umin = 32000, imin = 0; + for (i=0; i<FL_N_BRUSH; i++) { + if (brushes[i].brush == NULL) goto CREATE_BRUSH; + if (brushes[i].usage<umin) { + umin = brushes[i].usage; + imin = i; + } + } + i = imin; + HGDIOBJ tmpbrush = GetStockObject(BLACK_BRUSH); // get a stock brush + HGDIOBJ oldbrush = SelectObject(fl_gc,tmpbrush); // load in into current context + if (oldbrush != brushes[i].brush) SelectObject(fl_gc,oldbrush); // reload old one + DeleteObject(brushes[i].brush); // delete the one in list + brushes[i].brush = NULL; + brushes[i].backref->brush = -1; + } +CREATE_BRUSH: + brushes[i].brush = CreateSolidBrush(xmap->rgb); + brushes[i].usage = 0; + brushes[i].backref = xmap; + xmap->brush = i; + return brushes[i].brush; +} + +void Fl::free_color(Fl_Color i, int overlay) { + if (overlay) return; // do something about GL overlay? + clear_xmap(fl_xmap[i]); +} + +void Fl::set_color(Fl_Color i, unsigned c) { + if (fl_cmap[i] != c) { + clear_xmap(fl_xmap[i]); + fl_cmap[i] = c; + } +} + +#if USE_COLORMAP + +// 'fl_select_palette()' - Make a color palette for 8-bit displays if necessary +// Thanks to Michael Sweet @ Easy Software Products for this + +HPALETTE +fl_select_palette(void) +{ + static char beenhere; + if (!beenhere) { + beenhere = 1; + + //if (GetDeviceCaps(fl_gc, BITSPIXEL) > 8) return NULL; + int nColors = GetDeviceCaps(fl_gc, SIZEPALETTE); + if (nColors <= 0 || nColors > 256) return NULL; + // this will try to work on < 256 color screens, but will probably + // come out quite badly. + + // I lamely try to get this variable-sized object allocated on stack: + ulong foo[(sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY))/sizeof(ulong)+1]; + LOGPALETTE *pPal = (LOGPALETTE*)foo; + + pPal->palVersion = 0x300; + pPal->palNumEntries = nColors; + + // Build 256 colors from the standard FLTK colormap... + + for (int i = 0; i < nColors; i ++) { + pPal->palPalEntry[i].peRed = (fl_cmap[i] >> 24) & 255; + pPal->palPalEntry[i].peGreen = (fl_cmap[i] >> 16) & 255; + pPal->palPalEntry[i].peBlue = (fl_cmap[i] >> 8) & 255; + pPal->palPalEntry[i].peFlags = 0; + }; + + // Create the palette: + fl_palette = CreatePalette(pPal); + } + if (fl_palette) { + SelectPalette(fl_gc, fl_palette, FALSE); + RealizePalette(fl_gc); + } + return fl_palette; +} + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_cursor.cxx b/Utilities/FLTK/src/fl_cursor.cxx new file mode 100644 index 0000000000..651c098d56 --- /dev/null +++ b/Utilities/FLTK/src/fl_cursor.cxx @@ -0,0 +1,326 @@ +// +// "$Id$" +// +// Mouse cursor support for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Change the current cursor. +// Under X the cursor is attached to the X window. I tried to hide +// this and pretend that changing the cursor is a drawing function. +// This avoids a field in the Fl_Window, and I suspect is more +// portable to other systems. + +#include <FL/Fl.H> +#include <FL/Fl_Window.H> +#include <FL/x.H> +#if !defined(WIN32) && !defined(__APPLE__) +# include <X11/cursorfont.h> +#endif +#include <FL/fl_draw.H> + +void fl_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) { + if (Fl::first_window()) Fl::first_window()->cursor(c,fg,bg); +} + +void Fl_Window::default_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) { +// if (c == FL_CURSOR_DEFAULT) c = FL_CURSOR_ARROW; + + cursor_default = c; + cursor_fg = fg; + cursor_bg = bg; + + cursor(c, fg, bg); +} + +#ifdef WIN32 + +# ifndef IDC_HAND +# define IDC_HAND MAKEINTRESOURCE(32649) +# endif // !IDC_HAND + +void Fl_Window::cursor(Fl_Cursor c, Fl_Color c1, Fl_Color c2) { + if (!shown()) return; + // the cursor must be set for the top level window, not for subwindows + Fl_Window *w = window(), *toplevel = this; + while (w) { toplevel = w; w = w->window(); } + if (toplevel != this) { toplevel->cursor(c, c1, c2); return; } + // now set the actual cursor + if (c == FL_CURSOR_DEFAULT) { + c = cursor_default; + } + if (c > FL_CURSOR_NESW) { + i->cursor = 0; + } else if (c == FL_CURSOR_DEFAULT) { + i->cursor = fl_default_cursor; + } else { + LPSTR n; + switch (c) { + case FL_CURSOR_ARROW: n = IDC_ARROW; break; + case FL_CURSOR_CROSS: n = IDC_CROSS; break; + case FL_CURSOR_WAIT: n = IDC_WAIT; break; + case FL_CURSOR_INSERT: n = IDC_IBEAM; break; + case FL_CURSOR_HELP: n = IDC_HELP; break; + case FL_CURSOR_HAND: { + OSVERSIONINFO osvi; + + // Get the OS version: Windows 98 and 2000 have a standard + // hand cursor. + memset(&osvi, 0, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + + if (osvi.dwMajorVersion > 4 || + (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion > 0 && + osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)) n = IDC_HAND; + else n = IDC_UPARROW; + } break; + case FL_CURSOR_MOVE: n = IDC_SIZEALL; break; + case FL_CURSOR_N: + case FL_CURSOR_S: + case FL_CURSOR_NS: n = IDC_SIZENS; break; + case FL_CURSOR_NE: + case FL_CURSOR_SW: + case FL_CURSOR_NESW: n = IDC_SIZENESW; break; + case FL_CURSOR_E: + case FL_CURSOR_W: + case FL_CURSOR_WE: n = IDC_SIZEWE; break; + case FL_CURSOR_SE: + case FL_CURSOR_NW: + case FL_CURSOR_NWSE: n = IDC_SIZENWSE; break; + default: n = IDC_NO; break; + } + i->cursor = LoadCursor(NULL, n); + } + SetCursor(i->cursor); +} + +#elif defined(__APPLE__) + +// warning: this function is only implemented in Quickdraw. The function +// below may not work If FLTK is compiled with Quartz enabled + +static Cursor crsrHAND = +{ + { 0x0600, 0x0900, 0x0900, 0x0900, 0x09C0, 0x0938, 0x6926, 0x9805, + 0x8801, 0x4801, 0x2002, 0x2002, 0x1004, 0x0804, 0x0408, 0x0408 }, + { 0x0600, 0x0F00, 0x0F00, 0x0F00, 0x0FC0, 0x0FF8, 0x6FFE, 0xFFFF, + 0xFFFF, 0x7FFF, 0x3FFE, 0x3FFE, 0x1FFC, 0x0FFC, 0x07F8, 0x07F8 }, + { 1, 5 } // Hotspot: ( y, x ) +}, *crsrHANDptr = &crsrHAND; +static Cursor crsrHELP = +{ + { 0x0000, 0x4000, 0x6000, 0x7000, 0x783C, 0x7C7E, 0x7E66, 0x7F06, + 0x7F8C, 0x7C18, 0x6C18, 0x4600, 0x0618, 0x0318, 0x0300, 0x0000 }, + { 0xC000, 0xE000, 0xF000, 0xF83C, 0xFC7E, 0xFEFF, 0xFFFF, 0xFFFF, + 0xFFFE, 0xFFFC, 0xFE3C, 0xEF3C, 0xCF3C, 0x07BC, 0x0798, 0x0380 }, + { 1, 1 } +}, *crsrHELPptr = &crsrHELP; +static Cursor crsrMOVE = +{ + { 0x0000, 0x0180, 0x03C0, 0x07E0, 0x07E0, 0x1998, 0x399C, 0x7FFE, + 0x7FFE, 0x399C, 0x1998, 0x07E0, 0x07E0, 0x03C0, 0x0180, 0x0000 }, + { 0x0180, 0x03C0, 0x07E0, 0x0FF0, 0x1FF8, 0x3FFC, 0x7FFE, 0xFFFF, + 0xFFFF, 0x7FFE, 0x3FFC, 0x1FF8, 0x0FF0, 0x07E0, 0x03C0, 0x0180 }, + { 8, 8 } +}, *crsrMOVEptr = &crsrMOVE; +static Cursor crsrNS = +{ + { 0x0000, 0x0180, 0x03C0, 0x07E0, 0x0FF0, 0x0180, 0x0180, 0x0180, + 0x0180, 0x0180, 0x0180, 0x0FF0, 0x07E0, 0x03C0, 0x0180, 0x0000 }, + { 0x0180, 0x03C0, 0x07E0, 0x0FF0, 0x1FF8, 0x1FF8, 0x03C0, 0x03C0, + 0x03C0, 0x03C0, 0x1FF8, 0x1FF8, 0x0FF0, 0x07E0, 0x03C0, 0x0180 }, + { 8, 8 } +}, *crsrNSptr = &crsrNS; +static Cursor crsrWE = +{ + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0810, 0x1818, 0x381C, 0x7FFE, + 0x7FFE, 0x381C, 0x1818, 0x0810, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0x0000, 0x0000, 0x0000, 0x0C30, 0x1C38, 0x3C3C, 0x7FFE, 0xFFFF, + 0xFFFF, 0x7FFE, 0x3C3C, 0x1C38, 0x0C30, 0x0000, 0x0000, 0x0000 }, + { 8, 8 } +}, *crsrWEptr = &crsrWE; +static Cursor crsrNWSE = +{ + { 0x0000, 0x7E00, 0x7C00, 0x7800, 0x7C00, 0x6E00, 0x4710, 0x03B0, + 0x01F0, 0x00F0, 0x01F0, 0x03F0, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0xFF00, 0xFF00, 0xFE00, 0xFC00, 0xFE00, 0xFF18, 0xEFB8, 0xC7F8, + 0x03F8, 0x01F8, 0x03F8, 0x07F8, 0x07F8, 0x0000, 0x0000, 0x0000 }, + { 8, 8 } +}, *crsrNWSEptr = &crsrNWSE; +static Cursor crsrNESW = +{ + { 0x0000, 0x03F0, 0x01F0, 0x00F0, 0x01F0, 0x03B0, 0x4710, 0x6E00, + 0x7C00, 0x7800, 0x7C00, 0x7E00, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0x07F8, 0x07F8, 0x03F8, 0x01F8, 0x03F8, 0xC7F8, 0xEFB8, 0xFF18, + 0xFE00, 0xFC00, 0xFE00, 0xFF00, 0xFF00, 0x0000, 0x0000, 0x0000 }, + { 8, 8 } +}, *crsrNESWptr = &crsrNESW; +static Cursor crsrNONE = +{ + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0, 0 } +}, *crsrNONEptr = &crsrNONE; +static Cursor crsrARROW = +{ + { 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7C00, 0x7E00, 0x7F00, + 0x7F80, 0x7C00, 0x6C00, 0x4600, 0x0600, 0x0300, 0x0300, 0x0000 }, + { 0xC000, 0xE000, 0xF000, 0xF800, 0xFC00, 0xFE00, 0xFF00, 0xFF80, + 0xFFC0, 0xFFC0, 0xFE00, 0xEF00, 0xCF00, 0x0780, 0x0780, 0x0380 }, + { 1, 1 } +}, *crsrARROWptr = &crsrARROW; + + +void Fl_Window::cursor(Fl_Cursor c, Fl_Color, Fl_Color) { + if (!shown()) return; + if (c == FL_CURSOR_DEFAULT) { + c = cursor_default; + } + switch (c) { + case FL_CURSOR_CROSS: i->cursor = GetCursor( crossCursor ); break; + case FL_CURSOR_WAIT: i->cursor = GetCursor( watchCursor ); break; + case FL_CURSOR_INSERT: i->cursor = GetCursor( iBeamCursor ); break; + case FL_CURSOR_N: + case FL_CURSOR_S: + case FL_CURSOR_NS: i->cursor = &crsrNSptr; break; + case FL_CURSOR_HELP: i->cursor = &crsrHELPptr; break; + case FL_CURSOR_HAND: i->cursor = &crsrHANDptr; break; + case FL_CURSOR_MOVE: i->cursor = &crsrMOVEptr; break; + case FL_CURSOR_NE: + case FL_CURSOR_SW: + case FL_CURSOR_NESW: i->cursor = &crsrNESWptr; break; + case FL_CURSOR_E: + case FL_CURSOR_W: + case FL_CURSOR_WE: i->cursor = &crsrWEptr; break; + case FL_CURSOR_SE: + case FL_CURSOR_NW: + case FL_CURSOR_NWSE: i->cursor = &crsrNWSEptr; break; + case FL_CURSOR_NONE: i->cursor = &crsrNONEptr; break; + case FL_CURSOR_ARROW: i->cursor = &crsrARROWptr; break; + case FL_CURSOR_DEFAULT: + default: + i->cursor = fl_default_cursor; break; + } + SetCursor( *i->cursor ); +} + +#else + +// I like the MSWindows resize cursors, so I duplicate them here: + +#define CURSORSIZE 16 +#define HOTXY 7 +static struct TableEntry { + uchar bits[CURSORSIZE*CURSORSIZE/8]; + uchar mask[CURSORSIZE*CURSORSIZE/8]; + Cursor cursor; +} table[] = { + {{ // FL_CURSOR_NS + 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0x80, 0x01, 0x80, 0x01, + 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, + 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00}, + { + 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf0, 0x0f, 0xc0, 0x03, + 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xf0, 0x0f, + 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01}}, + {{ // FL_CURSOR_EW + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, + 0x0c, 0x30, 0xfe, 0x7f, 0xfe, 0x7f, 0x0c, 0x30, 0x08, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1c, 0x38, + 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0x1c, 0x38, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{ // FL_CURSOR_NWSE + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x38, 0x00, 0x78, 0x00, + 0xe8, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x1c, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + { + 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x7c, 0x00, 0xfc, 0x00, + 0xfc, 0x01, 0xec, 0x03, 0xc0, 0x37, 0x80, 0x3f, 0x00, 0x3f, 0x00, 0x3e, + 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00}}, + {{ // FL_CURSOR_NESW + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1c, 0x00, 0x1e, + 0x00, 0x17, 0x80, 0x03, 0xc0, 0x01, 0xe8, 0x00, 0x78, 0x00, 0x38, 0x00, + 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3f, + 0x80, 0x3f, 0xc0, 0x37, 0xec, 0x03, 0xfc, 0x01, 0xfc, 0x00, 0x7c, 0x00, + 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0}, {0}} // FL_CURSOR_NONE & unknown +}; + +void Fl_Window::cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) { + if (!shown()) return; + Cursor xc; + int deleteit = 0; + if (c == FL_CURSOR_DEFAULT) { + c = cursor_default; + fg = cursor_fg; + bg = cursor_bg; + } + + if (!c) { + xc = None; + } else { + if (c >= FL_CURSOR_NS) { + TableEntry *q = (c > FL_CURSOR_NESW) ? table+4 : table+(c-FL_CURSOR_NS); + if (!(q->cursor)) { + XColor dummy = { 0 }; + Pixmap p = XCreateBitmapFromData(fl_display, + RootWindow(fl_display, fl_screen), (const char*)(q->bits), + CURSORSIZE, CURSORSIZE); + Pixmap m = XCreateBitmapFromData(fl_display, + RootWindow(fl_display, fl_screen), (const char*)(q->mask), + CURSORSIZE, CURSORSIZE); + q->cursor = XCreatePixmapCursor(fl_display, p,m,&dummy, &dummy, + HOTXY, HOTXY); + XFreePixmap(fl_display, m); + XFreePixmap(fl_display, p); + } + xc = q->cursor; + } else { + xc = XCreateFontCursor(fl_display, (c-1)*2); + deleteit = 1; + } + XColor fgc; + uchar r,g,b; + Fl::get_color(fg,r,g,b); + fgc.red = r<<8; fgc.green = g<<8; fgc.blue = b<<8; + XColor bgc; + Fl::get_color(bg,r,g,b); + bgc.red = r<<8; bgc.green = g<<8; bgc.blue = b<<8; + XRecolorCursor(fl_display, xc, &fgc, &bgc); + } + XDefineCursor(fl_display, fl_xid(this), xc); + if (deleteit) XFreeCursor(fl_display, xc); +} + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_curve.cxx b/Utilities/FLTK/src/fl_curve.cxx new file mode 100644 index 0000000000..e97579aa0a --- /dev/null +++ b/Utilities/FLTK/src/fl_curve.cxx @@ -0,0 +1,106 @@ +// +// "$Id$" +// +// Bezier curve functions for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Utility for drawing Bezier curves, adding the points to +// the current fl_begin/fl_vertex/fl_end path. +// Incremental math implementation: +// I very much doubt this is optimal! From Foley/vanDam page 511. +// If anybody has a better algorithim, please send it! + +#include <FL/fl_draw.H> +#include <math.h> + +void fl_curve(double X0, double Y0, + double X1, double Y1, + double X2, double Y2, + double X3, double Y3) { + + double x = fl_transform_x(X0,Y0); + double y = fl_transform_y(X0,Y0); + + // draw point 0: + fl_transformed_vertex(x,y); + + double x1 = fl_transform_x(X1,Y1); + double yy1 = fl_transform_y(X1,Y1); + double x2 = fl_transform_x(X2,Y2); + double y2 = fl_transform_y(X2,Y2); + double x3 = fl_transform_x(X3,Y3); + double y3 = fl_transform_y(X3,Y3); + + // find the area: + double a = fabs((x-x2)*(y3-yy1)-(y-y2)*(x3-x1)); + double b = fabs((x-x3)*(y2-yy1)-(y-y3)*(x2-x1)); + if (b > a) a = b; + + // use that to guess at the number of segments: + int n = int(sqrt(a)/4); + if (n > 1) { + if (n > 100) n = 100; // make huge curves not hang forever + + double e = 1.0/n; + + // calculate the coefficients of 3rd order equation: + double xa = (x3-3*x2+3*x1-x); + double xb = 3*(x2-2*x1+x); + double xc = 3*(x1-x); + // calculate the forward differences: + double dx1 = ((xa*e+xb)*e+xc)*e; + double dx3 = 6*xa*e*e*e; + double dx2 = dx3 + 2*xb*e*e; + + // calculate the coefficients of 3rd order equation: + double ya = (y3-3*y2+3*yy1-y); + double yb = 3*(y2-2*yy1+y); + double yc = 3*(yy1-y); + // calculate the forward differences: + double dy1 = ((ya*e+yb)*e+yc)*e; + double dy3 = 6*ya*e*e*e; + double dy2 = dy3 + 2*yb*e*e; + + // draw points 1 .. n-2: + for (int m=2; m<n; m++) { + x += dx1; + dx1 += dx2; + dx2 += dx3; + y += dy1; + dy1 += dy2; + dy2 += dy3; + fl_transformed_vertex(x,y); + } + + // draw point n-1: + fl_transformed_vertex(x+dx1, y+dy1); + } + + // draw point n: + fl_transformed_vertex(x3,y3); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_diamond_box.cxx b/Utilities/FLTK/src/fl_diamond_box.cxx new file mode 100644 index 0000000000..830a8beb70 --- /dev/null +++ b/Utilities/FLTK/src/fl_diamond_box.cxx @@ -0,0 +1,80 @@ +// +// "$Id$" +// +// Diamond box code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Box drawing code for an obscure box type. +// These box types are in seperate files so they are not linked +// in if not used. + +// The diamond box draws best if the area is square! + +#include <FL/Fl.H> +#include <FL/fl_draw.H> + +extern uchar* fl_gray_ramp(); + +static void fl_diamond_up_box(int x,int y,int w,int h,Fl_Color bgcolor) { + w &= -2; + h &= -2; + int x1 = x+w/2; + int y1 = y+h/2; + fl_color(bgcolor); fl_polygon(x+3, y1, x1,y+3, x+w-3,y1, x1,y+h-3); + uchar *g = fl_gray_ramp(); + fl_color(g['W']); fl_line(x+1, y1, x1, y+1, x+w-1, y1); + fl_color(g['U']); fl_line(x+2, y1, x1, y+2, x+w-2, y1); + fl_color(g['S']); fl_line(x+3, y1, x1, y+3, x+w-3, y1); + fl_color(g['P']); fl_line(x+3, y1, x1, y+h-3, x+w-3, y1); + fl_color(g['N']); fl_line(x+2, y1, x1, y+h-2, x+w-2, y1); + fl_color(g['H']); fl_line(x+1, y1, x1, y+h-1, x+w-1, y1); + fl_color(g['A']); fl_loop(x, y1, x1, y, x+w, y1, x1, y+h); +} + +static void fl_diamond_down_box(int x,int y,int w,int h,Fl_Color bgcolor) { + w &= -2; + h &= -2; + int x1 = x+w/2; + int y1 = y+h/2; + uchar *g = fl_gray_ramp(); + fl_color(g['P']); fl_line(x+0, y1, x1, y+0, x+w-0, y1); + fl_color(g['N']); fl_line(x+1, y1, x1, y+1, x+w-1, y1); + fl_color(g['H']); fl_line(x+2, y1, x1, y+2, x+w-2, y1); + fl_color(g['W']); fl_line(x+2, y1, x1, y+h-2, x+w-2, y1); + fl_color(g['U']); fl_line(x+1, y1, x1, y+h-1, x+w-1, y1); + fl_color(g['S']); fl_line(x+0, y1, x1, y+h-0, x+w-0, y1); + fl_color(bgcolor); fl_polygon(x+3, y1, x1,y+3, x+w-3,y1, x1,y+h-3); + fl_color(g['A']); fl_loop(x+3, y1, x1, y+3, x+w-3, y1, x1, y+h-3); +} + +extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*); +Fl_Boxtype fl_define_FL_DIAMOND_BOX() { + fl_internal_boxtype(_FL_DIAMOND_DOWN_BOX, fl_diamond_down_box); + fl_internal_boxtype(_FL_DIAMOND_UP_BOX,fl_diamond_up_box); + return _FL_DIAMOND_UP_BOX; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_dnd.cxx b/Utilities/FLTK/src/fl_dnd.cxx new file mode 100644 index 0000000000..1870bd7b36 --- /dev/null +++ b/Utilities/FLTK/src/fl_dnd.cxx @@ -0,0 +1,38 @@ +// +// "$Id$" +// +// Drag & Drop code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#ifdef WIN32 +# include "fl_dnd_win32.cxx" +#elif defined(__APPLE__) +# include "fl_dnd_mac.cxx" +#else +# include "fl_dnd_x.cxx" +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_dnd_mac.cxx b/Utilities/FLTK/src/fl_dnd_mac.cxx new file mode 100644 index 0000000000..4f805e842a --- /dev/null +++ b/Utilities/FLTK/src/fl_dnd_mac.cxx @@ -0,0 +1,91 @@ +// +// "$Id$" +// +// Drag & Drop code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to "fltk-bugs@fltk.org + +// This file contains win32-specific code for fltk which is always linked +// in. Search other files for "WIN32" or filenames ending in _win32.cxx +// for other system-specific code. + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#include <FL/x.H> +#include <FL/Fl_Window.H> + +// warning: this function is only implemented in Quickdraw. The function +// below may not work If FLTK is compiled with Quartz enabled + +extern EventRef fl_os_event; +extern char *fl_selection_buffer; +extern int fl_selection_length; + + +/** + * drag and drop whatever is in the cut-copy-paste buffer + * - create a selection first using: + * Fl::copy(const char *stuff, int len, 0) + */ +int Fl::dnd() +{ + OSErr result; + DragReference dragRef; + result = NewDrag( &dragRef ); + if ( result != noErr ) return false; + + result = AddDragItemFlavor( dragRef, 1, 'TEXT', fl_selection_buffer, fl_selection_length, 0 ); + if ( result != noErr ) { DisposeDrag( dragRef ); return false; } + + Point mp; + GetMouse(&mp); + LocalToGlobal( &mp ); + RgnHandle region = NewRgn(); + SetRectRgn( region, mp.h-10, mp.v-10, mp.h+10, mp.v+10 ); + RgnHandle r2 = NewRgn(); + SetRectRgn( r2, mp.h-8, mp.v-8, mp.h+8, mp.v+8 ); + DiffRgn( region, r2, region ); + DisposeRgn( r2 ); + + EventRecord event; + ConvertEventRefToEventRecord( fl_os_event, &event ); + result = TrackDrag( dragRef, &event, region ); + + Fl_Widget *w = Fl::pushed(); + if ( w ) + { + int old_event = Fl::e_number; + w->handle(Fl::e_number = FL_RELEASE); + Fl::e_number = old_event; + Fl::pushed( 0 ); + } + + if ( result != noErr ) { DisposeRgn( region ); DisposeDrag( dragRef ); return false; } + + DisposeRgn( region ); + DisposeDrag( dragRef ); + return true; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_dnd_win32.cxx b/Utilities/FLTK/src/fl_dnd_win32.cxx new file mode 100644 index 0000000000..1475a6775e --- /dev/null +++ b/Utilities/FLTK/src/fl_dnd_win32.cxx @@ -0,0 +1,404 @@ +// +// "$Id$" +// +// Drag & Drop code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to "fltk-bugs@fltk.org + +// This file contains win32-specific code for fltk which is always linked +// in. Search other files for "WIN32" or filenames ending in _win32.cxx +// for other system-specific code. + +#include <FL/Fl.H> +#include <FL/x.H> +#include <FL/Fl_Window.H> +#include "flstring.h" +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <time.h> +#if defined(__CYGWIN__) +#include <sys/time.h> +#include <unistd.h> +#else +#include <winsock.h> +#endif + +extern char *fl_selection_buffer[2]; +extern int fl_selection_length[2]; +extern int fl_selection_buffer_length[2]; +extern char fl_i_own_selection[2]; + +Fl_Window *fl_dnd_target_window = 0; + +// All of the following code requires GCC 3.x or a non-GNU compiler... +#if !defined(__GNUC__) || __GNUC__ >= 3 + +#include <ole2.h> +#include <shellapi.h> + +/** + * subclass the IDropTarget to receive data from DnD operations + */ +class FLDropTarget : public IDropTarget +{ + DWORD m_cRefCount; + DWORD lastEffect; + int px, py; +public: + FLDropTarget() : m_cRefCount(0) { } // initialize + HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, LPVOID *ppvObject ) { + if (IID_IUnknown==riid || IID_IDropTarget==riid) + { + *ppvObject=this; + ((LPUNKNOWN)*ppvObject)->AddRef(); + return S_OK; + } + *ppvObject = NULL; + return E_NOINTERFACE; + } + ULONG STDMETHODCALLTYPE AddRef() { return ++m_cRefCount; } + ULONG STDMETHODCALLTYPE Release() { + long nTemp; + nTemp = --m_cRefCount; + if(nTemp==0) + delete this; + return nTemp; + } + HRESULT STDMETHODCALLTYPE DragEnter( IDataObject *pDataObj, DWORD /*grfKeyState*/, POINTL pt, DWORD *pdwEffect) { + if( !pDataObj ) return E_INVALIDARG; + // set e_modifiers here from grfKeyState, set e_x and e_root_x + // check if FLTK handles this drag and return if it can't (i.e. BMP drag without filename) + POINT ppt; + Fl::e_x_root = ppt.x = pt.x; + Fl::e_y_root = ppt.y = pt.y; + HWND hWnd = WindowFromPoint( ppt ); + Fl_Window *target = fl_find( hWnd ); + if (target) { + Fl::e_x = Fl::e_x_root-target->x(); + Fl::e_y = Fl::e_y_root-target->y(); + } + fl_dnd_target_window = target; + px = pt.x; py = pt.y; + if (fillCurrentDragData(pDataObj)) { + // FLTK has no mechanism yet for the different drop effects, so we allow move and copy + if ( target && Fl::handle( FL_DND_ENTER, target ) ) + *pdwEffect = DROPEFFECT_MOVE|DROPEFFECT_COPY; //|DROPEFFECT_LINK; + else + *pdwEffect = DROPEFFECT_NONE; + } else { + *pdwEffect = DROPEFFECT_NONE; + } + lastEffect = *pdwEffect; + return S_OK; + } + HRESULT STDMETHODCALLTYPE DragOver( DWORD /*grfKeyState*/, POINTL pt, DWORD *pdwEffect) { + if ( px==pt.x && py==pt.y ) + { + *pdwEffect = lastEffect; + return S_OK; + } + if ( !fl_dnd_target_window ) + { + *pdwEffect = lastEffect = DROPEFFECT_NONE; + return S_OK; + } + // set e_modifiers here from grfKeyState, set e_x and e_root_x + Fl::e_x_root = pt.x; + Fl::e_y_root = pt.y; + if (fl_dnd_target_window) { + Fl::e_x = Fl::e_x_root-fl_dnd_target_window->x(); + Fl::e_y = Fl::e_y_root-fl_dnd_target_window->y(); + } + if (fillCurrentDragData(0)) { + // Fl_Group will change DND_DRAG into DND_ENTER and DND_LEAVE if needed + if ( Fl::handle( FL_DND_DRAG, fl_dnd_target_window ) ) + *pdwEffect = DROPEFFECT_MOVE|DROPEFFECT_COPY; //|DROPEFFECT_LINK; + else + *pdwEffect = DROPEFFECT_NONE; + } else { + *pdwEffect = DROPEFFECT_NONE; + } + px = pt.x; py = pt.y; + lastEffect = *pdwEffect; + return S_OK; + } + HRESULT STDMETHODCALLTYPE DragLeave() { + if ( fl_dnd_target_window && fillCurrentDragData(0)) + { + Fl::handle( FL_DND_LEAVE, fl_dnd_target_window ); + fl_dnd_target_window = 0; + clearCurrentDragData(); + } + return S_OK; + } + HRESULT STDMETHODCALLTYPE Drop( IDataObject *data, DWORD /*grfKeyState*/, POINTL pt, DWORD* /*pdwEffect*/) { + if ( !fl_dnd_target_window ) + return S_OK; + Fl_Window *target = fl_dnd_target_window; + fl_dnd_target_window = 0; + Fl::e_x_root = pt.x; + Fl::e_y_root = pt.y; + if (target) { + Fl::e_x = Fl::e_x_root-target->x(); + Fl::e_y = Fl::e_y_root-target->y(); + } + // tell FLTK that the user released an object on this widget + if ( !Fl::handle( FL_DND_RELEASE, target ) ) + return S_OK; + + Fl_Widget *w = target; + while (w->parent()) w = w->window(); + HWND hwnd = fl_xid( (Fl_Window*)w ); + if (fillCurrentDragData(data)) { + int old_event = Fl::e_number; + Fl::belowmouse()->handle(Fl::e_number = FL_PASTE); // e_text will be invalid after this call + Fl::e_number = old_event; + SetForegroundWindow( hwnd ); + clearCurrentDragData(); + return S_OK; + } + return S_OK; + } +private: + + static IDataObject *currDragRef; + static char *currDragData; + static int currDragSize; + static char currDragResult; + + static void clearCurrentDragData() { + currDragRef = 0; + if (currDragData) free(currDragData); + currDragData = 0; + currDragSize = 0; + currDragResult = 0; + } + static char fillCurrentDragData(IDataObject *data) { + // shortcut through this whole procedure if there is no fresh data + if (!data) + return currDragResult; + // shortcut through this whole procedure if this is still the same drag event + // (* this is safe, because 'currDragRef' is cleared on Leave and Drop events) + if (data==currDragRef) + return currDragResult; + + // clear currDrag* for a new drag event + clearCurrentDragData(); + + // fill currDrag* with ASCII data, if available + FORMATETC fmt = { 0 }; + STGMEDIUM medium = { 0 }; + fmt.tymed = TYMED_HGLOBAL; + fmt.dwAspect = DVASPECT_CONTENT; + fmt.lindex = -1; + fmt.cfFormat = CF_TEXT; + // if it is ASCII text, return a copy of it + if ( data->GetData( &fmt, &medium )==S_OK ) + { + void *stuff = GlobalLock( medium.hGlobal ); + Fl::e_length = strlen((char*)stuff); + Fl::e_text = strdup((char*)stuff); + GlobalUnlock( medium.hGlobal ); + ReleaseStgMedium( &medium ); + currDragResult = 1; + return currDragResult; + } + // else fill currDrag* with filenames, if possible + memset(&fmt, 0, sizeof(fmt)); + fmt.tymed = TYMED_HGLOBAL; + fmt.dwAspect = DVASPECT_CONTENT; + fmt.lindex = -1; + fmt.cfFormat = CF_HDROP; + // if it is a pathname list, send an FL_PASTE with a \n seperated list of filepaths + if ( data->GetData( &fmt, &medium )==S_OK ) + { + HDROP hdrop = (HDROP)medium.hGlobal; + int i, n, nn = 0, nf = DragQueryFile( hdrop, (UINT)-1, 0, 0 ); + for ( i=0; i<nf; i++ ) nn += DragQueryFile( hdrop, i, 0, 0 ); + nn += nf; + Fl::e_length = nn-1; + char *dst = Fl::e_text = (char*)malloc(nn+1); + for ( i=0; i<nf; i++ ) { + n = DragQueryFile( hdrop, i, dst, nn ); + dst += n; + if ( i<nf-1 ) *dst++ = '\n'; + } + *dst = 0; + ReleaseStgMedium( &medium ); + currDragResult = 1; + return currDragResult; + } + currDragResult = 0; + return currDragResult; + } +} flDropTarget; + +IDropTarget *flIDropTarget = &flDropTarget; + +IDataObject *FLDropTarget::currDragRef = 0; +char *FLDropTarget::currDragData = 0; +int FLDropTarget::currDragSize = 0; +char FLDropTarget::currDragResult = 0; + +/** + * this class is needed to allow FLTK apps to be a DnD source + */ +class FLDropSource : public IDropSource +{ + DWORD m_cRefCount; +public: + FLDropSource() { m_cRefCount = 0; } + HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, LPVOID *ppvObject ) { + if (IID_IUnknown==riid || IID_IDropSource==riid) + { + *ppvObject=this; + ((LPUNKNOWN)*ppvObject)->AddRef(); + return S_OK; + } + *ppvObject = NULL; + return E_NOINTERFACE; + } + ULONG STDMETHODCALLTYPE AddRef() { return ++m_cRefCount; } + ULONG STDMETHODCALLTYPE Release() { + long nTemp; + nTemp = --m_cRefCount; + if(nTemp==0) + delete this; + return nTemp; + } + STDMETHODIMP GiveFeedback( ulong ) { return DRAGDROP_S_USEDEFAULTCURSORS; } + STDMETHODIMP QueryContinueDrag( BOOL esc, DWORD keyState ) { + if ( esc ) + return DRAGDROP_S_CANCEL; + if ( !(keyState & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON)) ) + return DRAGDROP_S_DROP; + return S_OK; + } +}; + +/** + * this is the actual object that FLTK can drop somewhere + * - the implementation is minimal, but it should work with all decent Win32 drop targets + */ +class FLDataObject : public IDataObject +{ + DWORD m_cRefCount; +public: + FLDataObject() { m_cRefCount = 1; } + HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, LPVOID *ppvObject ) { + if (IID_IUnknown==riid || IID_IDataObject==riid) + { + *ppvObject=this; + ((LPUNKNOWN)*ppvObject)->AddRef(); + return S_OK; + } + *ppvObject = NULL; + return E_NOINTERFACE; + } + ULONG STDMETHODCALLTYPE AddRef() { return ++m_cRefCount; } + ULONG STDMETHODCALLTYPE Release() { + long nTemp; + nTemp = --m_cRefCount; + if(nTemp==0) + delete this; + return nTemp; + } + // GetData currently allows ASCII text through Global Memory only + HRESULT STDMETHODCALLTYPE GetData( FORMATETC *pformatetcIn, STGMEDIUM *pmedium ) { + if ((pformatetcIn->dwAspect & DVASPECT_CONTENT) && + (pformatetcIn->tymed & TYMED_HGLOBAL) && + (pformatetcIn->cfFormat == CF_TEXT)) + { + HGLOBAL gh = GlobalAlloc( GHND, fl_selection_length[0]+1 ); + char *pMem = (char*)GlobalLock( gh ); + memmove( pMem, fl_selection_buffer[0], fl_selection_length[0] ); + pMem[ fl_selection_length[0] ] = 0; + pmedium->tymed = TYMED_HGLOBAL; + pmedium->hGlobal = gh; + pmedium->pUnkForRelease = NULL; + GlobalUnlock( gh ); + return S_OK; + } + return DV_E_FORMATETC; + } + HRESULT STDMETHODCALLTYPE QueryGetData( FORMATETC *pformatetc ) + { + if ((pformatetc->dwAspect & DVASPECT_CONTENT) && + (pformatetc->tymed & TYMED_HGLOBAL) && + (pformatetc->cfFormat == CF_TEXT)) + return S_OK; + return DV_E_FORMATETC; + } + // all the following methods are not really needed for a DnD object + HRESULT STDMETHODCALLTYPE GetDataHere( FORMATETC* /*pformatetcIn*/, STGMEDIUM* /*pmedium*/) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE GetCanonicalFormatEtc( FORMATETC* /*in*/, FORMATETC* /*out*/) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE SetData( FORMATETC* /*pformatetc*/, STGMEDIUM* /*pmedium*/, BOOL /*fRelease*/) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE EnumFormatEtc( DWORD /*dir*/, IEnumFORMATETC** /*ppenumFormatEtc*/) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE DAdvise( FORMATETC* /*pformatetc*/, DWORD /*advf*/, + IAdviseSink* /*pAdvSink*/, DWORD* /*pdwConnection*/) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE DUnadvise( DWORD /*dwConnection*/) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE EnumDAdvise( IEnumSTATDATA** /*ppenumAdvise*/) { return E_NOTIMPL; } +}; + + +/** + * drag and drop whatever is in the cut-copy-paste buffer + * - create a selection first using: + * Fl::copy(const char *stuff, int len, 0) + */ +int Fl::dnd() +{ + DWORD dropEffect; + ReleaseCapture(); + + FLDataObject *fdo = new FLDataObject; + fdo->AddRef(); + FLDropSource *fds = new FLDropSource; + fds->AddRef(); + + HRESULT ret = DoDragDrop( fdo, fds, DROPEFFECT_MOVE|DROPEFFECT_LINK|DROPEFFECT_COPY, &dropEffect ); + + fdo->Release(); + fds->Release(); + + Fl_Widget *w = Fl::pushed(); + if ( w ) + { + int old_event = Fl::e_number; + w->handle(Fl::e_number = FL_RELEASE); + Fl::e_number = old_event; + Fl::pushed( 0 ); + } + if ( ret==DRAGDROP_S_DROP ) return 1; // or DD_S_CANCEL + return 0; +} +#else +int Fl::dnd() +{ + // Always indicate DnD failed when using GCC < 3... + return 1; +} +#endif // !__GNUC__ || __GNUC__ >= 3 + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_dnd_x.cxx b/Utilities/FLTK/src/fl_dnd_x.cxx new file mode 100644 index 0000000000..fa0c43a5f9 --- /dev/null +++ b/Utilities/FLTK/src/fl_dnd_x.cxx @@ -0,0 +1,201 @@ +// +// "$Id$" +// +// Drag & Drop code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2006 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/Fl_Window.H> +#include <FL/x.H> +#include "flstring.h" + + +extern Atom fl_XdndAware; +extern Atom fl_XdndSelection; +extern Atom fl_XdndEnter; +extern Atom fl_XdndTypeList; +extern Atom fl_XdndPosition; +extern Atom fl_XdndLeave; +extern Atom fl_XdndDrop; +extern Atom fl_XdndStatus; +extern Atom fl_XdndActionCopy; +extern Atom fl_XdndFinished; +//extern Atom fl_XdndProxy; +extern Atom fl_XdndURIList; + +extern char fl_i_own_selection[2]; +extern char *fl_selection_buffer[2]; + +extern void fl_sendClientMessage(Window window, Atom message, + unsigned long d0, + unsigned long d1=0, + unsigned long d2=0, + unsigned long d3=0, + unsigned long d4=0); + +// return version # of Xdnd this window supports. Also change the +// window to the proxy if it uses a proxy: +static int dnd_aware(Window& window) { + Atom actual; int format; unsigned long count, remaining; + unsigned char *data = 0; + XGetWindowProperty(fl_display, window, fl_XdndAware, + 0, 4, False, XA_ATOM, + &actual, &format, + &count, &remaining, &data); + if (actual == XA_ATOM && format==32 && count && data) + return int(*(Atom*)data); + return 0; +} + +static int grabfunc(int event) { + if (event == FL_RELEASE) Fl::pushed(0); + return 0; +} + +extern int (*fl_local_grab)(int); // in Fl.cxx + +// send an event to an fltk window belonging to this program: +static int local_handle(int event, Fl_Window* window) { + fl_local_grab = 0; + Fl::e_x = Fl::e_x_root-window->x(); + Fl::e_y = Fl::e_y_root-window->y(); + int ret = Fl::handle(event,window); + fl_local_grab = grabfunc; + return ret; +} + +int Fl::dnd() { + Fl_Window *source_fl_win = Fl::first_window(); + Fl::first_window()->cursor((Fl_Cursor)21); + Window source_window = fl_xid(Fl::first_window()); + fl_local_grab = grabfunc; + Window target_window = 0; + Fl_Window* local_window = 0; + int dndversion = 4; int dest_x, dest_y; + XSetSelectionOwner(fl_display, fl_XdndSelection, fl_message_window, fl_event_time); + + while (Fl::pushed()) { + + // figure out what window we are pointing at: + Window new_window = 0; int new_version = 0; + Fl_Window* new_local_window = 0; + for (Window child = RootWindow(fl_display, fl_screen);;) { + Window root; unsigned int junk3; + XQueryPointer(fl_display, child, &root, &child, + &e_x_root, &e_y_root, &dest_x, &dest_y, &junk3); + if (!child) { + if (!new_window && (new_version = dnd_aware(root))) new_window = root; + break; + } + new_window = child; + if ((new_local_window = fl_find(child))) break; + if ((new_version = dnd_aware(new_window))) break; + } + + if (new_window != target_window) { + if (local_window) { + local_handle(FL_DND_LEAVE, local_window); + } else if (dndversion) { + fl_sendClientMessage(target_window, fl_XdndLeave, source_window); + } + dndversion = new_version; + target_window = new_window; + local_window = new_local_window; + if (local_window) { + local_handle(FL_DND_ENTER, local_window); + } else if (dndversion) { + // Send an X-DND message to the target window. In order to + // support dragging of files/URLs as well as arbitrary text, + // we look at the selection buffer - if the buffer starts + // with a common URI scheme, does not contain spaces, and + // contains at least one CR LF, then we flag the data as + // both a URI list (MIME media type "text/uri-list") and + // plain text. Otherwise, we just say it is plain text. + if ((!strncmp(fl_selection_buffer[0], "file:///", 8) || + !strncmp(fl_selection_buffer[0], "ftp://", 6) || + !strncmp(fl_selection_buffer[0], "http://", 7) || + !strncmp(fl_selection_buffer[0], "https://", 8) || + !strncmp(fl_selection_buffer[0], "ipp://", 6) || + !strncmp(fl_selection_buffer[0], "ldap:", 5) || + !strncmp(fl_selection_buffer[0], "mailto:", 7) || + !strncmp(fl_selection_buffer[0], "news:", 5) || + !strncmp(fl_selection_buffer[0], "smb://", 6)) && + !strchr(fl_selection_buffer[0], ' ') && + strstr(fl_selection_buffer[0], "\r\n")) { + // Send file/URI list... + fl_sendClientMessage(target_window, fl_XdndEnter, source_window, + dndversion<<24, fl_XdndURIList, XA_STRING, 0); + } else { + // Send plain text... + fl_sendClientMessage(target_window, fl_XdndEnter, source_window, + dndversion<<24, XA_STRING, 0, 0); + } + } + } + if (local_window) { + local_handle(FL_DND_DRAG, local_window); + } else if (dndversion) { + fl_sendClientMessage(target_window, fl_XdndPosition, source_window, + 0, (e_x_root<<16)|e_y_root, fl_event_time, + fl_XdndActionCopy); + } + Fl::wait(); + } + + if (local_window) { + fl_i_own_selection[0] = 1; + if (local_handle(FL_DND_RELEASE, local_window)) paste(*belowmouse(), 0); + } else if (dndversion) { + fl_sendClientMessage(target_window, fl_XdndDrop, source_window, + 0, fl_event_time); + } else if (target_window) { + // fake a drop by clicking the middle mouse button: + XButtonEvent msg; + msg.type = ButtonPress; + msg.window = target_window; + msg.root = RootWindow(fl_display, fl_screen); + msg.subwindow = 0; + msg.time = fl_event_time+1; + msg.x = dest_x; + msg.y = dest_y; + msg.x_root = Fl::e_x_root; + msg.y_root = Fl::e_y_root; + msg.state = 0x0; + msg.button = Button2; + XSendEvent(fl_display, target_window, False, 0L, (XEvent*)&msg); + msg.time++; + msg.state = 0x200; + msg.type = ButtonRelease; + XSendEvent(fl_display, target_window, False, 0L, (XEvent*)&msg); + } + + fl_local_grab = 0; + source_fl_win->cursor(FL_CURSOR_DEFAULT); + return 1; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_draw.cxx b/Utilities/FLTK/src/fl_draw.cxx new file mode 100644 index 0000000000..637744c4fd --- /dev/null +++ b/Utilities/FLTK/src/fl_draw.cxx @@ -0,0 +1,332 @@ +// +// "$Id$" +// +// Label drawing code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Implementation of fl_draw(const char*,int,int,int,int,Fl_Align) +// Used to draw all the labels and text, this routine: +// Word wraps the labels to fit into their bounding box. +// Breaks them into lines at the newlines. +// Expands all unprintable characters to ^X or \nnn notation +// Aligns them against the inside of the box. + +#define min(a,b) ((a)<(b)?(a):(b)) +#include <FL/fl_draw.H> +#include <FL/Fl_Image.H> + +#include "flstring.h" +#include <ctype.h> +#include <math.h> + +#define MAXBUF 1024 + +char fl_draw_shortcut; // set by fl_labeltypes.cxx + +static char* underline_at; + +// Copy p to buf, replacing unprintable characters with ^X and \nnn +// Stop at a newline or if MAXBUF characters written to buffer. +// Also word-wrap if width exceeds maxw. +// Returns a pointer to the start of the next line of caharcters. +// Sets n to the number of characters put into the buffer. +// Sets width to the width of the string in the current font. + +static const char* +expand(const char* from, char* buf, double maxw, int& n, double &width, + int wrap, int draw_symbols) { + char* o = buf; + char* e = buf+(MAXBUF-4); + underline_at = 0; + char* word_end = o; + const char* word_start = from; + double w = 0; + + const char* p = from; + for (;; p++) { + + int c = *p & 255; + + if (!c || c == ' ' || c == '\n') { + // test for word-wrap: + if (word_start < p && wrap) { + double newwidth = w + fl_width(word_end, o-word_end); + if (word_end > buf && newwidth > maxw) { // break before this word + o = word_end; + p = word_start; + break; + } + word_end = o; + w = newwidth; + } + if (!c) break; + else if (c == '\n') {p++; break;} + word_start = p+1; + } + + if (o > e) break; // don't overflow buffer + + if (c == '\t') { + for (c = (o-buf)%8; c<8 && o<e; c++) *o++ = ' '; + } else if (c == '&' && fl_draw_shortcut && *(p+1)) { + if (*(p+1) == '&') {p++; *o++ = '&';} + else if (fl_draw_shortcut != 2) underline_at = o; + } else if (c < ' ' || c == 127) { // ^X + *o++ = '^'; + *o++ = c ^ 0x40; + } else if (c == 0xA0) { // non-breaking space + *o++ = ' '; + } else if (c == '@' && draw_symbols) { // Symbol??? + if (p[1] && p[1] != '@') break; + *o++ = c; + if (p[1]) p++; + } else { + *o++ = c; + } + } + + width = w + fl_width(word_end, o-word_end); + *o = 0; + n = o-buf; + return p; +} + +void fl_draw( + const char* str, // the (multi-line) string + int x, int y, int w, int h, // bounding box + Fl_Align align, + void (*callthis)(const char*,int,int,int), + Fl_Image* img, int draw_symbols) { + const char* p; + const char* e; + char buf[MAXBUF]; + int buflen; + char symbol[2][255], *symptr; + int symwidth[2], symoffset, symtotal; + + // count how many lines and put the last one into the buffer: + int lines; + double width; + + symbol[0][0] = '\0'; + symwidth[0] = 0; + + symbol[1][0] = '\0'; + symwidth[1] = 0; + + if (draw_symbols) { + if (str && str[0] == '@' && str[1] && str[1] != '@') { + // Start with a symbol... + for (symptr = symbol[0]; + *str && !isspace(*str) && symptr < (symbol[0] + sizeof(symbol[0]) - 1); + *symptr++ = *str++); + *symptr = '\0'; + if (isspace(*str)) str++; + symwidth[0] = min(w,h); + } + + if (str && (p = strrchr(str, '@')) != NULL && p > (str + 1) && p[-1] != '@') { + strlcpy(symbol[1], p, sizeof(symbol[1])); + symwidth[1] = min(w,h); + } + } + + symtotal = symwidth[0] + symwidth[1]; + + if (str) { + for (p = str, lines=0; p;) { + e = expand(p, buf, w - symtotal, buflen, width, align&FL_ALIGN_WRAP, + draw_symbols); + lines++; + if (!*e || (*e == '@' && e[1] != '@' && draw_symbols)) break; + p = e; + } + } else lines = 0; + + if ((symwidth[0] || symwidth[1]) && lines) { + if (symwidth[0]) symwidth[0] = lines * fl_height(); + if (symwidth[1]) symwidth[1] = lines * fl_height(); + } + + symtotal = symwidth[0] + symwidth[1]; + + // figure out vertical position of the first line: + int xpos; + int ypos; + int height = fl_height(); + int imgh = img ? img->h() : 0; + + symoffset = 0; + + if (align & FL_ALIGN_BOTTOM) ypos = y+h-(lines-1)*height-imgh; + else if (align & FL_ALIGN_TOP) ypos = y+height; + else ypos = y+(h-lines*height-imgh)/2+height; + + // draw the image unless the "text over image" alignment flag is set... + if (img && !(align & FL_ALIGN_TEXT_OVER_IMAGE)) { + if (img->w() > symoffset) symoffset = img->w(); + + if (align & FL_ALIGN_LEFT) xpos = x + symwidth[0]; + else if (align & FL_ALIGN_RIGHT) xpos = x + w - img->w() - symwidth[1]; + else xpos = x + (w - img->w() - symtotal) / 2 + symwidth[0]; + + img->draw(xpos, ypos - height); + ypos += img->h(); + } + + // now draw all the lines: + if (str) { + int desc = fl_descent(); + for (p=str; ; ypos += height) { + if (lines>1) e = expand(p, buf, w - symtotal, buflen, width, + align&FL_ALIGN_WRAP, draw_symbols); + else e = ""; + + if (width > symoffset) symoffset = (int)(width + 0.5); + + if (align & FL_ALIGN_LEFT) xpos = x + symwidth[0]; + else if (align & FL_ALIGN_RIGHT) xpos = x + w - (int)(width + .5) - symwidth[1]; + else xpos = x + (w - (int)(width + .5) - symtotal) / 2 + symwidth[0]; + + callthis(buf,buflen,xpos,ypos-desc); + + if (underline_at && underline_at >= buf && underline_at < (buf + buflen)) + callthis("_",1,xpos+int(fl_width(buf,underline_at-buf)),ypos-desc); + + if (!*e || (*e == '@' && e[1] != '@')) break; + p = e; + } + } + + // draw the image if the "text over image" alignment flag is set... + if (img && (align & FL_ALIGN_TEXT_OVER_IMAGE)) { + if (img->w() > symoffset) symoffset = img->w(); + + if (align & FL_ALIGN_LEFT) xpos = x + symwidth[0]; + else if (align & FL_ALIGN_RIGHT) xpos = x + w - img->w() - symwidth[1]; + else xpos = x + (w - img->w() - symtotal) / 2 + symwidth[0]; + + img->draw(xpos, ypos); + } + + // draw the symbols, if any... + if (symwidth[0]) { + // draw to the left + if (align & FL_ALIGN_LEFT) xpos = x; + else if (align & FL_ALIGN_RIGHT) xpos = x + w - symtotal - symoffset; + else xpos = x + (w - symoffset - symtotal) / 2; + + if (align & FL_ALIGN_BOTTOM) ypos = y + h - symwidth[0]; + else if (align & FL_ALIGN_TOP) ypos = y; + else ypos = y + (h - symwidth[0]) / 2; + + fl_draw_symbol(symbol[0], xpos, ypos, symwidth[0], symwidth[0], fl_color()); + } + + if (symwidth[1]) { + // draw to the right + if (align & FL_ALIGN_LEFT) xpos = x + symoffset + symwidth[0]; + else if (align & FL_ALIGN_RIGHT) xpos = x + w - symwidth[1]; + else xpos = x + (w - symoffset - symtotal) / 2 + symoffset + symwidth[0]; + + if (align & FL_ALIGN_BOTTOM) ypos = y + h - symwidth[1]; + else if (align & FL_ALIGN_TOP) ypos = y; + else ypos = y + (h - symwidth[1]) / 2; + + fl_draw_symbol(symbol[1], xpos, ypos, symwidth[1], symwidth[1], fl_color()); + } +} + +void fl_draw( + const char* str, // the (multi-line) string + int x, int y, int w, int h, // bounding box + Fl_Align align, + Fl_Image* img, + int draw_symbols) { + if ((!str || !*str) && !img) return; + if (w && h && !fl_not_clipped(x, y, w, h) && (align & FL_ALIGN_INSIDE)) return; + if (align & FL_ALIGN_CLIP) fl_clip(x, y, w, h); + fl_draw(str, x, y, w, h, align, fl_draw, img, draw_symbols); + if (align & FL_ALIGN_CLIP) fl_pop_clip(); +} + +void fl_measure(const char* str, int& w, int& h, int draw_symbols) { + if (!str || !*str) {w = 0; h = 0; return;} + h = fl_height(); + const char* p; + const char* e; + char buf[MAXBUF]; + int buflen; + int lines; + double width; + int W = 0; + char symbol[2][255], *symptr; + int symwidth[2], symtotal; + + // count how many lines and put the last one into the buffer: + symbol[0][0] = '\0'; + symwidth[0] = 0; + + symbol[1][0] = '\0'; + symwidth[1] = 0; + + if (str && str[0] == '@' && str[1] && str[1] != '@') { + // Start with a symbol... + for (symptr = symbol[0]; + *str && !isspace(*str) && symptr < (symbol[0] + sizeof(symbol[0]) - 1); + *symptr++ = *str++); + *symptr = '\0'; + if (isspace(*str)) str++; + symwidth[0] = h; + } + + if (str && (p = strrchr(str, '@')) != NULL && p > (str + 1)) { + strlcpy(symbol[1], p, sizeof(symbol[1])); + symwidth[1] = h; + } + + symtotal = symwidth[0] + symwidth[1]; + + for (p = str, lines=0; p;) { + e = expand(p, buf, w - symtotal, buflen, width, w != 0, draw_symbols); + if ((int)ceil(width) > W) W = (int)ceil(width); + lines++; + if (!*e || (*e == '@' && draw_symbols)) break; + p = e; + } + + if ((symwidth[0] || symwidth[1]) && lines) { + if (symwidth[0]) symwidth[0] = lines * fl_height(); + if (symwidth[1]) symwidth[1] = lines * fl_height(); + } + + symtotal = symwidth[0] + symwidth[1]; + + w = W + symtotal; + h = lines*h; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_draw_image.cxx b/Utilities/FLTK/src/fl_draw_image.cxx new file mode 100644 index 0000000000..a5cba970f5 --- /dev/null +++ b/Utilities/FLTK/src/fl_draw_image.cxx @@ -0,0 +1,578 @@ +// +// "$Id$" +// +// Image drawing routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// I hope a simple and portable method of drawing color and monochrome +// images. To keep this simple, only a single storage type is +// supported: 8 bit unsigned data, byte order RGB, and pixels are +// stored packed into rows with the origin at the top-left. It is +// possible to alter the size of pixels with the "delta" argument, to +// add alpha or other information per pixel. It is also possible to +// change the origin and direction of the image data by messing with +// the "delta" and "linedelta", making them negative, though this may +// defeat some of the shortcuts in translating the image for X. + +#include "fltk-config.h" + +#ifdef WIN32 +# include "fl_draw_image_win32.cxx" +#elif defined(__APPLE__) +# include "fl_draw_image_mac.cxx" +#else + +// A list of assumptions made about the X display: + +// bits_per_pixel must be one of 8, 16, 24, 32. + +// scanline_pad must be a power of 2 and greater or equal to 8. + +// PsuedoColor visuals must have 8 bits_per_pixel (although the depth +// may be less than 8). This is the only limitation that affects any +// modern X displays, you can't use 12 or 16 bit colormaps. + +// The mask bits in TrueColor visuals for each color are +// contiguous and have at least one bit of each color. This +// is not checked for. + +// For 24 and 32 bit visuals there must be at least 8 bits of each color. + +//////////////////////////////////////////////////////////////// + +# include <FL/Fl.H> +# include <FL/fl_draw.H> +# include <FL/x.H> +# include "Fl_XColor.H" +# include "flstring.h" + +static XImage xi; // template used to pass info to X +static int bytes_per_pixel; +static int scanline_add; +static int scanline_mask; + +static void (*converter)(const uchar *from, uchar *to, int w, int delta); +static void (*mono_converter)(const uchar *from, uchar *to, int w, int delta); + +static int dir; // direction-alternator +static int ri,gi,bi; // saved error-diffusion value + +# if USE_COLORMAP +//////////////////////////////////////////////////////////////// +// 8-bit converter with error diffusion + +static void color8_converter(const uchar *from, uchar *to, int w, int delta) { + int r=ri, g=gi, b=bi; + int d, td; + if (dir) { + dir = 0; + from = from+(w-1)*delta; + to = to+(w-1); + d = -delta; + td = -1; + } else { + dir = 1; + d = delta; + td = 1; + } + for (; w--; from += d, to += td) { + r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255; + g += from[1]; if (g < 0) g = 0; else if (g>255) g = 255; + b += from[2]; if (b < 0) b = 0; else if (b>255) b = 255; + Fl_Color i = fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256); + Fl_XColor& xmap = fl_xmap[0][i]; + if (!xmap.mapped) {if (!fl_redmask) fl_xpixel(r,g,b); else fl_xpixel(i);} + r -= xmap.r; + g -= xmap.g; + b -= xmap.b; + *to = uchar(xmap.pixel); + } + ri = r; gi = g; bi = b; +} + +static void mono8_converter(const uchar *from, uchar *to, int w, int delta) { + int r=ri, g=gi, b=bi; + int d, td; + if (dir) { + dir = 0; + from = from+(w-1)*delta; + to = to+(w-1); + d = -delta; + td = -1; + } else { + dir = 1; + d = delta; + td = 1; + } + for (; w--; from += d, to += td) { + r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255; + g += from[0]; if (g < 0) g = 0; else if (g>255) g = 255; + b += from[0]; if (b < 0) b = 0; else if (b>255) b = 255; + Fl_Color i = fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256); + Fl_XColor& xmap = fl_xmap[0][i]; + if (!xmap.mapped) {if (!fl_redmask) fl_xpixel(r,g,b); else fl_xpixel(i);} + r -= xmap.r; + g -= xmap.g; + b -= xmap.b; + *to = uchar(xmap.pixel); + } + ri = r; gi = g; bi = b; +} + +# endif + +//////////////////////////////////////////////////////////////// +// 16 bit TrueColor converters with error diffusion +// Cray computers have no 16-bit type, so we use character pointers +// (which may be slow) + +# ifdef U16 +# define OUTTYPE U16 +# define OUTSIZE 1 +# define OUTASSIGN(v) *t = v +# else +# define OUTTYPE uchar +# define OUTSIZE 2 +# define OUTASSIGN(v) int tt=v; t[0] = uchar(tt>>8); t[1] = uchar(tt) +# endif + +static void color16_converter(const uchar *from, uchar *to, int w, int delta) { + OUTTYPE *t = (OUTTYPE *)to; + int d, td; + if (dir) { + dir = 0; + from = from+(w-1)*delta; + t = t+(w-1)*OUTSIZE; + d = -delta; + td = -OUTSIZE; + } else { + dir = 1; + d = delta; + td = OUTSIZE; + } + int r=ri, g=gi, b=bi; + for (; w--; from += d, t += td) { + r = (r&~fl_redmask) +from[0]; if (r>255) r = 255; + g = (g&~fl_greenmask)+from[1]; if (g>255) g = 255; + b = (b&~fl_bluemask) +from[2]; if (b>255) b = 255; + OUTASSIGN(( + ((r&fl_redmask)<<fl_redshift)+ + ((g&fl_greenmask)<<fl_greenshift)+ + ((b&fl_bluemask)<<fl_blueshift) + ) >> fl_extrashift); + } + ri = r; gi = g; bi = b; +} + +static void mono16_converter(const uchar *from,uchar *to,int w, int delta) { + OUTTYPE *t = (OUTTYPE *)to; + int d, td; + if (dir) { + dir = 0; + from = from+(w-1)*delta; + t = t+(w-1)*OUTSIZE; + d = -delta; + td = -OUTSIZE; + } else { + dir = 1; + d = delta; + td = OUTSIZE; + } + uchar mask = fl_redmask & fl_greenmask & fl_bluemask; + int r=ri; + for (; w--; from += d, t += td) { + r = (r&~mask) + *from; if (r > 255) r = 255; + uchar m = r&mask; + OUTASSIGN(( + (m<<fl_redshift)+ + (m<<fl_greenshift)+ + (m<<fl_blueshift) + ) >> fl_extrashift); + } + ri = r; +} + +// special-case the 5r6g5b layout used by XFree86: + +static void c565_converter(const uchar *from, uchar *to, int w, int delta) { + OUTTYPE *t = (OUTTYPE *)to; + int d, td; + if (dir) { + dir = 0; + from = from+(w-1)*delta; + t = t+(w-1)*OUTSIZE; + d = -delta; + td = -OUTSIZE; + } else { + dir = 1; + d = delta; + td = OUTSIZE; + } + int r=ri, g=gi, b=bi; + for (; w--; from += d, t += td) { + r = (r&7)+from[0]; if (r>255) r = 255; + g = (g&3)+from[1]; if (g>255) g = 255; + b = (b&7)+from[2]; if (b>255) b = 255; + OUTASSIGN(((r&0xf8)<<8) + ((g&0xfc)<<3) + (b>>3)); + } + ri = r; gi = g; bi = b; +} + +static void m565_converter(const uchar *from,uchar *to,int w, int delta) { + OUTTYPE *t = (OUTTYPE *)to; + int d, td; + if (dir) { + dir = 0; + from = from+(w-1)*delta; + t = t+(w-1)*OUTSIZE; + d = -delta; + td = -OUTSIZE; + } else { + dir = 1; + d = delta; + td = OUTSIZE; + } + int r=ri; + for (; w--; from += d, t += td) { + r = (r&7) + *from; if (r > 255) r = 255; + OUTASSIGN((r>>3) * 0x841); + } + ri = r; +} + +//////////////////////////////////////////////////////////////// +// 24bit TrueColor converters: + +static void rgb_converter(const uchar *from, uchar *to, int w, int delta) { + int d = delta-3; + for (; w--; from += d) { + *to++ = *from++; + *to++ = *from++; + *to++ = *from++; + } +} + +static void bgr_converter(const uchar *from, uchar *to, int w, int delta) { + for (; w--; from += delta) { + uchar r = from[0]; + uchar g = from[1]; + *to++ = from[2]; + *to++ = g; + *to++ = r; + } +} + +static void rrr_converter(const uchar *from, uchar *to, int w, int delta) { + for (; w--; from += delta) { + *to++ = *from; + *to++ = *from; + *to++ = *from; + } +} + +//////////////////////////////////////////////////////////////// +// 32bit TrueColor converters on a 32 or 64-bit machine: + +# ifdef U64 +# define STORETYPE U64 +# if WORDS_BIGENDIAN +# define INNARDS32(f) \ + U64 *t = (U64*)to; \ + int w1 = (w+1)/2; \ + for (; w1--; from += delta) {U64 i = f; from += delta; *t++ = (i<<32)|(f);} +# else +# define INNARDS32(f) \ + U64 *t = (U64*)to; \ + int w1 = (w+1)/2; \ + for (; w1--; from += delta) {U64 i=f; from+= delta; *t++ = ((U64)(f)<<32)|i;} +# endif +# else +# define STORETYPE U32 +# define INNARDS32(f) \ + U32 *t = (U32*)to; for (; w--; from += delta) *t++ = f +# endif + +static void rgbx_converter(const uchar *from, uchar *to, int w, int delta) { + INNARDS32((unsigned(from[0])<<24)+(from[1]<<16)+(from[2]<<8)); +} + +static void xbgr_converter(const uchar *from, uchar *to, int w, int delta) { + INNARDS32((from[0])+(from[1]<<8)+(from[2]<<16)); +} + +static void xrgb_converter(const uchar *from, uchar *to, int w, int delta) { + INNARDS32((from[0]<<16)+(from[1]<<8)+(from[2])); +} + +static void bgrx_converter(const uchar *from, uchar *to, int w, int delta) { + INNARDS32((from[0]<<8)+(from[1]<<16)+(unsigned(from[2])<<24)); +} + +static void rrrx_converter(const uchar *from, uchar *to, int w, int delta) { + INNARDS32(unsigned(*from) * 0x1010100U); +} + +static void xrrr_converter(const uchar *from, uchar *to, int w, int delta) { + INNARDS32(*from * 0x10101U); +} + +static void +color32_converter(const uchar *from, uchar *to, int w, int delta) { + INNARDS32( + (from[0]<<fl_redshift)+(from[1]<<fl_greenshift)+(from[2]<<fl_blueshift)); +} + +static void +mono32_converter(const uchar *from,uchar *to,int w, int delta) { + INNARDS32( + (*from << fl_redshift)+(*from << fl_greenshift)+(*from << fl_blueshift)); +} + +//////////////////////////////////////////////////////////////// + +static void figure_out_visual() { + + fl_xpixel(FL_BLACK); // setup fl_redmask, etc, in fl_color.cxx + fl_xpixel(FL_WHITE); // also make sure white is allocated + + static XPixmapFormatValues *pfvlist; + static int FL_NUM_pfv; + if (!pfvlist) pfvlist = XListPixmapFormats(fl_display,&FL_NUM_pfv); + XPixmapFormatValues *pfv; + for (pfv = pfvlist; pfv < pfvlist+FL_NUM_pfv; pfv++) + if (pfv->depth == fl_visual->depth) break; + xi.format = ZPixmap; + xi.byte_order = ImageByteOrder(fl_display); +//i.bitmap_unit = 8; +//i.bitmap_bit_order = MSBFirst; +//i.bitmap_pad = 8; + xi.depth = fl_visual->depth; + xi.bits_per_pixel = pfv->bits_per_pixel; + + if (xi.bits_per_pixel & 7) bytes_per_pixel = 0; // produce fatal error + else bytes_per_pixel = xi.bits_per_pixel/8; + + unsigned int n = pfv->scanline_pad/8; + if (pfv->scanline_pad & 7 || (n&(n-1))) + Fl::fatal("Can't do scanline_pad of %d",pfv->scanline_pad); + if (n < sizeof(STORETYPE)) n = sizeof(STORETYPE); + scanline_add = n-1; + scanline_mask = -n; + +# if USE_COLORMAP + if (bytes_per_pixel == 1) { + converter = color8_converter; + mono_converter = mono8_converter; + return; + } + if (!fl_visual->red_mask) + Fl::fatal("Can't do %d bits_per_pixel colormap",xi.bits_per_pixel); +# endif + + // otherwise it is a TrueColor visual: + + int rs = fl_redshift; + int gs = fl_greenshift; + int bs = fl_blueshift; + + switch (bytes_per_pixel) { + + case 2: + // All 16-bit TrueColor visuals are supported on any machine with + // 24 or more bits per integer. +# ifdef U16 + xi.byte_order = WORDS_BIGENDIAN; +# else + xi.byte_order = 1; +# endif + if (rs == 11 && gs == 6 && bs == 0 && fl_extrashift == 3) { + converter = c565_converter; + mono_converter = m565_converter; + } else { + converter = color16_converter; + mono_converter = mono16_converter; + } + break; + + case 3: + if (xi.byte_order) {rs = 16-rs; gs = 16-gs; bs = 16-bs;} + if (rs == 0 && gs == 8 && bs == 16) { + converter = rgb_converter; + mono_converter = rrr_converter; + } else if (rs == 16 && gs == 8 && bs == 0) { + converter = bgr_converter; + mono_converter = rrr_converter; + } else { + Fl::fatal("Can't do arbitrary 24bit color"); + } + break; + + case 4: + if ((xi.byte_order!=0) != WORDS_BIGENDIAN) + {rs = 24-rs; gs = 24-gs; bs = 24-bs;} + if (rs == 0 && gs == 8 && bs == 16) { + converter = xbgr_converter; + mono_converter = xrrr_converter; + } else if (rs == 24 && gs == 16 && bs == 8) { + converter = rgbx_converter; + mono_converter = rrrx_converter; + } else if (rs == 8 && gs == 16 && bs == 24) { + converter = bgrx_converter; + mono_converter = rrrx_converter; + } else if (rs == 16 && gs == 8 && bs == 0) { + converter = xrgb_converter; + mono_converter = xrrr_converter; + } else { + xi.byte_order = WORDS_BIGENDIAN; + converter = color32_converter; + mono_converter = mono32_converter; + } + break; + + default: + Fl::fatal("Can't do %d bits_per_pixel",xi.bits_per_pixel); + } + +} + +# define MAXBUFFER 0x40000 // 256k + +static void innards(const uchar *buf, int X, int Y, int W, int H, + int delta, int linedelta, int mono, + Fl_Draw_Image_Cb cb, void* userdata) +{ + if (!linedelta) linedelta = W*delta; + + int dx, dy, w, h; + fl_clip_box(X,Y,W,H,dx,dy,w,h); + if (w<=0 || h<=0) return; + dx -= X; + dy -= Y; + + if (!bytes_per_pixel) figure_out_visual(); + xi.width = w; + xi.height = h; + + void (*conv)(const uchar *from, uchar *to, int w, int delta) = converter; + if (mono) conv = mono_converter; + + // See if the data is already in the right format. Unfortunately + // some 32-bit x servers (XFree86) care about the unknown 8 bits + // and they must be zero. I can't confirm this for user-supplied + // data, so the 32-bit shortcut is disabled... + // This can set bytes_per_line negative if image is bottom-to-top + // I tested it on Linux, but it may fail on other Xlib implementations: + if (buf && ( +# if 0 // set this to 1 to allow 32-bit shortcut + delta == 4 && +# if WORDS_BIGENDIAN + conv == rgbx_converter +# else + conv == xbgr_converter +# endif + || +# endif + conv == rgb_converter && delta==3 + ) && !(linedelta&scanline_add)) { + xi.data = (char *)(buf+delta*dx+linedelta*dy); + xi.bytes_per_line = linedelta; + + } else { + int linesize = ((w*bytes_per_pixel+scanline_add)&scanline_mask)/sizeof(STORETYPE); + int blocking = h; + static STORETYPE *buffer; // our storage, always word aligned + static long buffer_size; + {int size = linesize*h; + if (size > MAXBUFFER) { + size = MAXBUFFER; + blocking = MAXBUFFER/linesize; + } + if (size > buffer_size) { + delete[] buffer; + buffer_size = size; + buffer = new STORETYPE[size]; + }} + xi.data = (char *)buffer; + xi.bytes_per_line = linesize*sizeof(STORETYPE); + if (buf) { + buf += delta*dx+linedelta*dy; + for (int j=0; j<h; ) { + STORETYPE *to = buffer; + int k; + for (k = 0; j<h && k<blocking; k++, j++) { + conv(buf, (uchar*)to, w, delta); + buf += linedelta; + to += linesize; + } + XPutImage(fl_display,fl_window,fl_gc, &xi, 0, 0, X+dx, Y+dy+j-k, w, k); + } + } else { + STORETYPE* linebuf = new STORETYPE[(W*delta+(sizeof(STORETYPE)-1))/sizeof(STORETYPE)]; + for (int j=0; j<h; ) { + STORETYPE *to = buffer; + int k; + for (k = 0; j<h && k<blocking; k++, j++) { + cb(userdata, dx, dy+j, w, (uchar*)linebuf); + conv((uchar*)linebuf, (uchar*)to, w, delta); + to += linesize; + } + XPutImage(fl_display,fl_window,fl_gc, &xi, 0, 0, X+dx, Y+dy+j-k, w, k); + } + + delete[] linebuf; + } + } +} + +void fl_draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){ + innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0); +} +void fl_draw_image(Fl_Draw_Image_Cb cb, void* data, + int x, int y, int w, int h,int d) { + innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data); +} +void fl_draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){ + innards(buf,x,y,w,h,d,l,1,0,0); +} +void fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data, + int x, int y, int w, int h,int d) { + innards(0,x,y,w,h,d,0,1,cb,data); +} + +void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) { + if (fl_visual->depth > 16) { + fl_color(r,g,b); + fl_rectf(x,y,w,h); + } else { + uchar c[3]; + c[0] = r; c[1] = g; c[2] = b; + innards(c,x,y,w,h,0,0,0,0,0); + } +} + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_draw_image_mac.cxx b/Utilities/FLTK/src/fl_draw_image_mac.cxx new file mode 100644 index 0000000000..d165b87f93 --- /dev/null +++ b/Utilities/FLTK/src/fl_draw_image_mac.cxx @@ -0,0 +1,271 @@ +// +// "$Id$" +// +// MacOS image drawing code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +//////////////////////////////////////////////////////////////// + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#include <FL/fl_draw.H> +#include <FL/x.H> + +#define MAXBUFFER 0x40000 // 256k + +/** + * draw an image based on the input parameters + * + * buf: image source data + * X, Y: position (in buffer?!) + * W, H: size of picture (in pixel?) + * delta: distance from pixel to pixel in buf in bytes + * linedelta: distance from line to line in buf in bytes + * mono: if set, pixel is one byte - if zero, pixel is 3 byte + * cb: callback to copy image data into (RGB?) buffer + * buf: pointer to first byte in image source + * x, y: position in buffer + * w: width (in bytes?) + * dst: destination buffer + * userdata: ? + */ +static void innards(const uchar *buf, int X, int Y, int W, int H, + int delta, int linedelta, int mono, + Fl_Draw_Image_Cb cb, void* userdata) +{ + if (!linedelta) linedelta = W*delta; + +#ifdef __APPLE_QD__ + // theoretically, if the current GPort permits, we could write + // directly into it, avoiding the temporary GWorld. For now I + // will go the safe way... . + char direct = 0; + GWorldPtr gw; + Rect bounds; + bounds.left=0; bounds.right=W; bounds.top=0; bounds.bottom=H; + QDErr err = NewGWorld( &gw, 32, &bounds, 0L, 0L, useTempMem ); + if (err==noErr && gw) { + PixMapHandle pm = GetGWorldPixMap( gw ); + if ( pm ) { + LockPixels( pm ); + if ( *pm ) { + uchar *base = (uchar*)GetPixBaseAddr( pm ); + if ( base ) { + PixMapPtr pmp = *pm; + // make absolutely sure that we can use a direct memory write to + // create the pixmap! + if ( pmp->pixelType == 16 || pmp->pixelSize == 32 || pmp->cmpCount == 3 || pmp->cmpSize == 8 ) { + int rowBytes = pmp->rowBytes & 0x3fff; + if ( cb ) + { + uchar *tmpBuf = new uchar[ W*delta ]; + if ( mono ) delta -= 1; else delta -= 3; + for ( int i=0; i<H; i++ ) + { + uchar *src = tmpBuf; + uchar *dst = base + i*rowBytes; + cb( userdata, 0, i, W, tmpBuf ); + if ( mono ) { + for ( int j=0; j<W; j++ ) + { uchar c = *src++; *dst++ = 0; *dst++ = c; *dst++ = c; *dst++ = c; src += delta; } + } else { + for ( int j=0; j<W; j++ ) + { *dst++ = 0; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; src += delta; } + } + } + delete[] tmpBuf; + } + else + { + if ( mono ) delta -= 1; else delta -= 3; + for ( int i=0; i<H; i++ ) + { + const uchar *src = buf+i*linedelta; + uchar *dst = base + i*rowBytes; + if ( mono ) { + for ( int j=0; j<W; j++ ) + { uchar c = *src++; *dst++ = 0; *dst++ = c; *dst++ = c; *dst++ = c; src += delta; } + } else { + for ( int j=0; j<W; j++ ) + { *dst++ = 0; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; src += delta; } + } + } + } + + fl_copy_offscreen( X, Y, W, H, gw, 0, 0 ); + direct = 1; + } + } + } + + UnlockPixels( pm ); + } + + DisposeGWorld( gw ); + } + + // great. We were able to write the pixels directly into memory, so we can return now. + if ( direct ) + return; + + // following the very save (and very slow) way to write the image into the give port + if ( cb ) + { + uchar *tmpBuf = new uchar[ W*3 ]; + for ( int i=0; i<H; i++ ) + { + uchar *src = tmpBuf; + cb( userdata, 0, i, W, tmpBuf ); + for ( int j=0; j<W; j++ ) + { + if ( mono ) + { fl_color( src[0], src[0], src[0] ); src++; } + else + { fl_color( src[0], src[1], src[2] ); src+=3; } + MoveTo( X+j, Y+i ); + Line( 0, 0 ); + } + } + delete[] tmpBuf; + } + else + { + for ( int i=0; i<H; i++ ) + { + const uchar *src = buf+i*linedelta; + for ( int j=0; j<W; j++ ) + { + if ( mono ) + fl_color( src[0], src[0], src[0] ); + else + fl_color( src[0], src[1], src[2] ); + MoveTo( X+j, Y+i ); + Line( 0, 0 ); + src += delta; + } + } + } +#elif defined(__APPLE_QUARTZ__) + const void *array = buf; + uchar *tmpBuf = 0; + if (cb) { + tmpBuf = new uchar[ H*W*delta ]; + for (int i=0; i<H; i++) { + cb(userdata, 0, i, W, tmpBuf+i*W*delta); + } + array = (void*)tmpBuf; + linedelta = W; + } + // create an image context + CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); + CGDataProviderRef src = CGDataProviderCreateWithData( 0L, array, linedelta*H*delta, 0L); + CGImageRef img = CGImageCreate( W, H, 8, 8*delta, linedelta*delta, + lut, delta&1?kCGImageAlphaNone:kCGImageAlphaNoneSkipLast, + src, 0L, false, kCGRenderingIntentDefault); + // draw the image into the destination context + if (img) { + CGRect rect = { X, Y, W, H }; + Fl_X::q_begin_image(rect, 0, 0, W, H); + CGContextDrawImage(fl_gc, rect, img); + Fl_X::q_end_image(); + // release all allocated resources + CGImageRelease(img); + } + CGColorSpaceRelease(lut); + CGDataProviderRelease(src); + if (cb) { + delete[] tmpBuf; + } + if (img) return; // else fall through to slow mode + // following the very save (and very slow) way to write the image into the give port + CGContextSetShouldAntialias(fl_gc, false); + if ( cb ) + { + uchar *tmpBuf = new uchar[ W*4 ]; + for ( int i=0; i<H; i++ ) + { + uchar *src = tmpBuf; + cb( userdata, 0, i, W, tmpBuf ); + for ( int j=0; j<W; j++ ) + { + if ( mono ) + { fl_color( src[0], src[0], src[0] ); } + else + { fl_color( src[0], src[1], src[2] ); } + CGContextMoveToPoint(fl_gc, X+j, Y+i); + CGContextAddLineToPoint(fl_gc, X+j, Y+i); + CGContextStrokePath(fl_gc); + src+=delta; + } + } + delete[] tmpBuf; + } + else + { + for ( int i=0; i<H; i++ ) + { + const uchar *src = buf+i*linedelta; + for ( int j=0; j<W; j++ ) + { + if ( mono ) + fl_color( src[0], src[0], src[0] ); + else + fl_color( src[0], src[1], src[2] ); + CGContextMoveToPoint(fl_gc, X+j, Y+i); + CGContextAddLineToPoint(fl_gc, X+j, Y+i); + CGContextStrokePath(fl_gc); + src += delta; + } + } + } + CGContextSetShouldAntialias(fl_gc, true); +#else +# error : you must defined __APPLE_QD__ or __APPLE_QUARTZ__ +#endif +} + +void fl_draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){ + innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0); +} +void fl_draw_image(Fl_Draw_Image_Cb cb, void* data, + int x, int y, int w, int h,int d) { + innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data); +} +void fl_draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){ + innards(buf,x,y,w,h,d,l,1,0,0); +} +void fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data, + int x, int y, int w, int h,int d) { + innards(0,x,y,w,h,d,0,1,cb,data); +} + +void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) { + fl_color(r,g,b); + fl_rectf(x,y,w,h); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_draw_image_win32.cxx b/Utilities/FLTK/src/fl_draw_image_win32.cxx new file mode 100644 index 0000000000..5ee8ed0d3c --- /dev/null +++ b/Utilities/FLTK/src/fl_draw_image_win32.cxx @@ -0,0 +1,265 @@ +// +// "$Id$" +// +// WIN32 image drawing code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// I hope a simple and portable method of drawing color and monochrome +// images. To keep this simple, only a single storage type is +// supported: 8 bit unsigned data, byte order RGB, and pixels are +// stored packed into rows with the origin at the top-left. It is +// possible to alter the size of pixels with the "delta" argument, to +// add alpha or other information per pixel. It is also possible to +// change the origin and direction of the image data by messing with +// the "delta" and "linedelta", making them negative, though this may +// defeat some of the shortcuts in translating the image for X. + +// Unbelievably (since it conflicts with how most PC software works) +// Micro$oft picked a bottom-up and BGR storage format for their +// DIB images. I'm pretty certain there is a way around this, but +// I can't find any other than the brute-force method of drawing +// each line as a seperate image. This may also need to be done +// if the delta is any amount other than 1, 3, or 4. + +//////////////////////////////////////////////////////////////// + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#include <FL/fl_draw.H> +#include <FL/x.H> + +#define MAXBUFFER 0x40000 // 256k + +#if USE_COLORMAP + +// error-diffusion dither into the FLTK colormap +static void dither(uchar* to, const uchar* from, int w, int delta) { + static int ri, gi, bi, dir; + int r=ri, g=gi, b=bi; + int d, td; + if (dir) { + dir = 0; + from = from+(w-1)*delta; + to = to+(w-1); + d = -delta; + td = -1; + } else { + dir = 1; + d = delta; + td = 1; + } + for (; w--; from += d, to += td) { + r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255; + int rr = r*FL_NUM_RED/256; + r -= rr*255/(FL_NUM_RED-1); + g += from[1]; if (g < 0) g = 0; else if (g>255) g = 255; + int gg = g*FL_NUM_GREEN/256; + g -= gg*255/(FL_NUM_GREEN-1); + b += from[2]; if (b < 0) b = 0; else if (b>255) b = 255; + int bb = b*FL_NUM_BLUE/256; + b -= bb*255/(FL_NUM_BLUE-1); + *to = uchar(FL_COLOR_CUBE+(bb*FL_NUM_RED+rr)*FL_NUM_GREEN+gg); + } + ri = r; gi = g; bi = b; +} + +// error-diffusion dither into the FLTK colormap +static void monodither(uchar* to, const uchar* from, int w, int delta) { + static int ri,dir; + int r=ri; + int d, td; + if (dir) { + dir = 0; + from = from+(w-1)*delta; + to = to+(w-1); + d = -delta; + td = -1; + } else { + dir = 1; + d = delta; + td = 1; + } + for (; w--; from += d, to += td) { + r += *from; if (r < 0) r = 0; else if (r>255) r = 255; + int rr = r*FL_NUM_GRAY/256; + r -= rr*255/(FL_NUM_GRAY-1); + *to = uchar(FL_GRAY_RAMP+rr); + } + ri = r; +} + +#endif // USE_COLORMAP + +static void innards(const uchar *buf, int X, int Y, int W, int H, + int delta, int linedelta, int mono, + Fl_Draw_Image_Cb cb, void* userdata) +{ +#if USE_COLORMAP + char indexed = (fl_palette != 0); +#endif + + if (!linedelta) linedelta = W*delta; + + int x, y, w, h; + fl_clip_box(X,Y,W,H,x,y,w,h); + if (w<=0 || h<=0) return; + if (buf) buf += (x-X)*delta + (y-Y)*linedelta; + + static U32 bmibuffer[256+12]; + BITMAPINFO &bmi = *((BITMAPINFO*)bmibuffer); + if (!bmi.bmiHeader.biSize) { + bmi.bmiHeader.biSize = sizeof(bmi)-4; // does it use this to determine type? + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biXPelsPerMeter = 0; + bmi.bmiHeader.biYPelsPerMeter = 0; + bmi.bmiHeader.biClrUsed = 0; + bmi.bmiHeader.biClrImportant = 0; + } +#if USE_COLORMAP + if (indexed) { + for (short i=0; i<256; i++) { + *((short*)(bmi.bmiColors)+i) = i; + } + } else +#endif + if (mono) { + for (int i=0; i<256; i++) { + bmi.bmiColors[i].rgbBlue = (uchar)i; + bmi.bmiColors[i].rgbGreen = (uchar)i; + bmi.bmiColors[i].rgbRed = (uchar)i; + bmi.bmiColors[i].rgbReserved = (uchar)i; + } + } + bmi.bmiHeader.biWidth = w; +#if USE_COLORMAP + bmi.bmiHeader.biBitCount = mono|indexed ? 8 : 24; + int pixelsize = mono|indexed ? 1 : 3; +#else + bmi.bmiHeader.biBitCount = mono ? 8 : 24; + int pixelsize = mono ? 1 : 3; +#endif + int linesize = (pixelsize*w+3)&~3; + + static U32* buffer; + int blocking = h; + {int size = linesize*h; + if (size > MAXBUFFER) { + size = MAXBUFFER; + blocking = MAXBUFFER/linesize; + } + static long buffer_size; + if (size > buffer_size) { + delete[] buffer; + buffer_size = size; + buffer = new U32[(size+3)/4]; + }} + bmi.bmiHeader.biHeight = blocking; + static U32* line_buffer; + if (!buf) { + int size = W*delta; + static int line_buf_size; + if (size > line_buf_size) { + delete[] line_buffer; + line_buf_size = size; + line_buffer = new U32[(size+3)/4]; + } + } + for (int j=0; j<h; ) { + int k; + for (k = 0; j<h && k<blocking; k++, j++) { + const uchar* from; + if (!buf) { // run the converter: + cb(userdata, x-X, y-Y+j, w, (uchar*)line_buffer); + from = (uchar*)line_buffer; + } else { + from = buf; + buf += linedelta; + } + uchar *to = (uchar*)buffer+(blocking-k-1)*linesize; +#if USE_COLORMAP + if (indexed) { + if (mono) + monodither(to, from, w, delta); + else + dither(to, from, w, delta); + to += w; + } else +#endif + if (mono) { + for (int i=w; i--; from += delta) *to++ = *from; + } else { + for (int i=w; i--; from += delta, to += 3) { + uchar r = from[0]; + to[0] = from[2]; + to[1] = from[1]; + to[2] = r; + } + } + } + SetDIBitsToDevice(fl_gc, x, y+j-k, w, k, 0, 0, 0, k, + (LPSTR)((uchar*)buffer+(blocking-k)*linesize), + &bmi, +#if USE_COLORMAP + indexed ? DIB_PAL_COLORS : DIB_RGB_COLORS +#else + DIB_RGB_COLORS +#endif + ); + } +} + +void fl_draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){ + innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0); +} +void fl_draw_image(Fl_Draw_Image_Cb cb, void* data, + int x, int y, int w, int h,int d) { + innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data); +} +void fl_draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){ + innards(buf,x,y,w,h,d,l,1,0,0); +} +void fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data, + int x, int y, int w, int h,int d) { + innards(0,x,y,w,h,d,0,1,cb,data); +} + +void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) { +#if USE_COLORMAP + // use the error diffusion dithering code to produce a much nicer block: + if (fl_palette) { + uchar c[3]; + c[0] = r; c[1] = g; c[2] = b; + innards(c,x,y,w,h,0,0,0,0,0); + return; + } +#endif + fl_color(r,g,b); + fl_rectf(x,y,w,h); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_draw_pixmap.cxx b/Utilities/FLTK/src/fl_draw_pixmap.cxx new file mode 100644 index 0000000000..9aebb3554d --- /dev/null +++ b/Utilities/FLTK/src/fl_draw_pixmap.cxx @@ -0,0 +1,343 @@ +// +// "$Id$" +// +// Pixmap drawing code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Implemented without using the xpm library (which I can't use because +// it interferes with the color cube used by fl_draw_image). +// Current implementation is cheap and slow, and works best on a full-color +// display. Transparency is not handled, and colors are dithered to +// the color cube. Color index is achieved by adding the id +// characters together! Also mallocs a lot of temporary memory! +// Notice that there is no pixmap file interface. This is on purpose, +// as I want to discourage programs that require support files to work. +// All data needed by a program ui should be compiled in!!! + +#include "fltk-config.h" + +#include <FL/Fl.H> +#include <FL/fl_draw.H> +#include <FL/x.H> +#include <stdio.h> +#include "flstring.h" + +static int ncolors, chars_per_pixel; + +int fl_measure_pixmap(/*const*/ char* const* data, int &w, int &h) { + return fl_measure_pixmap((const char*const*)data,w,h); +} + +int fl_measure_pixmap(const char * const *data, int &w, int &h) { + int i = sscanf(data[0],"%d%d%d%d",&w,&h,&ncolors,&chars_per_pixel); + if (i<4 || w<=0 || h<=0 || + chars_per_pixel!=1 && chars_per_pixel!=2) return w=0; + return 1; +} + +#ifdef U64 + +// The callback from fl_draw_image to get a row of data passes this: +struct pixmap_data { + int w, h; + const uchar*const* data; + union { + U64 colors[256]; + U64* byte1[256]; + }; +}; + +// callback for 1 byte per pixel: +static void cb1(void*v, int x, int y, int w, uchar* buf) { + pixmap_data& d = *(pixmap_data*)v; + const uchar* p = d.data[y]+x; + U64* q = (U64*)buf; + for (int X=w; X>0; X-=2, p += 2) { + if (X>1) { +# if WORDS_BIGENDIAN + *q++ = (d.colors[p[0]]<<32) | d.colors[p[1]]; +# else + *q++ = (d.colors[p[1]]<<32) | d.colors[p[0]]; +# endif + } else { +# if WORDS_BIGENDIAN + *q++ = d.colors[p[0]]<<32; +# else + *q++ = d.colors[p[0]]; +# endif + } + } +} + +// callback for 2 bytes per pixel: +static void cb2(void*v, int x, int y, int w, uchar* buf) { + pixmap_data& d = *(pixmap_data*)v; + const uchar* p = d.data[y]+2*x; + U64* q = (U64*)buf; + for (int X=w; X>0; X-=2) { + U64* colors = d.byte1[*p++]; + int index = *p++; + if (X>1) { + U64* colors1 = d.byte1[*p++]; + int index1 = *p++; +# if WORDS_BIGENDIAN + *q++ = (colors[index]<<32) | colors1[index1]; +# else + *q++ = (colors1[index1]<<32) | colors[index]; +# endif + } else { +# if WORDS_BIGENDIAN + *q++ = colors[index]<<32; +# else + *q++ = colors[index]; +# endif + } + } +} + +#else // U32 + +// The callback from fl_draw_image to get a row of data passes this: +struct pixmap_data { + int w, h; + const uchar*const* data; + union { + U32 colors[256]; + U32* byte1[256]; + }; +}; + +# ifndef __APPLE_QUARTZ__ + +// callback for 1 byte per pixel: +static void cb1(void*v, int x, int y, int w, uchar* buf) { + pixmap_data& d = *(pixmap_data*)v; + const uchar* p = d.data[y]+x; + U32* q = (U32*)buf; + for (int X=w; X--;) *q++ = d.colors[*p++]; +} + +// callback for 2 bytes per pixel: +static void cb2(void*v, int x, int y, int w, uchar* buf) { + pixmap_data& d = *(pixmap_data*)v; + const uchar* p = d.data[y]+2*x; + U32* q = (U32*)buf; + for (int X=w; X--;) { + U32* colors = d.byte1[*p++]; + *q++ = colors[*p++]; + } +} + +# endif // !__APPLE_QUARTZ__ + +#endif // U64 else U32 + +uchar **fl_mask_bitmap; // if non-zero, create bitmap and store pointer here + +int fl_draw_pixmap(/*const*/ char* const* data, int x,int y,Fl_Color bg) { + return fl_draw_pixmap((const char*const*)data,x,y,bg); +} + +int fl_draw_pixmap(const char*const* di, int x, int y, Fl_Color bg) { + pixmap_data d; + if (!fl_measure_pixmap(di, d.w, d.h)) return 0; + const uchar*const* data = (const uchar*const*)(di+1); + int transparent_index = -1; + + if (ncolors < 0) { // FLTK (non standard) compressed colormap + ncolors = -ncolors; + const uchar *p = *data++; + // if first color is ' ' it is transparent (put it later to make + // it not be transparent): + if (*p == ' ') { + uchar* c = (uchar*)&d.colors[(int)' ']; +#ifdef U64 + *(U64*)c = 0; +# if WORDS_BIGENDIAN + c += 4; +# endif +#endif + transparent_index = ' '; + Fl::get_color(bg, c[0], c[1], c[2]); c[3] = 0; + p += 4; + ncolors--; + } + // read all the rest of the colors: + for (int i=0; i < ncolors; i++) { + uchar* c = (uchar*)&d.colors[*p++]; +#ifdef U64 + *(U64*)c = 0; +# if WORDS_BIGENDIAN + c += 4; +# endif +#endif + *c++ = *p++; + *c++ = *p++; + *c++ = *p++; +#ifdef __APPLE_QUARTZ__ + *c = 255; +#else + *c = 0; +#endif + } + } else { // normal XPM colormap with names + if (chars_per_pixel>1) memset(d.byte1, 0, sizeof(d.byte1)); + for (int i=0; i<ncolors; i++) { + const uchar *p = *data++; + // the first 1 or 2 characters are the color index: + int ind = *p++; + uchar* c; + if (chars_per_pixel>1) { +#ifdef U64 + U64* colors = d.byte1[ind]; + if (!colors) colors = d.byte1[ind] = new U64[256]; +#else + U32* colors = d.byte1[ind]; + if (!colors) colors = d.byte1[ind] = new U32[256]; +#endif + c = (uchar*)&colors[*p]; + ind = (ind<<8)|*p++; + } else { + c = (uchar *)&d.colors[ind]; + } + // look for "c word", or last word if none: + const uchar *previous_word = p; + for (;;) { + while (*p && isspace(*p)) p++; + uchar what = *p++; + while (*p && !isspace(*p)) p++; + while (*p && isspace(*p)) p++; + if (!*p) {p = previous_word; break;} + if (what == 'c') break; + previous_word = p; + while (*p && !isspace(*p)) p++; + } +#ifdef U64 + *(U64*)c = 0; +# if WORDS_BIGENDIAN + c += 4; +# endif +#endif +#ifdef __APPLE_QUARTZ__ + c[3] = 255; +#endif + if (!fl_parse_color((const char*)p, c[0], c[1], c[2])) { + // assume "None" or "#transparent" for any errors + // "bg" should be transparent... + Fl::get_color(bg, c[0], c[1], c[2]); +#ifdef __APPLE_QUARTZ__ + c[3] = 0; +#endif + transparent_index = ind; + } + } + } + d.data = data; + +#ifndef __APPLE_QUARTZ__ + + // build the mask bitmap used by Fl_Pixmap: + if (fl_mask_bitmap && transparent_index >= 0) { + int W = (d.w+7)/8; + uchar* bitmap = new uchar[W * d.h]; + *fl_mask_bitmap = bitmap; + for (int Y = 0; Y < d.h; Y++) { + const uchar* p = data[Y]; + if (chars_per_pixel <= 1) { + int dw = d.w; + for (int X = 0; X < W; X++) { + uchar b = (dw-->0 && *p++ != transparent_index); + if (dw-->0 && *p++ != transparent_index) b |= 2; + if (dw-->0 && *p++ != transparent_index) b |= 4; + if (dw-->0 && *p++ != transparent_index) b |= 8; + if (dw-->0 && *p++ != transparent_index) b |= 16; + if (dw-->0 && *p++ != transparent_index) b |= 32; + if (dw-->0 && *p++ != transparent_index) b |= 64; + if (dw-->0 && *p++ != transparent_index) b |= 128; + *bitmap++ = b; + } + } else { + uchar b = 0, bit = 1; + for (int X = 0; X < d.w; X++) { + int ind = *p++; + ind = (ind<<8) | (*p++); + if (ind != transparent_index) b |= bit; + + if (bit < 128) bit <<= 1; + else { + *bitmap++ = b; + b = 0; + bit = 1; + } + } + + if (bit > 1) *bitmap++ = b; + } + } + } + + fl_draw_image(chars_per_pixel==1 ? cb1 : cb2, &d, x, y, d.w, d.h, 4); + +#else // __APPLE_QUARTZ__ + + bool transparent = (transparent_index>=0); + transparent = true; + U32 *array = new U32[d.w * d.h], *q = array; + for (int Y = 0; Y < d.h; Y++) { + const uchar* p = data[Y]; + if (chars_per_pixel <= 1) { + for (int X = 0; X < d.w; X++) { + *q++ = d.colors[*p++]; + } + } else { + for (int X = 0; X < d.w; X++) { + U32* colors = d.byte1[*p++]; + *q++ = colors[*p++]; + } + } + } + CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); + CGDataProviderRef src = CGDataProviderCreateWithData( 0L, array, d.w * d.h * 4, 0L); + CGImageRef img = CGImageCreate(d.w, d.h, 8, 4*8, 4*d.w, + lut, transparent?kCGImageAlphaLast:kCGImageAlphaNoneSkipLast, + src, 0L, false, kCGRenderingIntentDefault); + CGColorSpaceRelease(lut); + CGDataProviderRelease(src); + CGRect rect = { x, y, d.w, d.h }; + Fl_X::q_begin_image(rect, x, y, d.w, d.h); + CGContextDrawImage(fl_gc, rect, img); + Fl_X::q_end_image(); + CGContextFlush(fl_gc); + CGImageRelease(img); + delete array; + +#endif // !__APPLE_QUARTZ__ + + if (chars_per_pixel > 1) for (int i = 0; i < 256; i++) delete[] d.byte1[i]; + return 1; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_engraved_label.cxx b/Utilities/FLTK/src/fl_engraved_label.cxx new file mode 100644 index 0000000000..7ec602efca --- /dev/null +++ b/Utilities/FLTK/src/fl_engraved_label.cxx @@ -0,0 +1,93 @@ +// +// "$Id$" +// +// Engraved label drawing routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Drawing code for XForms style engraved & embossed labels + +#include <FL/Fl.H> +#include <FL/Fl_Widget.H> +#include <FL/fl_draw.H> + +// data[] is dx, dy, color triples + +static void innards( + const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align, + int data[][3], int n) +{ + Fl_Align a1 = align; + if (a1 & FL_ALIGN_CLIP) { + fl_clip(X, Y, W, H); a1 = (Fl_Align)(a1&~FL_ALIGN_CLIP);} + fl_font((Fl_Font)o->font, o->size); + for (int i = 0; i < n; i++) { + fl_color((Fl_Color)(i < n-1 ? data[i][2] : o->color)); + fl_draw(o->value, X+data[i][0], Y+data[i][1], W, H, a1); + } + if (align & FL_ALIGN_CLIP) fl_pop_clip(); +} + +static void fl_shadow_label( + const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align) +{ + static int data[2][3] = {{2,2,FL_DARK3},{0,0,0}}; + innards(o, X, Y, W, H, align, data, 2); +} + +static void fl_engraved_label( + const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align) +{ + static int data[7][3] = { + {1,0,FL_LIGHT3},{1,1,FL_LIGHT3},{0,1,FL_LIGHT3}, + {-1,0,FL_DARK3},{-1,-1,FL_DARK3},{0,-1,FL_DARK3}, + {0,0,0}}; + innards(o, X, Y, W, H, align, data, 7); +} + +static void fl_embossed_label( + const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align) +{ + static int data[7][3] = { + {-1,0,FL_LIGHT3},{-1,-1,FL_LIGHT3},{0,-1,FL_LIGHT3}, + {1,0,FL_DARK3},{1,1,FL_DARK3},{0,1,FL_DARK3}, + {0,0,0}}; + innards(o, X, Y, W, H, align, data, 7); +} + +Fl_Labeltype fl_define_FL_SHADOW_LABEL() { + Fl::set_labeltype(_FL_SHADOW_LABEL, fl_shadow_label, 0); + return _FL_SHADOW_LABEL; +} +Fl_Labeltype fl_define_FL_ENGRAVED_LABEL() { + Fl::set_labeltype(_FL_ENGRAVED_LABEL, fl_engraved_label, 0); + return _FL_ENGRAVED_LABEL; +} +Fl_Labeltype fl_define_FL_EMBOSSED_LABEL() { + Fl::set_labeltype(_FL_EMBOSSED_LABEL, fl_embossed_label, 0); + return _FL_EMBOSSED_LABEL; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_file_dir.cxx b/Utilities/FLTK/src/fl_file_dir.cxx new file mode 100644 index 0000000000..b03759d5b4 --- /dev/null +++ b/Utilities/FLTK/src/fl_file_dir.cxx @@ -0,0 +1,160 @@ +// +// "$Id$" +// +// File chooser widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include "flstring.h" +#include <FL/filename.H> +#include <FL/Fl_File_Chooser.H> +#include <FL/fl_ask.H> + + +static Fl_File_Chooser *fc = (Fl_File_Chooser *)0; +static void (*current_callback)(const char*) = 0; +static const char *current_label = fl_ok; + + +// Do a file chooser callback... +static void callback(Fl_File_Chooser *, void*) { + if (current_callback && fc->value()) + (*current_callback)(fc->value()); +} + + +// Set the file chooser callback +void fl_file_chooser_callback(void (*cb)(const char*)) { + current_callback = cb; +} + + +// Set the "OK" button label +void fl_file_chooser_ok_label(const char *l) { + if (l) current_label = l; + else current_label = fl_ok; +} + + +// +// 'fl_file_chooser()' - Show a file chooser dialog and get a filename. +// + +char * // O - Filename or NULL +fl_file_chooser(const char *message, // I - Message in titlebar + const char *pat, // I - Filename pattern + const char *fname, // I - Initial filename selection + int relative) { // I - 0 for absolute path + static char retname[1024]; // Returned filename + + if (!fc) { + if (!fname || !*fname) fname = "."; + + fc = new Fl_File_Chooser(fname, pat, Fl_File_Chooser::CREATE, message); + fc->callback(callback, 0); + } else { + fc->type(Fl_File_Chooser::CREATE); + fc->filter(pat); + fc->label(message); + + if (!fname || !*fname) { + if (fc->filter() != pat && (!pat || !fc->filter() || + strcmp(pat, fc->filter())) && fc->value()) { + // if pattern is different, remove name but leave old directory: + strlcpy(retname, fc->value(), sizeof(retname)); + + char *p = strrchr(retname, '/'); + + if (p) { + // If the filename is "/foo", then the directory will be "/", not + // ""... + if (p == retname) + retname[1] = '\0'; + else + *p = '\0'; + } + + // Set the directory... + fc->directory(retname); + } + } + else + fc->value(fname); + } + + fc->ok_label(current_label); + fc->show(); + + while (fc->shown()) + Fl::wait(); + + if (fc->value() && relative) { + fl_filename_relative(retname, sizeof(retname), fc->value()); + + return retname; + } else if (fc->value()) return (char *)fc->value(); + else return 0; +} + + +// +// 'fl_dir_chooser()' - Show a file chooser dialog and get a directory. +// + +char * // O - Directory or NULL +fl_dir_chooser(const char *message, // I - Message for titlebar + const char *fname, // I - Initial directory name + int relative) // I - 0 for absolute +{ + static char retname[1024]; // Returned directory name + + if (!fc) { + if (!fname || !*fname) fname = "."; + + fc = new Fl_File_Chooser(fname, "*", Fl_File_Chooser::CREATE | + Fl_File_Chooser::DIRECTORY, message); + fc->callback(callback, 0); + } else { + fc->type(Fl_File_Chooser::CREATE | Fl_File_Chooser::DIRECTORY); + fc->filter("*"); + if (fname && *fname) fc->value(fname); + fc->label(message); + } + + fc->show(); + + while (fc->shown()) + Fl::wait(); + + if (fc->value() && relative) { + fl_filename_relative(retname, sizeof(retname), fc->value()); + + return retname; + } else if (fc->value()) return (char *)fc->value(); + else return 0; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_font.cxx b/Utilities/FLTK/src/fl_font.cxx new file mode 100644 index 0000000000..7dd3576fec --- /dev/null +++ b/Utilities/FLTK/src/fl_font.cxx @@ -0,0 +1,60 @@ +// +// "$Id$" +// +// Font selection code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Select fonts from the FLTK font table. +#include "flstring.h" +#include <FL/Fl.H> +#include <FL/fl_draw.H> +#include <FL/x.H> +#include "Fl_Font.H" + +#include <stdio.h> +#include <stdlib.h> + +#ifdef WIN32 +# include "fl_font_win32.cxx" +#elif defined(__APPLE__) +# include "fl_font_mac.cxx" +#elif USE_XFT +# include "fl_font_xft.cxx" +#else +# include "fl_font_x.cxx" +#endif // WIN32 + + +double fl_width(const char* c) { + if (c) return fl_width(c, strlen(c)); + else return 0.0f; +} + +void fl_draw(const char* str, int x, int y) { + fl_draw(str, strlen(str), x, y); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_font_mac.cxx b/Utilities/FLTK/src/fl_font_mac.cxx new file mode 100644 index 0000000000..4dd71f560e --- /dev/null +++ b/Utilities/FLTK/src/fl_font_mac.cxx @@ -0,0 +1,307 @@ +// +// "$Id$" +// +// MacOS font selection routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +//: MeasureText, FontMetrics, WidthTabHandle, GetSysFont, SysFontSize +//: TextSize, TextFont +//: GetFNum (theName: Str255; VAR familyID: Integer); +//: FUNCTION FMSwapFont (inRec: FMInput): FMOutPtr; +//: SetFractEnable + +Fl_FontSize::Fl_FontSize(const char* name, int Size) { + next = 0; +# if HAVE_GL + listbase = 0; +# endif +#ifdef __APPLE_QD__ + knowMetrics = 0; + switch (*name++) { + case 'I': face = italic; break; + case 'P': face = italic | bold; break; + case 'B': face = bold; break; + default: face = 0; break; + } + unsigned char fn[80]; + fn[0] = strlen(name); strcpy((char*)(fn+1), name); + GetFNum(fn, &font); + size = Size; + FMInput fIn = { font, size, face, 0, 0, { 1, 1}, { 1, 1} }; + FMOutput *fOut = FMSwapFont(&fIn); + ascent = fOut->ascent; //: the following three lines give only temporary aproimations + descent = fOut->descent; + for (int i=0; i<256; i++) width[i] = fOut->widMax; + minsize = maxsize = size; +#elif defined(__APPLE_QUARTZ__) + q_name = strdup(name); + size = Size; + ascent = Size*3/4; + descent = Size-ascent; + q_width = Size*2/3; + minsize = maxsize = Size; + // Using ATS to get the genral Glyph size information + CFStringRef cfname = CFStringCreateWithCString(0L, q_name, kCFStringEncodingASCII); + ATSFontRef font = ATSFontFindFromName(cfname, kATSOptionFlagsDefault); + if (font) { + ATSFontMetrics m = { 0 }; + ATSFontGetHorizontalMetrics(font, kATSOptionFlagsDefault, &m); + if (m.avgAdvanceWidth) q_width = int(m.avgAdvanceWidth*size); + // playing with the offsets a little to make standard sizes fit + if (m.ascent) ascent = int(m.ascent*size-0.5f); + if (m.descent) descent = -int(m.descent*size-1.5f); + } + CFRelease(cfname); +#endif +} + +Fl_FontSize* fl_fontsize = 0L; + +Fl_FontSize::~Fl_FontSize() { +/* +#if HAVE_GL + // ++ todo: remove OpenGL font alocations +// Delete list created by gl_draw(). This is not done by this code +// as it will link in GL unnecessarily. There should be some kind +// of "free" routine pointer, or a subclass? +// if (listbase) { +// int base = font->min_char_or_byte2; +// int size = font->max_char_or_byte2-base+1; +// int base = 0; int size = 256; +// glDeleteLists(listbase+base,size); +// } +#endif + */ + if (this == fl_fontsize) fl_fontsize = 0; +#ifdef __APPLE_QUARTZ__ + free(q_name); +#endif +} + +//////////////////////////////////////////////////////////////// + +static Fl_Fontdesc built_in_table[] = { +#ifdef __APPLE_QD__ +{" Arial"}, +{"BArial"}, +{"IArial"}, +{"PArial"}, +{" Courier New"}, +{"BCourier New"}, +{"ICourier New"}, +{"PCourier New"}, +{" Times New Roman"}, +{"BTimes New Roman"}, +{"ITimes New Roman"}, +{"PTimes New Roman"}, +{" Symbol"}, +{" Chicago"}, +{"BChicago"}, +{" Webdings"}, +#elif defined(__APPLE_QUARTZ__) +{"Arial"}, +{"Arial Bold"}, +{"Arial Italic"}, +{"Arial Bold Italic"}, +{"Courier New"}, +{"Courier New Bold"}, +{"Courier New Italic"}, +{"Courier New Bold Italic"}, +{"Times New Roman"}, +{"Times New Roman Bold"}, +{"Times New Roman Italic"}, +{"Times New Roman Bold Italic"}, +{"Symbol"}, +{"Monaco"}, +{"Andale Mono"}, // there is no bold Monaco font on standard Mac +{"Webdings"}, +#endif +}; + +Fl_Fontdesc* fl_fonts = built_in_table; + +void fl_font(Fl_FontSize* s) { + fl_fontsize = s; +#ifdef __APPLE_QD__ + if (fl_window) SetPort( GetWindowPort(fl_window) ); + TextFont(fl_fontsize->font); //: select font into current QuickDraw GC + TextFace(fl_fontsize->face); + TextSize(fl_fontsize->size); + if (!fl_fontsize->knowMetrics) { //: get the true metrics for the currnet GC + //: (fails on multiple monitors with different dpi's!) + FontInfo fi; GetFontInfo(&fi); + fl_fontsize->ascent = fi.ascent; + fl_fontsize->descent = fi.descent; + FMetricRec mr; FontMetrics(&mr); + short *f = (short*)*mr.wTabHandle; //: get the char size table + for (int i=0; i<256; i++) fl_fontsize->width[i] = f[2*i]; + fl_fontsize->knowMetrics = 1; + } +#elif defined(__APPLE_QUARTZ__) + if (!s) return; + if (!fl_gc) return; // no worries, we will assign the font to the context later + CGContextSelectFont(fl_gc, s->q_name, (float)s->size, kCGEncodingMacRoman); +#else +# error : need to defined either Quartz or Quickdraw +#endif +} + +static Fl_FontSize* find(int fnum, int size) { + Fl_Fontdesc* s = fl_fonts+fnum; + if (!s->name) s = fl_fonts; // use 0 if fnum undefined + Fl_FontSize* f; + for (f = s->first; f; f = f->next) + if (f->minsize <= size && f->maxsize >= size) return f; + f = new Fl_FontSize(s->name, size); + f->next = s->first; + s->first = f; + return f; +} + +//////////////////////////////////////////////////////////////// +// Public interface: + +int fl_font_ = 0; +int fl_size_ = 0; + +void fl_font(int fnum, int size) { + fl_font_ = fnum; + fl_size_ = size; + fl_font(find(fnum, size)); +} + +int fl_height() { + if (fl_fontsize) return fl_fontsize->ascent+fl_fontsize->descent; + else return -1; +} + +int fl_descent() { + if (fl_fontsize) return fl_fontsize->descent; + else return -1; +} + +// MRS: The default character set is MacRoman, which is different from +// ISO-8859-1; in FLTK 2.0 we'll use UTF-8 with Quartz... + +static uchar macroman_lut[256] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 202, 193, 162, 163, 164, 180, 166, 164, 172, 169, 187, 199, 194, 173, 168, 248, + 161, 177, 178, 179, 171, 181, 166, 225, 252, 185, 188, 200, 188, 189, 190, 192, + 203, 231, 229, 204, 128, 129, 174, 130, 233, 131, 230, 232, 237, 234, 235, 236, + 208, 132, 241, 238, 239, 205, 133, 215, 175, 244, 242, 243, 134, 221, 222, 167, + 136, 135, 137, 139, 138, 140, 190, 141, 143, 142, 144, 145, 147, 146, 148, 149, + 240, 150, 152, 151, 153, 155, 154, 214, 191, 157, 156, 158, 159, 253, 254, 216 +}; + +static char *iso_buf = 0; +static int n_iso_buf = 0; + +// this function must be available for OpenGL character drawing as well +const char *fl_iso2macRoman(const char *s, int n) { + // do not do a text lookup for 'Symbol' or 'WebDings'. This fails + // if the user assigns a new font to these numbers though. + if (fl_font_ == 12 || fl_font_ == 15) + return s; + if (n>n_iso_buf) { + if (iso_buf) free(iso_buf); + iso_buf = (char*)malloc(n+500); + n_iso_buf = n; + } + uchar *src = (uchar*)s; + uchar *dst = (uchar*)iso_buf; + for (;n--;) { + *dst++ = macroman_lut[*src++]; + } + return iso_buf; +} + +double fl_width(const char* c, int n) { + const char *txt = fl_iso2macRoman(c, n); +#ifdef __APPLE_QD__ + return (double)TextWidth( txt, 0, n ); +#else + if (!fl_gc) { + Fl_Window *w = Fl::first_window(); + if (w) w->make_current(); + if (!fl_gc) return -1; + } + // according to the Apple developer docs, this is the correct way to + // find the length of a rendered text... + CGContextSetTextPosition(fl_gc, 0, 0); + CGContextSetTextDrawingMode(fl_gc, kCGTextInvisible); + CGContextShowText(fl_gc, txt, n); + CGContextSetTextDrawingMode(fl_gc, kCGTextFill); + CGPoint p = CGContextGetTextPosition(fl_gc); + return p.x; +#endif +} + +double fl_width(uchar c) { +#ifdef __APPLE_QD__ + return (double)TextWidth((const char*)(macroman_lut + c), 0, 1 ); +#else + return fl_width((const char*)(&c), 1); +#endif +} + +void fl_draw(const char *str, int n, float x, float y); + +void fl_draw(const char* str, int n, int x, int y) { +#ifdef __APPLE_QD__ + const char *txt = fl_iso2macRoman(str, n); + MoveTo(x, y); + DrawText((const char *)txt, 0, n); +#elif defined(__APPLE_QUARTZ__) + fl_draw(str, n, (float)x, (float)y); +#else +# error : neither Quartz no Quickdraw chosen +#endif +} + +void fl_draw(const char *str, int n, float x, float y) { +#ifdef __APPLE_QD__ + fl_draw(str, n, (int)x, (int)y); +#elif defined(__APPLE_QUARTZ__) + const char *txt = fl_iso2macRoman(str, n); + CGContextShowTextAtPoint(fl_gc, x, y, txt, n); +#else +# error : neither Quartz no Quickdraw chosen +#endif +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_font_win32.cxx b/Utilities/FLTK/src/fl_font_win32.cxx new file mode 100644 index 0000000000..13b361e830 --- /dev/null +++ b/Utilities/FLTK/src/fl_font_win32.cxx @@ -0,0 +1,169 @@ +// +// "$Id$" +// +// WIN32 font selection routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +Fl_FontSize::Fl_FontSize(const char* name, int size) { + int weight = FW_NORMAL; + int italic = 0; + switch (*name++) { + case 'I': italic = 1; break; + case 'P': italic = 1; + case 'B': weight = FW_BOLD; break; + case ' ': break; + default: name--; + } + fid = CreateFont( + -size, // negative makes it use "char size" + 0, // logical average character width + 0, // angle of escapement + 0, // base-line orientation angle + weight, + italic, + FALSE, // underline attribute flag + FALSE, // strikeout attribute flag + DEFAULT_CHARSET, // character set identifier + OUT_DEFAULT_PRECIS, // output precision + CLIP_DEFAULT_PRECIS,// clipping precision + DEFAULT_QUALITY, // output quality + DEFAULT_PITCH, // pitch and family + name // pointer to typeface name string + ); + if (!fl_gc) fl_GetDC(0); + SelectObject(fl_gc, fid); + GetTextMetrics(fl_gc, &metr); +// BOOL ret = GetCharWidthFloat(fl_gc, metr.tmFirstChar, metr.tmLastChar, font->width+metr.tmFirstChar); +// ...would be the right call, but is not implemented into Window95! (WinNT?) + GetCharWidth(fl_gc, 0, 255, width); +#if HAVE_GL + listbase = 0; +#endif + minsize = maxsize = size; +} + +Fl_FontSize* fl_fontsize; + +Fl_FontSize::~Fl_FontSize() { +#if HAVE_GL +// Delete list created by gl_draw(). This is not done by this code +// as it will link in GL unnecessarily. There should be some kind +// of "free" routine pointer, or a subclass? +// if (listbase) { +// int base = font->min_char_or_byte2; +// int size = font->max_char_or_byte2-base+1; +// int base = 0; int size = 256; +// glDeleteLists(listbase+base,size); +// } +#endif + if (this == fl_fontsize) fl_fontsize = 0; + DeleteObject(fid); +} + +//////////////////////////////////////////////////////////////// + +// WARNING: if you add to this table, you must redefine FL_FREE_FONT +// in Enumerations.H & recompile!! +static Fl_Fontdesc built_in_table[] = { +{" Arial"}, +{"BArial"}, +{"IArial"}, +{"PArial"}, +{" Courier New"}, +{"BCourier New"}, +{"ICourier New"}, +{"PCourier New"}, +{" Times New Roman"}, +{"BTimes New Roman"}, +{"ITimes New Roman"}, +{"PTimes New Roman"}, +{" Symbol"}, +{" Terminal"}, +{"BTerminal"}, +{" Wingdings"}, +}; + +Fl_Fontdesc* fl_fonts = built_in_table; + +static Fl_FontSize* find(int fnum, int size) { + Fl_Fontdesc* s = fl_fonts+fnum; + if (!s->name) s = fl_fonts; // use 0 if fnum undefined + Fl_FontSize* f; + for (f = s->first; f; f = f->next) + if (f->minsize <= size && f->maxsize >= size) return f; + f = new Fl_FontSize(s->name, size); + f->next = s->first; + s->first = f; + return f; +} + +//////////////////////////////////////////////////////////////// +// Public interface: + +int fl_font_ = 0; +int fl_size_ = 0; +//static HDC font_gc; + +void fl_font(int fnum, int size) { + if (fnum == fl_font_ && size == fl_size_) return; + fl_font_ = fnum; fl_size_ = size; + fl_fontsize = find(fnum, size); +} + +int fl_height() { + if (fl_fontsize) return (fl_fontsize->metr.tmAscent + fl_fontsize->metr.tmDescent); + else return -1; +} + +int fl_descent() { + if (fl_fontsize) return fl_fontsize->metr.tmDescent; + else return -1; +} + +double fl_width(const char* c, int n) { + if (!fl_fontsize) return -1.0; + double w = 0.0; + while (n--) w += fl_fontsize->width[uchar(*c++)]; + return w; +} + +double fl_width(uchar c) { + if (fl_fontsize) return fl_fontsize->width[c]; + else return -1.0; +} + +void fl_draw(const char* str, int n, int x, int y) { + COLORREF oldColor = SetTextColor(fl_gc, fl_RGB()); + if (fl_fontsize) SelectObject(fl_gc, fl_fontsize->fid); + TextOut(fl_gc, x, y, str, n); + SetTextColor(fl_gc, oldColor); +} + +void fl_draw(const char* str, int n, float x, float y) { + fl_draw(str, n, (int)x, (int)y); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_font_x.cxx b/Utilities/FLTK/src/fl_font_x.cxx new file mode 100644 index 0000000000..6540cc275f --- /dev/null +++ b/Utilities/FLTK/src/fl_font_x.cxx @@ -0,0 +1,264 @@ +// +// "$Id$" +// +// Standard X11 font selection code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +Fl_FontSize::Fl_FontSize(const char* name) { + font = XLoadQueryFont(fl_display, name); + if (!font) { + Fl::warning("bad font: %s", name); + font = XLoadQueryFont(fl_display, "fixed"); // if fixed fails we crash + } +# if HAVE_GL + listbase = 0; +# endif +} + +Fl_FontSize* fl_fontsize; + +Fl_FontSize::~Fl_FontSize() { +# if HAVE_GL +// Delete list created by gl_draw(). This is not done by this code +// as it will link in GL unnecessarily. There should be some kind +// of "free" routine pointer, or a subclass? +// if (listbase) { +// int base = font->min_char_or_byte2; +// int size = font->max_char_or_byte2-base+1; +// int base = 0; int size = 256; +// glDeleteLists(listbase+base,size); +// } +# endif + if (this == fl_fontsize) fl_fontsize = 0; + XFreeFont(fl_display, font); +} + +//////////////////////////////////////////////////////////////// + +// WARNING: if you add to this table, you must redefine FL_FREE_FONT +// in Enumerations.H & recompile!! +static Fl_Fontdesc built_in_table[] = { +{"-*-helvetica-medium-r-normal--*"}, +{"-*-helvetica-bold-r-normal--*"}, +{"-*-helvetica-medium-o-normal--*"}, +{"-*-helvetica-bold-o-normal--*"}, +{"-*-courier-medium-r-normal--*"}, +{"-*-courier-bold-r-normal--*"}, +{"-*-courier-medium-o-normal--*"}, +{"-*-courier-bold-o-normal--*"}, +{"-*-times-medium-r-normal--*"}, +{"-*-times-bold-r-normal--*"}, +{"-*-times-medium-i-normal--*"}, +{"-*-times-bold-i-normal--*"}, +{"-*-symbol-*"}, +{"-*-lucidatypewriter-medium-r-normal-sans-*"}, +{"-*-lucidatypewriter-bold-r-normal-sans-*"}, +{"-*-*zapf dingbats-*"} +}; + +Fl_Fontdesc* fl_fonts = built_in_table; + +#define MAXSIZE 32767 + +// return dash number N, or pointer to ending null if none: +const char* fl_font_word(const char* p, int n) { + while (*p) {if (*p=='-') {if (!--n) break;} p++;} + return p; +} + +// return a pointer to a number we think is "point size": +char* fl_find_fontsize(char* name) { + char* c = name; + // for standard x font names, try after 7th dash: + if (*c == '-') { + c = (char*)fl_font_word(c,7); + if (*c++ && isdigit(*c)) return c; + return 0; // malformed x font name? + } + char* r = 0; + // find last set of digits: + for (c++;* c; c++) + if (isdigit(*c) && !isdigit(*(c-1))) r = c; + return r; +} + +const char* fl_encoding = "iso8859-1"; + +// return true if this matches fl_encoding: +int fl_correct_encoding(const char* name) { + if (*name != '-') return 0; + const char* c = fl_font_word(name,13); + return (*c++ && !strcmp(c,fl_encoding)); +} + +// locate or create an Fl_FontSize for a given Fl_Fontdesc and size: +static Fl_FontSize* find(int fnum, int size) { + Fl_Fontdesc* s = fl_fonts+fnum; + if (!s->name) s = fl_fonts; // use font 0 if still undefined + Fl_FontSize* f; + for (f = s->first; f; f = f->next) + if (f->minsize <= size && f->maxsize >= size) return f; + fl_open_display(); + if (!s->xlist) { + s->xlist = XListFonts(fl_display, s->name, 100, &(s->n)); + if (!s->xlist) { // use fixed if no matching font... + s->first = new Fl_FontSize("fixed"); + s->first->minsize = 0; + s->first->maxsize = 32767; + return s->first; + } + } + // search for largest <= font size: + char* name = s->xlist[0]; int ptsize = 0; // best one found so far + int matchedlength = 32767; + char namebuffer[1024]; // holds scalable font name + int found_encoding = 0; + int m = s->n; if (m<0) m = -m; + for (int n=0; n < m; n++) { + + char* thisname = s->xlist[n]; + if (fl_correct_encoding(thisname)) { + if (!found_encoding) ptsize = 0; // force it to choose this + found_encoding = 1; + } else { + if (found_encoding) continue; + } + char* c = fl_find_fontsize(thisname); + int thissize = c ? atoi(c) : MAXSIZE; + int thislength = strlen(thisname); + if (thissize == size && thislength < matchedlength) { + // exact match, use it: + name = thisname; + ptsize = size; + matchedlength = thislength; + } else if (!thissize && ptsize!=size) { + // whoa! A scalable font! Use unless exact match found: + int l = c-thisname; + memcpy(namebuffer,thisname,l); + l += sprintf(namebuffer+l,"%d",size); + while (*c == '0') c++; + strcpy(namebuffer+l,c); + name = namebuffer; + ptsize = size; + } else if (!ptsize || // no fonts yet + thissize < ptsize && ptsize > size || // current font too big + thissize > ptsize && thissize <= size // current too small + ) { + name = thisname; ptsize = thissize; + matchedlength = thislength; + } + } + + if (ptsize != size) { // see if we already found this unscalable font: + for (f = s->first; f; f = f->next) { + if (f->minsize <= ptsize && f->maxsize >= ptsize) { + if (f->minsize > size) f->minsize = size; + if (f->maxsize < size) f->maxsize = size; + return f; + } + } + } + + // okay, we definately have some name, make the font: + f = new Fl_FontSize(name); + if (ptsize < size) {f->minsize = ptsize; f->maxsize = size;} + else {f->minsize = size; f->maxsize = ptsize;} + f->next = s->first; + s->first = f; + return f; + +} + +//////////////////////////////////////////////////////////////// +// Public interface: + +int fl_font_ = 0; +int fl_size_ = 0; +XFontStruct* fl_xfont = 0; +static GC font_gc; + +void fl_font(int fnum, int size) { + if (fnum == fl_font_ && size == fl_size_) return; + fl_font_ = fnum; fl_size_ = size; + Fl_FontSize* f = find(fnum, size); + if (f != fl_fontsize) { + fl_fontsize = f; + fl_xfont = f->font; + font_gc = 0; + } +} + +int fl_height() { + if (fl_xfont) return (fl_xfont->ascent + fl_xfont->descent); + else return -1; +} + +int fl_descent() { + if (fl_xfont) return fl_xfont->descent; + else return -1; +} + +double fl_width(const char* c, int n) { + if (!fl_xfont) return -1.0; + XCharStruct* p = fl_xfont->per_char; + if (!p) return n*fl_xfont->min_bounds.width; + int a = fl_xfont->min_char_or_byte2; + int b = fl_xfont->max_char_or_byte2 - a; + int w = 0; + while (n--) { + int x = *(uchar*)c++ - a; + if (x >= 0 && x <= b) w += p[x].width; + else w += fl_xfont->min_bounds.width; + } + return w; +} + +double fl_width(uchar c) { + if (!fl_xfont) return -1; + XCharStruct* p = fl_xfont->per_char; + if (p) { + int a = fl_xfont->min_char_or_byte2; + int b = fl_xfont->max_char_or_byte2 - a; + int x = c-a; + if (x >= 0 && x <= b) return p[x].width; + } + return fl_xfont->min_bounds.width; +} + +void fl_draw(const char* str, int n, int x, int y) { + if (font_gc != fl_gc) { + if (!fl_xfont) fl_font(FL_HELVETICA, 14); + font_gc = fl_gc; + XSetFont(fl_display, fl_gc, fl_xfont->fid); + } + XDrawString(fl_display, fl_window, fl_gc, x, y, str, n); +} + +void fl_draw(const char* str, int n, float x, float y) { + fl_draw(str, n, (int)x, (int)y); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_font_xft.cxx b/Utilities/FLTK/src/fl_font_xft.cxx new file mode 100644 index 0000000000..d608896bc0 --- /dev/null +++ b/Utilities/FLTK/src/fl_font_xft.cxx @@ -0,0 +1,265 @@ +// +// "$Id$" +// +// Xft font code for the Fast Light Tool Kit (FLTK). +// +// Copyright 2001-2005 Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// +// Draw fonts using Keith Packard's Xft library to provide anti- +// aliased text. Yow! +// +// Many thanks to Carl for making the original version of this. +// +// This font code only requires libXft to work. Contrary to popular +// belief there is no need to have FreeType, or the Xrender extension +// available to use this code. You will just get normal Xlib fonts +// (Xft calls them "core" fonts) The Xft algorithms for choosing +// these is about as good as the FLTK ones (I hope to fix it so it is +// exactly as good...), plus it can cache it's results and share them +// between programs, so using this should be a win in all cases. Also +// it should be obvious by comparing this file and fl_font_x.cxx that +// it is a lot easier to program with Xft than with Xlib. +// +// Also, Xft supports UTF-8 text rendering directly, which will allow +// us to support UTF-8 on all platforms more easily. +// +// To actually get antialiasing you need the following: +// +// 1. You have XFree86 4 +// 2. You have the XRender extension +// 3. Your X device driver supports the render extension +// 4. You have libXft +// 5. Your libXft has FreeType2 support compiled in +// 6. You have the FreeType2 library +// +// Distributions that have XFree86 4.0.3 or later should have all of this... +// +// Unlike some other Xft packages, I tried to keep this simple and not +// to work around the current problems in Xft by making the "patterns" +// complicated. I belive doing this defeats our ability to improve Xft +// itself. You should edit the ~/.xftconfig file to "fix" things, there +// are several web pages of information on how to do this. +// + +#include <X11/Xft/Xft.h> + +// The predefined fonts that FLTK has: +static Fl_Fontdesc built_in_table[] = { +{" sans"}, +{"Bsans"}, +{"Isans"}, +{"Psans"}, +{" mono"}, +{"Bmono"}, +{"Imono"}, +{"Pmono"}, +{" serif"}, +{"Bserif"}, +{"Iserif"}, +{"Pserif"}, +{" symbol"}, +{" screen"}, +{"Bscreen"}, +{" dingbats"}, +}; + +Fl_Fontdesc* fl_fonts = built_in_table; + +#define current_font (fl_fontsize->font) + +int fl_font_ = 0; +int fl_size_ = 0; +XFontStruct* fl_xfont = 0; +const char* fl_encoding_ = "iso8859-1"; +Fl_FontSize* fl_fontsize = 0; + +void fl_font(int fnum, int size) { + if (fnum == fl_font_ && size == fl_size_ && + !strcasecmp(fl_fontsize->encoding, fl_encoding_)) + return; + fl_font_ = fnum; fl_size_ = size; + Fl_Fontdesc *font = fl_fonts + fnum; + Fl_FontSize* f; + // search the fontsizes we have generated already + for (f = font->first; f; f = f->next) { + if (f->size == size && !strcasecmp(f->encoding, fl_encoding_)) + break; + } + if (!f) { + f = new Fl_FontSize(font->name); + f->next = font->first; + font->first = f; + } + fl_fontsize = f; +#if XFT_MAJOR < 2 + fl_xfont = f->font->u.core.font; +#endif // XFT_MAJOR < 2 +} + +static XftFont* fontopen(const char* name, bool core) { + fl_open_display(); + int slant = XFT_SLANT_ROMAN; + int weight = XFT_WEIGHT_MEDIUM; + // may be efficient, but this is non-obvious + switch (*name++) { + case 'I': slant = XFT_SLANT_ITALIC; break; + case 'P': slant = XFT_SLANT_ITALIC; + case 'B': weight = XFT_WEIGHT_BOLD; break; + case ' ': break; + default: name--; + } + // this call is extremely slow... + return XftFontOpen(fl_display, fl_screen, + XFT_FAMILY, XftTypeString, name, + XFT_WEIGHT, XftTypeInteger, weight, + XFT_SLANT, XftTypeInteger, slant, + XFT_ENCODING, XftTypeString, fl_encoding_, + XFT_PIXEL_SIZE, XftTypeDouble, (double)fl_size_, + core ? XFT_CORE : 0, XftTypeBool, true, + XFT_RENDER, XftTypeBool, false, + 0); +} + +Fl_FontSize::Fl_FontSize(const char* name) { + encoding = fl_encoding_; + size = fl_size_; +#if HAVE_GL + listbase = 0; +#endif // HAVE_GL + font = fontopen(name, false); +} + +Fl_FontSize::~Fl_FontSize() { + if (this == fl_fontsize) fl_fontsize = 0; +// XftFontClose(fl_display, font); +} + +int fl_height() { + if (current_font) return current_font->ascent + current_font->descent; + else return -1; +} + +int fl_descent() { + if (current_font) return current_font->descent; + else return -1; +} + +double fl_width(const char *str, int n) { + if (!current_font) return -1.0; + XGlyphInfo i; + XftTextExtents8(fl_display, current_font, (XftChar8 *)str, n, &i); + return i.xOff; +} + +double fl_width(uchar c) { + return fl_width((const char *)(&c), 1); +} + +#if HAVE_GL +// This call is used by opengl to get a bitmapped font. +XFontStruct* fl_xxfont() { +# if XFT_MAJOR > 1 + // kludge! + static XFontStruct* fixed = 0; + if (!fixed) fixed = XLoadQueryFont(fl_display, "fixed"); + return fixed; +# else + if (current_font->core) return current_font->u.core.font; + static XftFont* xftfont; + if (xftfont) XftFontClose (fl_display, xftfont); + xftfont = fontopen(fl_fonts[fl_font_].name, true); + return xftfont->u.core.font; +# endif // XFT_MAJOR > 1 +} +#endif // HAVE_GL + +#if USE_OVERLAY +// Currently Xft does not work with colormapped visuals, so this probably +// does not work unless you have a true-color overlay. +extern bool fl_overlay; +extern Colormap fl_overlay_colormap; +extern XVisualInfo* fl_overlay_visual; +#endif + +// For some reason Xft produces errors if you destroy a window whose id +// still exists in an XftDraw structure. It would be nice if this is not +// true, a lot of junk is needed to try to stop this: + +static XftDraw* draw; +static Window draw_window; +#if USE_OVERLAY +static XftDraw* draw_overlay; +static Window draw_overlay_window; +#endif + +void fl_destroy_xft_draw(Window id) { + if (id == draw_window) + XftDrawChange(draw, draw_window = fl_message_window); +#if USE_OVERLAY + if (id == draw_overlay_window) + XftDrawChange(draw_overlay, draw_overlay_window = fl_message_window); +#endif +} + +void fl_draw(const char *str, int n, int x, int y) { +#if USE_OVERLAY + XftDraw*& draw = fl_overlay ? draw_overlay : ::draw; + if (fl_overlay) { + if (!draw) + draw = XftDrawCreate(fl_display, draw_overlay_window = fl_window, + fl_overlay_visual->visual, fl_overlay_colormap); + else //if (draw_overlay_window != fl_window) + XftDrawChange(draw, draw_overlay_window = fl_window); + } else +#endif + if (!draw) + draw = XftDrawCreate(fl_display, draw_window = fl_window, + fl_visual->visual, fl_colormap); + else //if (draw_window != fl_window) + XftDrawChange(draw, draw_window = fl_window); + + Region region = fl_clip_region(); + if (region && XEmptyRegion(region)) return; + XftDrawSetClip(draw, region); + + // Use fltk's color allocator, copy the results to match what + // XftCollorAllocValue returns: + XftColor color; + color.pixel = fl_xpixel(fl_color_); + uchar r,g,b; Fl::get_color(fl_color_, r,g,b); + color.color.red = ((int)r)*0x101; + color.color.green = ((int)g)*0x101; + color.color.blue = ((int)b)*0x101; + color.color.alpha = 0xffff; + + XftDrawString8(draw, &color, current_font, x, y, (XftChar8 *)str, n); +} + +void fl_draw(const char* str, int n, float x, float y) { + fl_draw(str, n, (int)x, (int)y); +} + +// +// End of "$Id$" +// diff --git a/Utilities/FLTK/src/fl_images_core.cxx b/Utilities/FLTK/src/fl_images_core.cxx new file mode 100644 index 0000000000..96d374c125 --- /dev/null +++ b/Utilities/FLTK/src/fl_images_core.cxx @@ -0,0 +1,103 @@ +// +// "$Id$" +// +// FLTK images library core. +// +// Copyright 1997-2005 by Easy Software Products. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +// Contents: +// +// fl_register_images() - Register the image formats. +// fl_check_images() - Check for a supported image format. +// + +// +// Include necessary header files... +// + +#include <FL/Fl_Shared_Image.H> +#include <FL/Fl_BMP_Image.H> +#include <FL/Fl_GIF_Image.H> +#include <FL/Fl_JPEG_Image.H> +#include <FL/Fl_PNG_Image.H> +#include <FL/Fl_PNM_Image.H> +#include <stdio.h> +#include <stdlib.h> +#include "flstring.h" + + +// +// Define a simple global image registration function that registers +// the extra image formats that aren't part of the core FLTK library. +// + +static Fl_Image *fl_check_images(const char *name, uchar *header, int headerlen); + + +// +// 'fl_register_images()' - Register the image formats. +// + +void fl_register_images() { + Fl_Shared_Image::add_handler(fl_check_images); +} + + +// +// 'fl_check_images()' - Check for a supported image format. +// + +Fl_Image * // O - Image, if found +fl_check_images(const char *name, // I - Filename + uchar *header, // I - Header data from file + int headerlen) { // I - Amount of data + if (memcmp(header, "GIF87a", 6) == 0 || + memcmp(header, "GIF89a", 6) == 0) // GIF file + return new Fl_GIF_Image(name); + + if (memcmp(header, "BM", 2) == 0) // BMP file + return new Fl_BMP_Image(name); + + if (header[0] == 'P' && header[1] >= '1' && header[1] <= '7') + // Portable anymap + return new Fl_PNM_Image(name); + +#ifdef HAVE_LIBPNG + if (memcmp(header, "\211PNG", 4) == 0)// PNG file + return new Fl_PNG_Image(name); +#endif // HAVE_LIBPNG + +#ifdef HAVE_LIBJPEG + if (memcmp(header, "\377\330\377", 3) == 0 && + // Start-of-Image + header[3] >= 0xe0 && header[3] <= 0xef) + // APPn for JPEG file + return new Fl_JPEG_Image(name); +#endif // HAVE_LIBJPEG + + return 0; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_labeltype.cxx b/Utilities/FLTK/src/fl_labeltype.cxx new file mode 100644 index 0000000000..c73f40a9fb --- /dev/null +++ b/Utilities/FLTK/src/fl_labeltype.cxx @@ -0,0 +1,133 @@ +// +// "$Id$" +// +// Label drawing routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Drawing code for the (one) common label types. +// Other label types (symbols) are in their own source files +// to avoid linking if not used. + +#include <FL/Fl.H> +#include <FL/Fl_Widget.H> +#include <FL/Fl_Group.H> +#include <FL/fl_draw.H> +#include <FL/Fl_Image.H> + +void +fl_no_label(const Fl_Label*,int,int,int,int,Fl_Align) {} + +void +fl_normal_label(const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align) +{ + fl_font(o->font, o->size); + fl_color((Fl_Color)o->color); + fl_draw(o->value, X, Y, W, H, align, o->image); +} + +void +fl_normal_measure(const Fl_Label* o, int& W, int& H) { + fl_font(o->font, o->size); + fl_measure(o->value, W, H); + if (o->image) { + if (o->image->w() > W) W = o->image->w(); + H += o->image->h(); + } +} + +#define MAX_LABELTYPE 16 + +static Fl_Label_Draw_F* table[MAX_LABELTYPE] = { + fl_normal_label, + fl_no_label, + fl_normal_label, // _FL_SHADOW_LABEL, + fl_normal_label, // _FL_ENGRAVED_LABEL, + fl_normal_label, // _FL_EMBOSSED_LABEL, + fl_no_label, // _FL_MULTI_LABEL, + fl_no_label, // _FL_ICON_LABEL, + // FL_FREE_LABELTYPE+n: + fl_no_label, fl_no_label, fl_no_label, + fl_no_label, fl_no_label, fl_no_label, + fl_no_label, fl_no_label, fl_no_label +}; + +static Fl_Label_Measure_F* measure[MAX_LABELTYPE]; + +void Fl::set_labeltype(Fl_Labeltype t,Fl_Label_Draw_F* f,Fl_Label_Measure_F*m) +{ + table[t] = f; measure[t] = m; +} + +//////////////////////////////////////////////////////////////// + +// draw label with arbitrary alignment in arbitrary box: +void Fl_Label::draw(int X, int Y, int W, int H, Fl_Align align) const { + if (!value && !image) return; + table[type](this, X, Y, W, H, align); +} + +void Fl_Label::measure(int& W, int& H) const { + if (!value && !image) { + W = H = 0; + return; + } + + Fl_Label_Measure_F* f = ::measure[type]; if (!f) f = fl_normal_measure; + f(this, W, H); +} + +// The normal call for a draw() method: +void Fl_Widget::draw_label() const { + int X = x_+Fl::box_dx(box()); + int W = w_-Fl::box_dw(box()); + if (W > 11 && align()&(FL_ALIGN_LEFT|FL_ALIGN_RIGHT)) {X += 3; W -= 6;} + draw_label(X, y_+Fl::box_dy(box()), W, h_-Fl::box_dh(box())); +} + +// draw() can use this instead to change the bounding box: +void Fl_Widget::draw_label(int X, int Y, int W, int H) const { + // quit if we are not drawing a label inside the widget: + if ((align()&15) && !(align() & FL_ALIGN_INSIDE)) return; + draw_label(X,Y,W,H,align()); +} + +// Anybody can call this to force the label to draw anywhere: +void Fl_Widget::draw_label(int X, int Y, int W, int H, Fl_Align a) const { + if (flags()&SHORTCUT_LABEL) fl_draw_shortcut = 1; + Fl_Label l1 = label_; + if (!active_r()) { + l1.color = fl_inactive((Fl_Color)l1.color); + if (l1.deimage) l1.image = l1.deimage; + } + l1.draw(X,Y,W,H,a); + fl_draw_shortcut = 0; +} + +// include these vars here so they can be referenced without including +// Fl_Input_ code: +#include <FL/Fl_Input_.H> + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_line_style.cxx b/Utilities/FLTK/src/fl_line_style.cxx new file mode 100644 index 0000000000..a0be2894da --- /dev/null +++ b/Utilities/FLTK/src/fl_line_style.cxx @@ -0,0 +1,165 @@ +// +// "$Id$" +// +// Line style code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/fl_draw.H> +#include <FL/x.H> +#include "flstring.h" +#include <stdio.h> + +#ifdef __APPLE_QUARTZ__ +float fl_quartz_line_width_ = 1.0f; +static enum CGLineCap fl_quartz_line_cap_ = kCGLineCapButt; +static enum CGLineJoin fl_quartz_line_join_ = kCGLineJoinMiter; +static float *fl_quartz_line_pattern = 0; +static int fl_quartz_line_pattern_size = 0; +void fl_quartz_restore_line_style_() { + CGContextSetLineWidth(fl_gc, fl_quartz_line_width_); + CGContextSetLineCap(fl_gc, fl_quartz_line_cap_); + CGContextSetLineJoin(fl_gc, fl_quartz_line_join_); + CGContextSetLineDash(fl_gc, 0, fl_quartz_line_pattern, fl_quartz_line_pattern_size); +} +#endif + +void fl_line_style(int style, int width, char* dashes) { +#ifdef WIN32 + // According to Bill, the "default" cap and join should be the + // "fastest" mode supported for the platform. I don't know why + // they should be different (same graphics cards, etc., right?) MRS + static DWORD Cap[4]= {PS_ENDCAP_FLAT, PS_ENDCAP_FLAT, PS_ENDCAP_ROUND, PS_ENDCAP_SQUARE}; + static DWORD Join[4]={PS_JOIN_ROUND, PS_JOIN_MITER, PS_JOIN_ROUND, PS_JOIN_BEVEL}; + int s1 = PS_GEOMETRIC | Cap[(style>>8)&3] | Join[(style>>12)&3]; + DWORD a[16]; int n = 0; + if (dashes && dashes[0]) { + s1 |= PS_USERSTYLE; + for (n = 0; n < 16 && *dashes; n++) a[n] = *dashes++; + } else { + s1 |= style & 0xff; // allow them to pass any low 8 bits for style + } + if ((style || n) && !width) width = 1; // fix cards that do nothing for 0? + LOGBRUSH penbrush = {BS_SOLID,fl_RGB(),0}; // can this be fl_brush()? + HPEN newpen = ExtCreatePen(s1, width, &penbrush, n, n ? a : 0); + if (!newpen) { + Fl::error("fl_line_style(): Could not create GDI pen object."); + return; + } + HPEN oldpen = (HPEN)SelectObject(fl_gc, newpen); + DeleteObject(oldpen); + DeleteObject(fl_current_xmap->pen); + fl_current_xmap->pen = newpen; +#elif defined(__APPLE_QD__) + // QuickDraw supports pen size and pattern, but no arbitrary line styles. + static Pattern styles[] = { + { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } }, // FL_SOLID + { { 0xf0, 0xf0, 0xf0, 0xf0, 0x0f, 0x0f, 0x0f, 0x0f } }, // FL_DASH + { { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 } } // FL_DOT + }; + + if (!width) width = 1; + PenSize(width, width); + + style &= 0xff; + if (style > 2) style = 2; + PenPat(styles + style); +#elif defined(__APPLE_QUARTZ__) + static enum CGLineCap Cap[4] = { kCGLineCapButt, kCGLineCapButt, + kCGLineCapRound, kCGLineCapSquare }; + static enum CGLineJoin Join[4] = { kCGLineJoinMiter, kCGLineJoinMiter, + kCGLineJoinRound, kCGLineJoinBevel }; + if (width<1) width = 1; + fl_quartz_line_width_ = (float)width; + fl_quartz_line_cap_ = Cap[(style>>8)&3]; + fl_quartz_line_join_ = Join[(style>>12)&3]; + char *d = dashes; + static float pattern[16]; + if (d && *d) { + float *p = pattern; + while (*d) { *p++ = (float)*d++; } + fl_quartz_line_pattern = pattern; + fl_quartz_line_pattern_size = d-dashes; + } else if (style & 0xff) { + char dash, dot, gap; + // adjust lengths to account for cap: + if (style & 0x200) { + dash = char(2*width); + dot = 1; + gap = char(2*width-1); + } else { + dash = char(3*width); + dot = gap = char(width); + } + float *p = pattern; + switch (style & 0xff) { + case FL_DASH: *p++ = dash; *p++ = gap; break; + case FL_DOT: *p++ = dot; *p++ = gap; break; + case FL_DASHDOT: *p++ = dash; *p++ = gap; *p++ = dot; *p++ = gap; break; + case FL_DASHDOTDOT: *p++ = dash; *p++ = gap; *p++ = dot; *p++ = gap; *p++ = dot; *p++ = gap; break; + } + fl_quartz_line_pattern_size = p-pattern; + fl_quartz_line_pattern = pattern; + } else { + fl_quartz_line_pattern = 0; fl_quartz_line_pattern_size = 0; + } + fl_quartz_restore_line_style_(); +#else + int ndashes = dashes ? strlen(dashes) : 0; + // emulate the WIN32 dash patterns on X + char buf[7]; + if (!ndashes && (style&0xff)) { + int w = width ? width : 1; + char dash, dot, gap; + // adjust lengths to account for cap: + if (style & 0x200) { + dash = char(2*w); + dot = 1; // unfortunately 0 does not work + gap = char(2*w-1); + } else { + dash = char(3*w); + dot = gap = char(w); + } + char* p = dashes = buf; + switch (style & 0xff) { + case FL_DASH: *p++ = dash; *p++ = gap; break; + case FL_DOT: *p++ = dot; *p++ = gap; break; + case FL_DASHDOT: *p++ = dash; *p++ = gap; *p++ = dot; *p++ = gap; break; + case FL_DASHDOTDOT: *p++ = dash; *p++ = gap; *p++ = dot; *p++ = gap; *p++ = dot; *p++ = gap; break; + } + ndashes = p-buf; + } + static int Cap[4] = {CapButt, CapButt, CapRound, CapProjecting}; + static int Join[4] = {JoinMiter, JoinMiter, JoinRound, JoinBevel}; + XSetLineAttributes(fl_display, fl_gc, width, + ndashes ? LineOnOffDash : LineSolid, + Cap[(style>>8)&3], Join[(style>>12)&3]); + if (ndashes) XSetDashes(fl_display, fl_gc, 0, dashes, ndashes); +#endif +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_oval_box.cxx b/Utilities/FLTK/src/fl_oval_box.cxx new file mode 100644 index 0000000000..3d5ad009e0 --- /dev/null +++ b/Utilities/FLTK/src/fl_oval_box.cxx @@ -0,0 +1,66 @@ +// +// "$Id$" +// +// Oval box drawing code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + + +// Less-used box types are in seperate files so they are not linked +// in if not used. + +#include <FL/Fl.H> +#include <FL/fl_draw.H> + +static void fl_oval_flat_box(int x, int y, int w, int h, Fl_Color c) { + fl_color(c); + fl_pie(x, y, w, h, 0, 360); +} + +static void fl_oval_frame(int x, int y, int w, int h, Fl_Color c) { + fl_color(c); + fl_arc(x, y, w, h, 0, 360); +} + +static void fl_oval_box(int x, int y, int w, int h, Fl_Color c) { + fl_oval_flat_box(x,y,w,h,c); + fl_oval_frame(x,y,w,h,FL_BLACK); +} + +static void fl_oval_shadow_box(int x, int y, int w, int h, Fl_Color c) { + fl_oval_flat_box(x+3,y+3,w,h,FL_DARK3); + fl_oval_box(x,y,w,h,c); +} + +extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*); +Fl_Boxtype fl_define_FL_OVAL_BOX() { + fl_internal_boxtype(_FL_OSHADOW_BOX,fl_oval_shadow_box); + fl_internal_boxtype(_FL_OVAL_FRAME,fl_oval_frame); + fl_internal_boxtype(_FL_OFLAT_BOX,fl_oval_flat_box); + fl_internal_boxtype(_FL_OVAL_BOX,fl_oval_box); + return _FL_OVAL_BOX; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_overlay.cxx b/Utilities/FLTK/src/fl_overlay.cxx new file mode 100644 index 0000000000..6e740add3c --- /dev/null +++ b/Utilities/FLTK/src/fl_overlay.cxx @@ -0,0 +1,81 @@ +// +// "$Id$" +// +// Overlay support for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Extremely limited "overlay" support. You can use this to drag out +// a rectangle in response to mouse events. It is your responsibility +// to erase the overlay before drawing anything that might intersect +// it. + +#include <FL/x.H> +#include <FL/fl_draw.H> +#ifdef __APPLE__ +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#endif + +static int px,py,pw,ph; + +static void draw_current_rect() { +#ifdef WIN32 + int old = SetROP2(fl_gc, R2_NOT); + fl_rect(px, py, pw, ph); + SetROP2(fl_gc, old); +#elif defined(__APPLE_QD__) + PenMode( patXor ); + fl_rect(px, py, pw, ph); + PenMode( patCopy ); +#elif defined(__APPLE_QUARTZ__) + // warning: Quartz does not support xor drawing + // Use the Fl_Overlay_Window instead. + fl_rect(px, py, pw, ph); +#else + XSetFunction(fl_display, fl_gc, GXxor); + XSetForeground(fl_display, fl_gc, 0xffffffff); + XDrawRectangle(fl_display, fl_window, fl_gc, px, py, pw, ph); + XSetFunction(fl_display, fl_gc, GXcopy); +#endif +} + +void fl_overlay_clear() { + if (pw > 0) {draw_current_rect(); pw = 0;} +} + +void fl_overlay_rect(int x, int y, int w, int h) { + if (w < 0) {x += w; w = -w;} else if (!w) w = 1; + if (h < 0) {y += h; h = -h;} else if (!h) h = 1; + if (pw > 0) { + if (x==px && y==py && w==pw && h==ph) return; + draw_current_rect(); + } + px = x; py = y; pw = w; ph = h; + draw_current_rect(); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_overlay_visual.cxx b/Utilities/FLTK/src/fl_overlay_visual.cxx new file mode 100644 index 0000000000..b94d130762 --- /dev/null +++ b/Utilities/FLTK/src/fl_overlay_visual.cxx @@ -0,0 +1,107 @@ +// +// "$Id$" +// +// X overlay support for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Return an overlay visual, if any. Also allocate a colormap and +// record the depth for fl_color() to use. +// Another disgusting X interface, based on code extracted and +// purified with great difficulty from XLayerUtil.cxx: + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#if HAVE_OVERLAY +#include <FL/Fl.H> +#include <FL/x.H> + +// SERVER_OVERLAY_VISUALS property element: +struct OverlayInfo { + long overlay_visual; + long transparent_type; + long value; + long layer; +}; + +extern Colormap fl_overlay_colormap; +extern XVisualInfo* fl_overlay_visual; +extern ulong fl_transparent_pixel; + +XVisualInfo *fl_find_overlay_visual() { + static char beenhere; + if (beenhere) return fl_overlay_visual; + beenhere = 1; + + fl_open_display(); + Atom overlayVisualsAtom = + XInternAtom(fl_display,"SERVER_OVERLAY_VISUALS",1); + if (!overlayVisualsAtom) return 0; + OverlayInfo *overlayInfo; + ulong sizeData, bytesLeft; + Atom actualType; + int actualFormat; + if (XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen), + overlayVisualsAtom, 0L, 10000L, False, + overlayVisualsAtom, &actualType, &actualFormat, + &sizeData, &bytesLeft, + (unsigned char **) &overlayInfo)) return 0; + + if (actualType == overlayVisualsAtom && actualFormat == 32) { + int n = int(sizeData/4); + XVisualInfo* v = 0; + // find the greatest depth that has a transparent pixel: + for (int i = 0; i < n; i++) { + if (overlayInfo[i].transparent_type != 1) continue; + if (overlayInfo[i].layer <= 0) continue; + XVisualInfo templt; + templt.visualid = overlayInfo[i].overlay_visual; + int num; + XVisualInfo *v1=XGetVisualInfo(fl_display, VisualIDMask, &templt, &num); + if (v1->screen == fl_screen && v1->c_class == PseudoColor + && (!v || v1->depth > v->depth && v1->depth <= 8)) { + if (v) XFree((char*)v); + v = v1; + fl_transparent_pixel = overlayInfo[i].value; + } else { + XFree((char*)v1); + } + } + if (v) { + fl_overlay_visual = v; + fl_overlay_colormap = + XCreateColormap(fl_display, RootWindow(fl_display, fl_screen), + v->visual, AllocNone); + } + } + XFree((char*)overlayInfo); + //printf("overlay visual %ld selected\n", fl_overlay_visual->visualid); + return fl_overlay_visual; +} + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_plastic.cxx b/Utilities/FLTK/src/fl_plastic.cxx new file mode 100644 index 0000000000..86216e3cc8 --- /dev/null +++ b/Utilities/FLTK/src/fl_plastic.cxx @@ -0,0 +1,381 @@ +// +// "$Id$" +// +// "Plastic" drawing routines for the Fast Light Tool Kit (FLTK). +// +// These box types provide a cross between Aqua and KDE buttons; kindof +// like translucent plastic buttons... +// +// Copyright 2001-2005 by Michael Sweet. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Box drawing code for an obscure box type. +// These box types are in seperate files so they are not linked +// in if not used. + +#include <FL/Fl.H> +#include <FL/fl_draw.H> +#include "flstring.h" + +// +// Uncomment the following line to restore the old plastic box type +// appearance. +// + +//#define USE_OLD_PLASTIC_BOX +#define USE_OLD_PLASTIC_COLOR + +extern uchar *fl_gray_ramp(); + +inline Fl_Color shade_color(uchar gc, Fl_Color bc) { +#ifdef USE_OLD_PLASTIC_COLOR + return fl_color_average((Fl_Color)gc, bc, 0.75f); +#else + unsigned grgb = Fl::get_color((Fl_Color)gc), + brgb = Fl::get_color(bc); + int red, green, blue, gray; + + + gray = ((grgb >> 24) & 255); + red = gray * ((brgb >> 24) & 255) / 255 + gray * gray / 510; + gray = ((grgb >> 16) & 255); + green = gray * ((brgb >> 16) & 255) / 255 + gray * gray / 510; + gray = ((grgb >> 8) & 255); + blue = gray * ((brgb >> 8) & 255) / 255 + gray * gray / 510; + + if (red > 255) + red = 255; + + if (green > 255) + green = 255; + + if (blue > 255) + blue = 255; + + if (Fl::draw_box_active()) + return fl_rgb_color(red, green, blue); + else + return fl_color_average(FL_GRAY, fl_rgb_color(red, green, blue), 0.75f); +#endif // USE_OLD_PLASTIC_COLOR +} + + +static void frame_rect(int x, int y, int w, int h, const char *c, Fl_Color bc) { + uchar *g = fl_gray_ramp(); + int b = strlen(c) / 4 + 1; + + for (x += b, y += b, w -= 2 * b, h -= 2 * b; b > 1; b --) + { + // Draw lines around the perimeter of the button, 4 colors per + // circuit. + fl_color(shade_color(g[*c++], bc)); + fl_line(x, y + h + b, x + w - 1, y + h + b, x + w + b - 1, y + h); + fl_color(shade_color(g[*c++], bc)); + fl_line(x + w + b - 1, y + h, x + w + b - 1, y, x + w - 1, y - b); + fl_color(shade_color(g[*c++], bc)); + fl_line(x + w - 1, y - b, x, y - b, x - b, y); + fl_color(shade_color(g[*c++], bc)); + fl_line(x - b, y, x - b, y + h, x, y + h + b); + } +} + + +static void frame_round(int x, int y, int w, int h, const char *c, Fl_Color bc) { + uchar *g = fl_gray_ramp(); + int b = strlen(c) / 4 + 1; + + if (w==h) { + for (; b > 1; b --, x ++, y ++, w -= 2, h -= 2) + { + fl_color(shade_color(g[*c++], bc)); + fl_arc(x, y, w, h, 45.0, 135.0); + fl_color(shade_color(g[*c++], bc)); + fl_arc(x, y, w, h, 315.0, 405.0); + fl_color(shade_color(g[*c++], bc)); + fl_arc(x, y, w, h, 225.0, 315.0); + fl_color(shade_color(g[*c++], bc)); + fl_arc(x, y, w, h, 135.0, 225.0); + } + } else if (w>h) { + int d = h/2; + for (; b > 1; d--, b --, x ++, y ++, w -= 2, h -= 2) + { + fl_color(shade_color(g[*c++], bc)); + fl_arc(x, y, h, h, 90.0, 135.0); + fl_xyline(x+d, y, x+w-d); + fl_arc(x+w-h, y, h, h, 45.0, 90.0); + fl_color(shade_color(g[*c++], bc)); + fl_arc(x+w-h, y, h, h, 315.0, 405.0); + fl_color(shade_color(g[*c++], bc)); + fl_arc(x+w-h, y, h, h, 270.0, 315.0); + fl_xyline(x+d, y+h-1, x+w-d); + fl_arc(x, y, h, h, 225.0, 270.0); + fl_color(shade_color(g[*c++], bc)); + fl_arc(x, y, h, h, 135.0, 225.0); + } + } else if (w<h) { + int d = w/2; + for (; b > 1; d--, b --, x ++, y ++, w -= 2, h -= 2) + { + fl_color(shade_color(g[*c++], bc)); + fl_arc(x, y, w, w, 45.0, 135.0); + fl_color(shade_color(g[*c++], bc)); + fl_arc(x, y, w, w, 0.0, 45.0); + fl_yxline(x+w-1, y+d, y+h-d); + fl_arc(x, y+h-w, w, w, 315.0, 360.0); + fl_color(shade_color(g[*c++], bc)); + fl_arc(x, y+h-w, w, w, 225.0, 315.0); + fl_color(shade_color(g[*c++], bc)); + fl_arc(x, y+h-w, w, w, 180.0, 225.0); + fl_yxline(x, y+d, y+h-d); + fl_arc(x, y, w, w, 135.0, 180.0); + } + } +} + + +static void shade_rect(int x, int y, int w, int h, const char *c, Fl_Color bc) { + uchar *g = fl_gray_ramp(); + int i, j; + int clen = strlen(c) - 1; + int chalf = clen / 2; + int cstep = 1; + + if (h < (w * 2)) { + // Horizontal shading... + if (clen >= h) cstep = 2; + + for (i = 0, j = 0; j < chalf; i ++, j += cstep) { + // Draw the top line and points... + fl_color(shade_color(g[c[i]], bc)); + fl_xyline(x + 1, y + i, x + w - 2); + + fl_color(shade_color(g[c[i] - 2], bc)); + fl_point(x, y + i + 1); + fl_point(x + w - 1, y + i + 1); + + // Draw the bottom line and points... + fl_color(shade_color(g[c[clen - i]], bc)); + fl_xyline(x + 1, y + h - i, x + w - 2); + + fl_color(shade_color(g[c[clen - i] - 2], bc)); + fl_point(x, y + h - i); + fl_point(x + w - 1, y + h - i); + } + + // Draw the interior and sides... + i = chalf / cstep; + + fl_color(shade_color(g[c[chalf]], bc)); + fl_rectf(x + 1, y + i, w - 2, h - 2 * i + 1); + + fl_color(shade_color(g[c[chalf] - 2], bc)); + fl_yxline(x, y + i, y + h - i); + fl_yxline(x + w - 1, y + i, y + h - i); + } else { + // Vertical shading... + if (clen >= w) cstep = 2; + + for (i = 0, j = 0; j < chalf; i ++, j += cstep) { + // Draw the left line and points... + fl_color(shade_color(g[c[i]], bc)); + fl_yxline(x + i, y + 1, y + h - 1); + + fl_color(shade_color(g[c[i] - 2], bc)); + fl_point(x + i + 1, y); + fl_point(x + i + 1, y + h); + + // Draw the right line and points... + fl_color(shade_color(g[c[clen - i]], bc)); + fl_yxline(x + w - 1 - i, y + 1, y + h - 1); + + fl_color(shade_color(g[c[clen - i] - 2], bc)); + fl_point(x + w - 2 - i, y); + fl_point(x + w - 2 - i, y + h); + } + + // Draw the interior, top, and bottom... + i = chalf / cstep; + + fl_color(shade_color(g[c[chalf]], bc)); + fl_rectf(x + i, y + 1, w - 2 * i, h - 1); + + fl_color(shade_color(g[c[chalf] - 2], bc)); + fl_xyline(x + i, y, x + w - i); + fl_xyline(x + i, y + h, x + w - i); + } +} + +static void shade_round(int x, int y, int w, int h, const char *c, Fl_Color bc) { + uchar *g = fl_gray_ramp(); + int i; + int clen = strlen(c) - 1; + int chalf = clen / 2; + + if (w>h) { + int d = h/2; + const int na = 8; + for (i=0; i<chalf; i++, d--, x++, y++, w-=2, h-=2) + { + fl_color(shade_color(g[c[i]], bc)); + fl_pie(x, y, h, h, 90.0, 135.0+i*na); + fl_xyline(x+d, y, x+w-d); + fl_pie(x+w-h, y, h, h, 45.0+i*na, 90.0); + fl_color(shade_color(g[c[i] - 2], bc)); + fl_pie(x+w-h, y, h, h, 315.0+i*na, 405.0+i*na); + fl_color(shade_color(g[c[clen - i]], bc)); + fl_pie(x+w-h, y, h, h, 270.0, 315.0+i*na); + fl_xyline(x+d, y+h-1, x+w-d); + fl_pie(x, y, h, h, 225.0+i*na, 270.0); + fl_color(shade_color(g[c[clen - i] - 2], bc)); + fl_pie(x, y, h, h, 135.0+i*na, 225.0+i*na); + } + fl_color(shade_color(g[c[chalf]], bc)); + fl_rectf(x+d, y, w-h+1, h+1); + fl_pie(x, y, h, h, 90.0, 270.0); + fl_pie(x+w-h, y, h, h, 270.0, 90.0); + } else { + int d = w/2; + const int na = 8; + for (i=0; i<chalf; i++, d--, x++, y++, w-=2, h-=2) + { + fl_color(shade_color(g[c[i]], bc)); + fl_pie(x, y, w, w, 45.0+i*na, 135.0+i*na); + fl_color(shade_color(g[c[i] - 2], bc)); + fl_pie(x, y, w, w, 0.0, 45.0+i*na); + fl_yxline(x+w-1, y+d, y+h-d); + fl_pie(x, y+h-w, w, w, 315.0+i*na, 360.0); + fl_color(shade_color(g[c[clen - i]], bc)); + fl_pie(x, y+h-w, w, w, 225.0+i*na, 315.0+i*na); + fl_color(shade_color(g[c[clen - i] - 2], bc)); + fl_pie(x, y+h-w, w, w, 180.0, 225.0+i*na); + fl_yxline(x, y+d, y+h-d); + fl_pie(x, y, w, w, 135.0+i*na, 180.0); + } + fl_color(shade_color(g[c[chalf]], bc)); + fl_rectf(x, y+d, w+1, h-w+1); + fl_pie(x, y, w, w, 0.0, 180.0); + fl_pie(x, y+h-w, w, w, 180.0, 360.0); + } +} + + +static void up_frame(int x, int y, int w, int h, Fl_Color c) { + frame_rect(x, y, w, h - 1, "KLDIIJLM", c); +} + + +static void narrow_thin_box(int x, int y, int w, int h, Fl_Color c) { + if (h<=0 || w<=0) return; + uchar *g = fl_gray_ramp(); + fl_color(shade_color(g['R'], c)); + fl_rectf(x+1, y+1, w-2, h-2); + fl_color(shade_color(g['I'], c)); + if (w > 1) { + fl_xyline(x+1, y, x+w-2); + fl_xyline(x+1, y+h-1, x+w-2); + } + if (h > 1) { + fl_yxline(x, y+1, y+h-2); + fl_yxline(x+w-1, y+1, y+h-2); + } +} + + +static void thin_up_box(int x, int y, int w, int h, Fl_Color c) { +#ifdef USE_OLD_PLASTIC_BOX + shade_rect(x + 2, y + 2, w - 4, h - 5, "RVQNOPQRSTUVWVQ", c); + up_frame(x, y, w, h, c); +#else + if (w > 4 && h > 4) { + shade_rect(x + 1, y + 1, w - 2, h - 3, "RQOQSUWQ", c); + frame_rect(x, y, w, h - 1, "IJLM", c); + } else { + narrow_thin_box(x, y, w, h, c); + } +#endif // USE_OLD_PLASTIC_BOX +} + + +static void up_box(int x, int y, int w, int h, Fl_Color c) { +#ifdef USE_OLD_PLASTIC_BOX + shade_rect(x + 2, y + 2, w - 4, h - 5, "RVQNOPQRSTUVWVQ", c); + up_frame(x, y, w, h, c); +#else + if (w > 8 && h > 8) { + shade_rect(x + 1, y + 1, w - 2, h - 3, "RVQNOPQRSTUVWVQ", c); + frame_rect(x, y, w, h - 1, "IJLM", c); + } else { + thin_up_box(x, y, w, h, c); + } +#endif // USE_OLD_PLASTIC_BOX +} + + +static void up_round(int x, int y, int w, int h, Fl_Color c) { + shade_round(x, y, w, h, "RVQNOPQRSTUVWVQ", c); + frame_round(x, y, w, h, "IJLM", c); +} + + +static void down_frame(int x, int y, int w, int h, Fl_Color c) { + frame_rect(x, y, w, h - 1, "LLLLTTRR", c); +} + + +static void down_box(int x, int y, int w, int h, Fl_Color c) { + if (w > 6 && h > 6) { + shade_rect(x + 2, y + 2, w - 4, h - 5, "STUVWWWVT", c); + down_frame(x, y, w, h, c); + } + else { + narrow_thin_box(x, y, w, h, c); + } +} + + +static void down_round(int x, int y, int w, int h, Fl_Color c) { + shade_round(x, y, w, h, "STUVWWWVT", c); + frame_round(x, y, w, h, "IJLM", c); +} + + +extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*); + + +Fl_Boxtype fl_define_FL_PLASTIC_UP_BOX() { + fl_internal_boxtype(_FL_PLASTIC_UP_BOX, up_box); + fl_internal_boxtype(_FL_PLASTIC_DOWN_BOX, down_box); + fl_internal_boxtype(_FL_PLASTIC_UP_FRAME, up_frame); + fl_internal_boxtype(_FL_PLASTIC_DOWN_FRAME, down_frame); + fl_internal_boxtype(_FL_PLASTIC_THIN_UP_BOX, thin_up_box); + fl_internal_boxtype(_FL_PLASTIC_THIN_DOWN_BOX, down_box); + fl_internal_boxtype(_FL_PLASTIC_ROUND_UP_BOX, up_round); + fl_internal_boxtype(_FL_PLASTIC_ROUND_DOWN_BOX, down_round); + + return _FL_PLASTIC_UP_BOX; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_read_image.cxx b/Utilities/FLTK/src/fl_read_image.cxx new file mode 100644 index 0000000000..f0370a9c63 --- /dev/null +++ b/Utilities/FLTK/src/fl_read_image.cxx @@ -0,0 +1,425 @@ +// +// "$Id$" +// +// X11 image reading routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/x.H> +#include <FL/fl_draw.H> +#include "flstring.h" + +#ifdef DEBUG +# include <stdio.h> +#endif // DEBUG + +#ifdef WIN32 +# include "fl_read_image_win32.cxx" +#elif defined(__APPLE__) +# include "fl_read_image_mac.cxx" +#else +# include <X11/Xutil.h> +# ifdef __sgi +# include <X11/extensions/readdisplay.h> +# endif // __sgi + +// Defined in fl_color.cxx +extern uchar fl_redmask, fl_greenmask, fl_bluemask; +extern int fl_redshift, fl_greenshift, fl_blueshift, fl_extrashift; + +// +// 'fl_read_image()' - Read an image from the current window. +// + +uchar * // O - Pixel buffer or NULL if failed +fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate + int X, // I - Left position + int Y, // I - Top position + int w, // I - Width of area to read + int h, // I - Height of area to read + int alpha) { // I - Alpha value for image (0 for none) + XImage *image; // Captured image + int i, maxindex; // Looping vars + int x, y; // Current X & Y in image + int d; // Depth of image + unsigned char *line, // Array to hold image row + *line_ptr; // Pointer to current line image + unsigned char *pixel; // Current color value + XColor colors[4096]; // Colors from the colormap... + unsigned char cvals[4096][3]; // Color values from the colormap... + unsigned index_mask, + index_shift, + red_mask, + red_shift, + green_mask, + green_shift, + blue_mask, + blue_shift; + + + // + // Under X11 we have the option of the XGetImage() interface or SGI's + // ReadDisplay extension which does all of the really hard work for + // us... + // + +# ifdef __sgi + if (XReadDisplayQueryExtension(fl_display, &i, &i)) { + image = XReadDisplay(fl_display, fl_window, X, Y, w, h, 0, NULL); + } else +# else + image = 0; +# endif // __sgi + + if (!image) { + image = XGetImage(fl_display, fl_window, X, Y, w, h, AllPlanes, ZPixmap); + } + + if (!image) return 0; + +#ifdef DEBUG + printf("width = %d\n", image->width); + printf("height = %d\n", image->height); + printf("xoffset = %d\n", image->xoffset); + printf("format = %d\n", image->format); + printf("data = %p\n", image->data); + printf("byte_order = %d\n", image->byte_order); + printf("bitmap_unit = %d\n", image->bitmap_unit); + printf("bitmap_bit_order = %d\n", image->bitmap_bit_order); + printf("bitmap_pad = %d\n", image->bitmap_pad); + printf("depth = %d\n", image->depth); + printf("bytes_per_line = %d\n", image->bytes_per_line); + printf("bits_per_pixel = %d\n", image->bits_per_pixel); + printf("red_mask = %08x\n", image->red_mask); + printf("green_mask = %08x\n", image->green_mask); + printf("blue_mask = %08x\n", image->blue_mask); + printf("map_entries = %d\n", fl_visual->visual->map_entries); +#endif // DEBUG + + d = alpha ? 4 : 3; + + // Allocate the image data array as needed... + if (!p) p = new uchar[w * h * d]; + + // Initialize the default colors/alpha in the whole image... + memset(p, alpha, w * h * d); + + // Check that we have valid mask/shift values... + if (!image->red_mask && image->bits_per_pixel > 12) { + // Greater than 12 bits must be TrueColor... + image->red_mask = fl_visual->visual->red_mask; + image->green_mask = fl_visual->visual->green_mask; + image->blue_mask = fl_visual->visual->blue_mask; + +#ifdef DEBUG + puts("\n---- UPDATED ----"); + printf("fl_redmask = %08x\n", fl_redmask); + printf("fl_redshift = %d\n", fl_redshift); + printf("fl_greenmask = %08x\n", fl_greenmask); + printf("fl_greenshift = %d\n", fl_greenshift); + printf("fl_bluemask = %08x\n", fl_bluemask); + printf("fl_blueshift = %d\n", fl_blueshift); + printf("red_mask = %08x\n", image->red_mask); + printf("green_mask = %08x\n", image->green_mask); + printf("blue_mask = %08x\n", image->blue_mask); +#endif // DEBUG + } + + // Check if we have colormap image... + if (!image->red_mask) { + // Get the colormap entries for this window... + maxindex = fl_visual->visual->map_entries; + + for (i = 0; i < maxindex; i ++) colors[i].pixel = i; + + XQueryColors(fl_display, fl_colormap, colors, maxindex); + + for (i = 0; i < maxindex; i ++) { + cvals[i][0] = colors[i].red >> 8; + cvals[i][1] = colors[i].green >> 8; + cvals[i][2] = colors[i].blue >> 8; + } + + // Read the pixels and output an RGB image... + for (y = 0; y < image->height; y ++) { + pixel = (unsigned char *)(image->data + y * image->bytes_per_line); + line = p + y * w * d; + + switch (image->bits_per_pixel) { + case 1 : + for (x = image->width, line_ptr = line, index_mask = 128; + x > 0; + x --, line_ptr += d) { + if (*pixel & index_mask) { + line_ptr[0] = cvals[1][0]; + line_ptr[1] = cvals[1][1]; + line_ptr[2] = cvals[1][2]; + } else { + line_ptr[0] = cvals[0][0]; + line_ptr[1] = cvals[0][1]; + line_ptr[2] = cvals[0][2]; + } + + if (index_mask > 1) { + index_mask >>= 1; + } else { + index_mask = 128; + pixel ++; + } + } + break; + + case 2 : + for (x = image->width, line_ptr = line, index_shift = 6; + x > 0; + x --, line_ptr += d) { + i = (*pixel >> index_shift) & 3; + + line_ptr[0] = cvals[i][0]; + line_ptr[1] = cvals[i][1]; + line_ptr[2] = cvals[i][2]; + + if (index_shift > 0) { + index_mask >>= 2; + index_shift -= 2; + } else { + index_mask = 192; + index_shift = 6; + pixel ++; + } + } + break; + + case 4 : + for (x = image->width, line_ptr = line, index_shift = 4; + x > 0; + x --, line_ptr += d) { + if (index_shift == 4) i = (*pixel >> 4) & 15; + else i = *pixel & 15; + + line_ptr[0] = cvals[i][0]; + line_ptr[1] = cvals[i][1]; + line_ptr[2] = cvals[i][2]; + + if (index_shift > 0) { + index_shift = 0; + } else { + index_shift = 4; + pixel ++; + } + } + break; + + case 8 : + for (x = image->width, line_ptr = line; + x > 0; + x --, line_ptr += d, pixel ++) { + line_ptr[0] = cvals[*pixel][0]; + line_ptr[1] = cvals[*pixel][1]; + line_ptr[2] = cvals[*pixel][2]; + } + break; + + case 12 : + for (x = image->width, line_ptr = line, index_shift = 0; + x > 0; + x --, line_ptr += d) { + if (index_shift == 0) { + i = ((pixel[0] << 4) | (pixel[1] >> 4)) & 4095; + } else { + i = ((pixel[1] << 8) | pixel[2]) & 4095; + } + + line_ptr[0] = cvals[i][0]; + line_ptr[1] = cvals[i][1]; + line_ptr[2] = cvals[i][2]; + + if (index_shift == 0) { + index_shift = 4; + } else { + index_shift = 0; + pixel += 3; + } + } + break; + } + } + } else { + // RGB(A) image, so figure out the shifts & masks... + red_mask = image->red_mask; + red_shift = 0; + + while ((red_mask & 1) == 0) { + red_mask >>= 1; + red_shift ++; + } + + green_mask = image->green_mask; + green_shift = 0; + + while ((green_mask & 1) == 0) { + green_mask >>= 1; + green_shift ++; + } + + blue_mask = image->blue_mask; + blue_shift = 0; + + while ((blue_mask & 1) == 0) { + blue_mask >>= 1; + blue_shift ++; + } + + // Read the pixels and output an RGB image... + for (y = 0; y < image->height; y ++) { + pixel = (unsigned char *)(image->data + y * image->bytes_per_line); + line = p + y * w * d; + + switch (image->bits_per_pixel) { + case 8 : + for (x = image->width, line_ptr = line; + x > 0; + x --, line_ptr += d, pixel ++) { + i = *pixel; + + line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; + line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; + line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; + } + break; + + case 12 : + for (x = image->width, line_ptr = line, index_shift = 0; + x > 0; + x --, line_ptr += d) { + if (index_shift == 0) { + i = ((pixel[0] << 4) | (pixel[1] >> 4)) & 4095; + } else { + i = ((pixel[1] << 8) | pixel[2]) & 4095; + } + + line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; + line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; + line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; + + if (index_shift == 0) { + index_shift = 4; + } else { + index_shift = 0; + pixel += 3; + } + } + break; + + case 16 : + if (image->byte_order == LSBFirst) { + // Little-endian... + for (x = image->width, line_ptr = line; + x > 0; + x --, line_ptr += d, pixel += 2) { + i = (pixel[1] << 8) | pixel[0]; + + line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; + line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; + line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; + } + } else { + // Big-endian... + for (x = image->width, line_ptr = line; + x > 0; + x --, line_ptr += d, pixel += 2) { + i = (pixel[0] << 8) | pixel[1]; + + line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; + line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; + line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; + } + } + break; + + case 24 : + if (image->byte_order == LSBFirst) { + // Little-endian... + for (x = image->width, line_ptr = line; + x > 0; + x --, line_ptr += d, pixel += 3) { + i = (((pixel[2] << 8) | pixel[1]) << 8) | pixel[0]; + + line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; + line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; + line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; + } + } else { + // Big-endian... + for (x = image->width, line_ptr = line; + x > 0; + x --, line_ptr += d, pixel += 3) { + i = (((pixel[0] << 8) | pixel[1]) << 8) | pixel[2]; + + line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; + line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; + line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; + } + } + break; + + case 32 : + if (image->byte_order == LSBFirst) { + // Little-endian... + for (x = image->width, line_ptr = line; + x > 0; + x --, line_ptr += d, pixel += 4) { + i = (((((pixel[3] << 8) | pixel[2]) << 8) | pixel[1]) << 8) | pixel[0]; + + line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; + line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; + line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; + } + } else { + // Big-endian... + for (x = image->width, line_ptr = line; + x > 0; + x --, line_ptr += d, pixel += 4) { + i = (((((pixel[0] << 8) | pixel[1]) << 8) | pixel[2]) << 8) | pixel[3]; + + line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; + line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; + line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; + } + } + break; + } + } + } + + // Destroy the X image we've read and return the RGB(A) image... + XDestroyImage(image); + + return p; +} + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_read_image_mac.cxx b/Utilities/FLTK/src/fl_read_image_mac.cxx new file mode 100644 index 0000000000..0488fedd6b --- /dev/null +++ b/Utilities/FLTK/src/fl_read_image_mac.cxx @@ -0,0 +1,129 @@ +// +// "$Id$" +// +// WIN32 image reading routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +// warning: this function is only implemented in Quickdraw. The function +// below may not work If FLTK is compiled with Quartz enabled + +// +// 'fl_read_image()' - Read an image from the current window. +// + +uchar * // O - Pixel buffer or NULL if failed +fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate + int x, // I - Left position + int y, // I - Top position + int w, // I - Width of area to read + int h, // I - Height of area to read + int alpha) { // I - Alpha value for image (0 for none) + Rect src, // Source rectangle + dst; // Destination rectangle + Fl_Offscreen osbuffer; // Temporary off-screen buffer for copy + GrafPtr srcPort; // Source port + RGBColor rgb; // RGB colors for copy mask... + PixMapHandle pm; // Pixmap handle for off-screen buffer + uchar *base, // Base address of off-screen buffer + *psrc, // Pointer into off-screen buffer + *pdst; // Pointer into pixel buffer + int idx, idy; // Current X & Y in image + int d; // Depth of image + int rowBytes; // Number of bytes per row... + + + // Get an off-screen buffer for copying the image... + osbuffer = fl_create_offscreen(w,h); + + if (!osbuffer) return 0; + + // Set the source and destination rectangles... + src.top = y; + src.left = x; + src.bottom = y + h; + src.right = x + w; + + dst.top = 0; + dst.left = 0; + dst.bottom = h; + dst.right = w; + + // Get the source port... + GetPort(&srcPort); + + // Set the RGB copy mask via the foreground/background colors... + rgb.red = 0xffff; + rgb.green = 0xffff; + rgb.blue = 0xffff; + RGBBackColor(&rgb); + + rgb.red = 0x0000; + rgb.green = 0x0000; + rgb.blue = 0x0000; + RGBForeColor(&rgb); + + // Copy the screen image to the off-screen buffer... + CopyBits(GetPortBitMapForCopyBits(srcPort), + GetPortBitMapForCopyBits(osbuffer), &src, &dst, srcCopy, 0L); + + // Allocate the image data array as needed... + d = alpha ? 4 : 3; + + if (!p) p = new uchar[w * h * d]; + + // Initialize the default colors/alpha in the whole image... + memset(p, alpha, w * h * d); + + // Set the correct port for the off-screen buffer and lock the buffer + SetGWorld(osbuffer, 0); + + pm = GetGWorldPixMap(osbuffer); + LockPixels(pm); + + base = (uchar *)GetPixBaseAddr(pm); + rowBytes = (*pm)->rowBytes & 0x3fff; + + // Copy the image from the off-screen buffer to the memory buffer. + for (idy = 0, pdst = p; idy < h; idy ++) + for (idx = 0, psrc = base + idy * rowBytes + 1; idx < w; idx ++, psrc += 4, pdst += d) { + pdst[0] = psrc[0]; + pdst[1] = psrc[1]; + pdst[2] = psrc[2]; + } + + // Unlock and delete the off-screen buffer, then return... + UnlockPixels(pm); + fl_delete_offscreen(osbuffer); + + SetPort(srcPort); + return p; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_read_image_win32.cxx b/Utilities/FLTK/src/fl_read_image_win32.cxx new file mode 100644 index 0000000000..b218d598f9 --- /dev/null +++ b/Utilities/FLTK/src/fl_read_image_win32.cxx @@ -0,0 +1,72 @@ +// +// "$Id$" +// +// WIN32 image reading routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// +// 'fl_read_image()' - Read an image from the current window. +// + +uchar * // O - Pixel buffer or NULL if failed +fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate + int X, // I - Left position + int Y, // I - Top position + int w, // I - Width of area to read + int h, // I - Height of area to read + int alpha) { // I - Alpha value for image (0 for none) + int x, y; // Looping vars + int d; // Depth of image + uchar *ptr; // Pointer in image data + + + // Allocate the image data array as needed... + d = alpha ? 4 : 3; + + if (!p) p = new uchar[w * h * d]; + + // Initialize the default colors/alpha in the whole image... + memset(p, alpha, w * h * d); + + // Grab all of the pixels in the image, one at a time... + // MRS: there has to be a better way than this! + for (y = 0, ptr = p; y < h; y ++) { + for (x = 0; x < w; x ++, ptr += d) { + COLORREF c = GetPixel(fl_gc, X + x, Y + y); + + ptr[0] = c; + c >>= 8; + ptr[1] = c; + c >>= 8; + ptr[2] = c; + } + } + + return p; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_rect.cxx b/Utilities/FLTK/src/fl_rect.cxx new file mode 100644 index 0000000000..75a08b0b79 --- /dev/null +++ b/Utilities/FLTK/src/fl_rect.cxx @@ -0,0 +1,677 @@ +// +// "$Id$" +// +// Rectangle drawing routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// These routines from fl_draw.H are used by the standard boxtypes +// and thus are always linked into an fltk program. +// Also all fl_clip routines, since they are always linked in so +// that minimal update works. + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#include <FL/Fl.H> +#include <FL/Fl_Widget.H> +#include <FL/fl_draw.H> +#include <FL/x.H> + +#ifdef __APPLE_QUARTZ__ +extern float fl_quartz_line_width_; +#endif + +void fl_rect(int x, int y, int w, int h) { + if (w<=0 || h<=0) return; +#ifdef WIN32 + MoveToEx(fl_gc, x, y, 0L); + LineTo(fl_gc, x+w-1, y); + LineTo(fl_gc, x+w-1, y+h-1); + LineTo(fl_gc, x, y+h-1); + LineTo(fl_gc, x, y); +#elif defined(__APPLE_QD__) + Rect rect; + SetRect(&rect, x, y, x+w, y+h); + FrameRect(&rect); +#elif defined(__APPLE_QUARTZ__) + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false); + CGRect rect = CGRectMake(x, y, w-1, h-1); + CGContextStrokeRect(fl_gc, rect); + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true); +#else + XDrawRectangle(fl_display, fl_window, fl_gc, x, y, w-1, h-1); +#endif +} + +void fl_rectf(int x, int y, int w, int h) { + if (w<=0 || h<=0) return; +#ifdef WIN32 + RECT rect; + rect.left = x; rect.top = y; + rect.right = x + w; rect.bottom = y + h; + FillRect(fl_gc, &rect, fl_brush()); +#elif defined(__APPLE_QD__) + Rect rect; + SetRect(&rect, x, y, x+w, y+h); + PaintRect(&rect); +#elif defined(__APPLE_QUARTZ__) + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false); + CGRect rect = CGRectMake(x, y, w-1, h-1); + CGContextFillRect(fl_gc, rect); + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true); +#else + if (w && h) XFillRectangle(fl_display, fl_window, fl_gc, x, y, w, h); +#endif +} + +void fl_xyline(int x, int y, int x1) { +#ifdef WIN32 + MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x1+1, y); +#elif defined(__APPLE_QD__) + MoveTo(x, y); LineTo(x1, y); +#elif defined(__APPLE_QUARTZ__) + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y); + CGContextStrokePath(fl_gc); + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true); +#else + XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y); +#endif +} + +void fl_xyline(int x, int y, int x1, int y2) { +#ifdef WIN32 + if (y2 < y) y2--; + else y2++; + MoveToEx(fl_gc, x, y, 0L); + LineTo(fl_gc, x1, y); + LineTo(fl_gc, x1, y2); +#elif defined(__APPLE_QD__) + MoveTo(x, y); + LineTo(x1, y); + LineTo(x1, y2); +#elif defined(__APPLE_QUARTZ__) + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y); + CGContextAddLineToPoint(fl_gc, x1, y2); + CGContextStrokePath(fl_gc); + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true); +#else + XPoint p[3]; + p[0].x = x; p[0].y = p[1].y = y; + p[1].x = p[2].x = x1; p[2].y = y2; + XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0); +#endif +} + +void fl_xyline(int x, int y, int x1, int y2, int x3) { +#ifdef WIN32 + if(x3 < x1) x3--; + else x3++; + MoveToEx(fl_gc, x, y, 0L); + LineTo(fl_gc, x1, y); + LineTo(fl_gc, x1, y2); + LineTo(fl_gc, x3, y2); +#elif defined(__APPLE_QD__) + MoveTo(x, y); + LineTo(x1, y); + LineTo(x1, y2); + LineTo(x3, y2); +#elif defined(__APPLE_QUARTZ__) + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y); + CGContextAddLineToPoint(fl_gc, x1, y2); + CGContextAddLineToPoint(fl_gc, x3, y2); + CGContextStrokePath(fl_gc); + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true); +#else + XPoint p[4]; + p[0].x = x; p[0].y = p[1].y = y; + p[1].x = p[2].x = x1; p[2].y = p[3].y = y2; + p[3].x = x3; + XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0); +#endif +} + +void fl_yxline(int x, int y, int y1) { +#ifdef WIN32 + if (y1 < y) y1--; + else y1++; + MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x, y1); +#elif defined(__APPLE_QD__) + MoveTo(x, y); LineTo(x, y1); +#elif defined(__APPLE_QUARTZ__) + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x, y1); + CGContextStrokePath(fl_gc); + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true); +#else + XDrawLine(fl_display, fl_window, fl_gc, x, y, x, y1); +#endif +} + +void fl_yxline(int x, int y, int y1, int x2) { +#ifdef WIN32 + if (x2 > x) x2++; + else x2--; + MoveToEx(fl_gc, x, y, 0L); + LineTo(fl_gc, x, y1); + LineTo(fl_gc, x2, y1); +#elif defined(__APPLE_QD__) + MoveTo(x, y); + LineTo(x, y1); + LineTo(x2, y1); +#elif defined(__APPLE_QUARTZ__) + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x, y1); + CGContextAddLineToPoint(fl_gc, x2, y1); + CGContextStrokePath(fl_gc); + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true); +#else + XPoint p[3]; + p[0].x = p[1].x = x; p[0].y = y; + p[1].y = p[2].y = y1; p[2].x = x2; + XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0); +#endif +} + +void fl_yxline(int x, int y, int y1, int x2, int y3) { +#ifdef WIN32 + if(y3<y1) y3--; + else y3++; + MoveToEx(fl_gc, x, y, 0L); + LineTo(fl_gc, x, y1); + LineTo(fl_gc, x2, y1); + LineTo(fl_gc, x2, y3); +#elif defined(__APPLE_QD__) + MoveTo(x, y); + LineTo(x, y1); + LineTo(x2, y1); + LineTo(x2, y3); +#elif defined(__APPLE_QUARTZ__) + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x, y1); + CGContextAddLineToPoint(fl_gc, x2, y1); + CGContextAddLineToPoint(fl_gc, x2, y3); + CGContextStrokePath(fl_gc); + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true); +#else + XPoint p[4]; + p[0].x = p[1].x = x; p[0].y = y; + p[1].y = p[2].y = y1; p[2].x = p[3].x = x2; + p[3].y = y3; + XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0); +#endif +} + +void fl_line(int x, int y, int x1, int y1) { +#ifdef WIN32 + MoveToEx(fl_gc, x, y, 0L); + LineTo(fl_gc, x1, y1); + // Draw the last point *again* because the GDI line drawing + // functions will not draw the last point ("it's a feature!"...) + SetPixel(fl_gc, x1, y1, fl_RGB()); +#elif defined(__APPLE_QD__) + MoveTo(x, y); + LineTo(x1, y1); +#elif defined(__APPLE_QUARTZ__) + if (fl_quartz_line_width_==1.0f ) CGContextSetShouldAntialias(fl_gc, false); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y1); + CGContextStrokePath(fl_gc); + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true); +#else + XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y1); +#endif +} + +void fl_line(int x, int y, int x1, int y1, int x2, int y2) { +#ifdef WIN32 + MoveToEx(fl_gc, x, y, 0L); + LineTo(fl_gc, x1, y1); + LineTo(fl_gc, x2, y2); + // Draw the last point *again* because the GDI line drawing + // functions will not draw the last point ("it's a feature!"...) + SetPixel(fl_gc, x2, y2, fl_RGB()); +#elif defined(__APPLE_QD__) + MoveTo(x, y); + LineTo(x1, y1); + LineTo(x2, y2); +#elif defined(__APPLE_QUARTZ__) + if (fl_quartz_line_width_==1.0f ) CGContextSetShouldAntialias(fl_gc, false); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y1); + CGContextAddLineToPoint(fl_gc, x2, y2); + CGContextStrokePath(fl_gc); + if (fl_quartz_line_width_==1.0f ) CGContextSetShouldAntialias(fl_gc, true); +#else + XPoint p[3]; + p[0].x = x; p[0].y = y; + p[1].x = x1; p[1].y = y1; + p[2].x = x2; p[2].y = y2; + XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0); +#endif +} + +void fl_loop(int x, int y, int x1, int y1, int x2, int y2) { +#ifdef WIN32 + MoveToEx(fl_gc, x, y, 0L); + LineTo(fl_gc, x1, y1); + LineTo(fl_gc, x2, y2); + LineTo(fl_gc, x, y); +#elif defined(__APPLE_QD__) + MoveTo(x, y); + LineTo(x1, y1); + LineTo(x2, y2); + LineTo(x, y); +#elif defined(__APPLE_QUARTZ__) + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y1); + CGContextAddLineToPoint(fl_gc, x2, y2); + CGContextClosePath(fl_gc); + CGContextStrokePath(fl_gc); +#else + XPoint p[4]; + p[0].x = x; p[0].y = y; + p[1].x = x1; p[1].y = y1; + p[2].x = x2; p[2].y = y2; + p[3].x = x; p[3].y = y; + XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0); +#endif +} + +void fl_loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { +#ifdef WIN32 + MoveToEx(fl_gc, x, y, 0L); + LineTo(fl_gc, x1, y1); + LineTo(fl_gc, x2, y2); + LineTo(fl_gc, x3, y3); + LineTo(fl_gc, x, y); +#elif defined(__APPLE_QD__) + MoveTo(x, y); + LineTo(x1, y1); + LineTo(x2, y2); + LineTo(x3, y3); + LineTo(x, y); +#elif defined(__APPLE_QUARTZ__) + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y1); + CGContextAddLineToPoint(fl_gc, x2, y2); + CGContextAddLineToPoint(fl_gc, x3, y3); + CGContextClosePath(fl_gc); + CGContextStrokePath(fl_gc); +#else + XPoint p[5]; + p[0].x = x; p[0].y = y; + p[1].x = x1; p[1].y = y1; + p[2].x = x2; p[2].y = y2; + p[3].x = x3; p[3].y = y3; + p[4].x = x; p[4].y = y; + XDrawLines(fl_display, fl_window, fl_gc, p, 5, 0); +#endif +} + +void fl_polygon(int x, int y, int x1, int y1, int x2, int y2) { + XPoint p[4]; + p[0].x = x; p[0].y = y; + p[1].x = x1; p[1].y = y1; + p[2].x = x2; p[2].y = y2; +#ifdef WIN32 + SelectObject(fl_gc, fl_brush()); + Polygon(fl_gc, p, 3); +#elif defined(__APPLE_QD__) + PolyHandle poly = OpenPoly(); + MoveTo(x, y); + LineTo(x1, y1); + LineTo(x2, y2); + LineTo(x, y); + ClosePoly(); + PaintPoly(poly); + FramePoly(poly); + KillPoly(poly); +#elif defined(__APPLE_QUARTZ__) + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y1); + CGContextAddLineToPoint(fl_gc, x2, y2); + CGContextClosePath(fl_gc); + CGContextFillPath(fl_gc); +#else + p[3].x = x; p[3].y = y; + XFillPolygon(fl_display, fl_window, fl_gc, p, 3, Convex, 0); + XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0); +#endif +} + +void fl_polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { + XPoint p[5]; + p[0].x = x; p[0].y = y; + p[1].x = x1; p[1].y = y1; + p[2].x = x2; p[2].y = y2; + p[3].x = x3; p[3].y = y3; +#ifdef WIN32 + SelectObject(fl_gc, fl_brush()); + Polygon(fl_gc, p, 4); +#elif defined(__APPLE_QD__) + PolyHandle poly = OpenPoly(); + MoveTo(x, y); + LineTo(x1, y1); + LineTo(x2, y2); + LineTo(x3, y3); + LineTo(x, y); + ClosePoly(); + PaintPoly(poly); + FramePoly(poly); + KillPoly(poly); +#elif defined(__APPLE_QUARTZ__) + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y1); + CGContextAddLineToPoint(fl_gc, x2, y2); + CGContextAddLineToPoint(fl_gc, x3, y3); + CGContextClosePath(fl_gc); + CGContextFillPath(fl_gc); +#else + p[4].x = x; p[4].y = y; + XFillPolygon(fl_display, fl_window, fl_gc, p, 4, Convex, 0); + XDrawLines(fl_display, fl_window, fl_gc, p, 5, 0); +#endif +} + +void fl_point(int x, int y) { +#ifdef WIN32 + SetPixel(fl_gc, x, y, fl_RGB()); +#elif defined(__APPLE_QD__) + MoveTo(x, y); Line(0, 0); +#elif defined(__APPLE_QUARTZ__) + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x, y); + CGContextStrokePath(fl_gc); + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, true); +#else + XDrawPoint(fl_display, fl_window, fl_gc, x, y); +#endif +} + +//////////////////////////////////////////////////////////////// + +#define STACK_SIZE 10 +#define STACK_MAX (STACK_SIZE - 1) +static Fl_Region rstack[STACK_SIZE]; +static int rstackptr=0; +int fl_clip_state_number=0; // used by gl_begin.cxx to update GL clip + +#if !defined(WIN32) && !defined(__APPLE__) +// Missing X call: (is this the fastest way to init a 1-rectangle region?) +// MSWindows equivalent exists, implemented inline in win32.H +Fl_Region XRectangleRegion(int x, int y, int w, int h) { + XRectangle R; + R.x = x; R.y = y; R.width = w; R.height = h; + Fl_Region r = XCreateRegion(); + XUnionRectWithRegion(&R, r, r); + return r; +} +#endif + +#ifdef __APPLE_QD__ +extern Fl_Region fl_window_region; +#elif defined(__APPLE_QUARTZ__) +// warning: the Quartz implementation currently uses Quickdraw calls to achieve +// clipping. A future version should instead use 'CGContectClipToRect' +// and friends. +extern Fl_Region fl_window_region; +#endif + +// undo any clobbering of clip done by your program: +void fl_restore_clip() { + fl_clip_state_number++; + Fl_Region r = rstack[rstackptr]; +#ifdef WIN32 + SelectClipRgn(fl_gc, r); //if r is NULL, clip is automatically cleared +#elif defined(__APPLE_QD__) +# if 1 + // This code is required to allow true subwindows to work on Mac. + // During regular operation however, this seems overkill. + // See also: Fl_Window::make_current() + if ( fl_window ) { + GrafPtr port = GetWindowPort( fl_window ); + if ( port ) { // port will be NULL if we are using a GWorld (and fl_window_region is invalid) + RgnHandle portClip = NewRgn(); + CopyRgn( fl_window_region, portClip ); // changed + if ( r ) + SectRgn( portClip, r, portClip ); + SetPortClipRegion( port, portClip ); + DisposeRgn( portClip ); + } + } else { + if (r) + SetClip(r); + else { + Rect rect; rect.left=0; rect.top=0; rect.right=0x7fff; rect.bottom=0x7fff; + ClipRect(&rect); + } + } +# else + if (r) SetClip(r); + else { + Rect rect; rect.left=0; rect.top=0; rect.right=0x7fff; rect.bottom=0x7fff; + ClipRect(&rect); + } +# endif +#elif defined(__APPLE_QUARTZ__) + if ( fl_window ) + { + GrafPtr port = GetWindowPort( fl_window ); + if ( port ) { + RgnHandle portClip = NewRgn(); + CopyRgn( fl_window_region, portClip ); // changed + if ( r ) + SectRgn( portClip, r, portClip ); + Rect portRect; GetPortBounds(port, &portRect); + Fl_X::q_clear_clipping(); + ClipCGContextToRegion(fl_gc, &portRect, portClip ); + Fl_X::q_fill_context(); + DisposeRgn( portClip ); + } + } +#else + if (r) XSetRegion(fl_display, fl_gc, r); + else XSetClipMask(fl_display, fl_gc, 0); +#endif +} + +// Replace the top of the clip stack: +void fl_clip_region(Fl_Region r) { + Fl_Region oldr = rstack[rstackptr]; + if (oldr) XDestroyRegion(oldr); + rstack[rstackptr] = r; + fl_restore_clip(); +} + +// Return the current clip region... +Fl_Region fl_clip_region() { + return rstack[rstackptr]; +} + +// Intersect & push a new clip rectangle: +void fl_push_clip(int x, int y, int w, int h) { + Fl_Region r; + if (w > 0 && h > 0) { + r = XRectangleRegion(x,y,w,h); + Fl_Region current = rstack[rstackptr]; + if (current) { +#ifdef WIN32 + CombineRgn(r,r,current,RGN_AND); +#elif defined(__APPLE_QD__) + SectRgn(r, current, r); +#elif defined(__APPLE_QUARTZ__) + SectRgn(r, current, r); +#else + Fl_Region temp = XCreateRegion(); + XIntersectRegion(current, r, temp); + XDestroyRegion(r); + r = temp; +#endif + } + } else { // make empty clip region: +#ifdef WIN32 + r = CreateRectRgn(0,0,0,0); +#elif defined(__APPLE_QD__) + r = NewRgn(); + SetEmptyRgn(r); +#elif defined(__APPLE_QUARTZ__) + r = NewRgn(); + SetEmptyRgn(r); +#else + r = XCreateRegion(); +#endif + } + if (rstackptr < STACK_MAX) rstack[++rstackptr] = r; + else Fl::warning("fl_push_clip: clip stack overflow!\n"); + fl_restore_clip(); +} + +// make there be no clip (used by fl_begin_offscreen() only!) +void fl_push_no_clip() { + if (rstackptr < STACK_MAX) rstack[++rstackptr] = 0; + else Fl::warning("fl_push_no_clip: clip stack overflow!\n"); + fl_restore_clip(); +} + +// pop back to previous clip: +void fl_pop_clip() { + if (rstackptr > 0) { + Fl_Region oldr = rstack[rstackptr--]; + if (oldr) XDestroyRegion(oldr); + } else Fl::warning("fl_pop_clip: clip stack underflow!\n"); + fl_restore_clip(); +} + +// does this rectangle intersect current clip? +int fl_not_clipped(int x, int y, int w, int h) { + if (x+w <= 0 || y+h <= 0) return 0; + Fl_Region r = rstack[rstackptr]; +#ifdef WIN32 + if (!r) return 1; + RECT rect; + rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h; + return RectInRegion(r,&rect); +#elif defined(__APPLE_QD__) + if (!r) return 1; + Rect rect; + rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h; + return RectInRgn(&rect, r); +#elif defined(__APPLE_QUARTZ__) + if (!r) return 1; + Rect rect; + rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h; + return RectInRgn(&rect, r); +#else + return r ? XRectInRegion(r, x, y, w, h) : 1; +#endif +} + +// return rectangle surrounding intersection of this rectangle and clip: +int fl_clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){ + X = x; Y = y; W = w; H = h; + Fl_Region r = rstack[rstackptr]; + if (!r) return 0; +#ifdef WIN32 +// The win32 API makes no distinction between partial and complete +// intersection, so we have to check for partial intersection ourselves. +// However, given that the regions may be composite, we have to do +// some voodoo stuff... + Fl_Region rr = XRectangleRegion(x,y,w,h); + Fl_Region temp = CreateRectRgn(0,0,0,0); + int ret; + if (CombineRgn(temp, rr, r, RGN_AND) == NULLREGION) { // disjoint + W = H = 0; + ret = 2; + } else if (EqualRgn(temp, rr)) { // complete + ret = 0; + } else { // parital intersection + RECT rect; + GetRgnBox(temp, &rect); + X = rect.left; Y = rect.top; W = rect.right - X; H = rect.bottom - Y; + ret = 1; + } + DeleteObject(temp); + DeleteObject(rr); + return ret; +#elif defined(__APPLE_QD__) + RgnHandle rr = NewRgn(); + SetRectRgn( rr, x, y, x+w, y+h ); + SectRgn( r, rr, rr ); + Rect rp; GetRegionBounds(rr, &rp); + X = rp.left; + Y = rp.top; + W = rp.right - X; + H = rp.bottom - Y; + DisposeRgn( rr ); + if ( H==0 ) return 2; + if ( h==H && w==W ) return 0; + return 0; +#elif defined(__APPLE_QUARTZ__) + RgnHandle rr = NewRgn(); + SetRectRgn( rr, x, y, x+w, y+h ); + SectRgn( r, rr, rr ); + Rect rp; GetRegionBounds(rr, &rp); + X = rp.left; + Y = rp.top; + W = rp.right - X; + H = rp.bottom - Y; + DisposeRgn( rr ); + if ( H==0 ) return 2; + if ( h==H && w==W ) return 0; + return 0; +#else + switch (XRectInRegion(r, x, y, w, h)) { + case 0: // completely outside + W = H = 0; + return 2; + case 1: // completely inside: + return 0; + default: // partial: + break; + } + Fl_Region rr = XRectangleRegion(x,y,w,h); + Fl_Region temp = XCreateRegion(); + XIntersectRegion(r, rr, temp); + XRectangle rect; + XClipBox(temp, &rect); + X = rect.x; Y = rect.y; W = rect.width; H = rect.height; + XDestroyRegion(temp); + XDestroyRegion(rr); + return 1; +#endif +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_round_box.cxx b/Utilities/FLTK/src/fl_round_box.cxx new file mode 100644 index 0000000000..e8b085e6b7 --- /dev/null +++ b/Utilities/FLTK/src/fl_round_box.cxx @@ -0,0 +1,122 @@ +// +// "$Id$" +// +// Round box drawing routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Box drawing code for an obscure box type. +// These box types are in seperate files so they are not linked +// in if not used. + +#include <FL/Fl.H> +#include <FL/fl_draw.H> + +// A compiler from a certain very large software company will not compile +// the function pointer assignment due to the name conflict with fl_arc. +// This function is to fix that: +void fl_arc_i(int x,int y,int w,int h,double a1,double a2) { + fl_arc(x,y,w,h,a1,a2); +} + +enum {UPPER_LEFT, LOWER_RIGHT, CLOSED, FILL}; + +static void draw(int which, int x,int y,int w,int h, int inset, uchar color) +{ + if (inset*2 >= w) inset = (w-1)/2; + if (inset*2 >= h) inset = (h-1)/2; + x += inset; + y += inset; + w -= 2*inset; + h -= 2*inset; + int d = w <= h ? w : h; + if (d <= 1) return; + fl_color((Fl_Color)color); + void (*f)(int,int,int,int,double,double); + f = (which==FILL) ? fl_pie : fl_arc_i; + if (which >= CLOSED) { + f(x+w-d, y, d, d, w<=h ? 0 : -90, w<=h ? 180 : 90); + f(x, y+h-d, d, d, w<=h ? 180 : 90, w<=h ? 360 : 270); + } else if (which == UPPER_LEFT) { + f(x+w-d, y, d, d, 45, w<=h ? 180 : 90); + f(x, y+h-d, d, d, w<=h ? 180 : 90, 225); + } else { // LOWER_RIGHT + f(x, y+h-d, d, d, 225, w<=h ? 360 : 270); + f(x+w-d, y, d, d, w<=h ? 360 : 270, 360+45); + } + if (which == FILL) { + if (w < h) + fl_rectf(x, y+d/2, w, h-(d&-2)); + else if (w > h) + fl_rectf(x+d/2, y, w-(d&-2), h); + } else { + if (w < h) { + if (which != UPPER_LEFT) fl_yxline(x+w-1, y+d/2-1, y+h-d/2+1); + if (which != LOWER_RIGHT) fl_yxline(x, y+d/2-1, y+h-d/2+1); + } else if (w > h) { + if (which != UPPER_LEFT) fl_xyline(x+d/2-1, y+h-1, x+w-d/2+1); + if (which != LOWER_RIGHT) fl_xyline(x+d/2-1, y, x+w-d/2+1); + } + } +} + +extern uchar* fl_gray_ramp(); + +void fl_round_down_box(int x, int y, int w, int h, Fl_Color bgcolor) { + uchar *g = fl_gray_ramp(); + draw(FILL, x, y, w, h, 2, bgcolor); + draw(UPPER_LEFT, x+1, y, w-2, h, 0, g['N']); + draw(UPPER_LEFT, x+1, y, w-2, h, 1, g['H']); + draw(UPPER_LEFT, x, y, w, h, 0, g['N']); + draw(UPPER_LEFT, x, y, w, h, 1, g['H']); + draw(LOWER_RIGHT, x, y, w, h, 0, g['S']); + draw(LOWER_RIGHT, x+1, y, w-2, h, 0, g['U']); + draw(LOWER_RIGHT, x, y, w, h, 1, g['U']); + draw(LOWER_RIGHT, x+1, y, w-2, h, 1, g['W']); + draw(CLOSED, x, y, w, h, 2, g['A']); +} + +void fl_round_up_box(int x, int y, int w, int h, Fl_Color bgcolor) { + uchar *g = fl_gray_ramp(); + draw(FILL, x, y, w, h, 2, bgcolor); + draw(LOWER_RIGHT, x+1, y, w-2, h, 0, g['H']); + draw(LOWER_RIGHT, x+1, y, w-2, h, 1, g['N']); + draw(LOWER_RIGHT, x, y, w, h, 1, g['H']); + draw(LOWER_RIGHT, x, y, w, h, 2, g['N']); + draw(UPPER_LEFT, x, y, w, h, 2, g['U']); + draw(UPPER_LEFT, x+1, y, w-2, h, 1, g['S']); + draw(UPPER_LEFT, x, y, w, h, 1, g['W']); + draw(UPPER_LEFT, x+1, y, w-2, h, 0, g['U']); + draw(CLOSED, x, y, w, h, 0, g['A']); +} + +extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*); +Fl_Boxtype fl_define_FL_ROUND_UP_BOX() { + fl_internal_boxtype(_FL_ROUND_DOWN_BOX, fl_round_down_box); + fl_internal_boxtype(_FL_ROUND_UP_BOX, fl_round_up_box); + return _FL_ROUND_UP_BOX; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_rounded_box.cxx b/Utilities/FLTK/src/fl_rounded_box.cxx new file mode 100644 index 0000000000..bffaf29a0b --- /dev/null +++ b/Utilities/FLTK/src/fl_rounded_box.cxx @@ -0,0 +1,99 @@ +// +// "$Id$" +// +// Rounded box drawing routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/fl_draw.H> + +#define RN 5 +#define RS 15 +#define BW 3 + +static double offset[RN] = { 0.0, 0.07612, 0.29289, 0.61732, 1.0}; + +static void rbox(int fill, int x, int y, int w, int h) { + int i; + int rsx ,rsy, rs; + rsx = w*2/5; rsy = h*2/5; + if (rsx > rsy) rs = rsy; else rs = rsx; + if (rs > RS) rs = RS; + rsx = rs; rsy = rs; + + if (fill) fl_begin_polygon(); else fl_begin_loop(); + for (i=0; i<RN; i++) + fl_vertex(x + offset[RN-i-1]*rsx, y + offset[i] * rsy); + for (i=0; i<RN; i++) + fl_vertex(x + offset[i]*rsx, y + h-1 - offset[RN-i-1] * rsy); + for (i=0; i<RN; i++) + fl_vertex(x + w-1 - offset[RN-i-1]*rsx, y + h-1 - offset[i] * rsy); + for (i=0; i<RN; i++) + fl_vertex(x + w-1 - offset[i]*rsx, y + offset[RN-i-1] * rsy); + if (fill) fl_end_polygon(); else fl_end_loop(); +} + +static void fl_rflat_box(int x, int y, int w, int h, Fl_Color c) { + fl_color(c); rbox(1, x, y, w, h); rbox(0, x, y, w, h); +} + +static void fl_rounded_frame(int x, int y, int w, int h, Fl_Color c) { + fl_color(c); rbox(0, x, y, w, h); +} + +static void fl_rounded_box(int x, int y, int w, int h, Fl_Color c) { + fl_color(c); rbox(1, x, y, w, h); + fl_color(FL_BLACK); rbox(0, x, y, w, h); +} + +static void fl_rshadow_box(int x, int y, int w, int h, Fl_Color c) { + // draw shadow: + fl_color(FL_DARK3); + rbox(1, x+BW, y+BW, w, h); + rbox(0, x+BW, y+BW, w, h); + // draw the box: + fl_rounded_box(x, y, w, h, c); +} + +extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*); + +Fl_Boxtype fl_define_FL_ROUNDED_BOX() { + fl_internal_boxtype(_FL_ROUNDED_FRAME, fl_rounded_frame); + fl_internal_boxtype(_FL_ROUNDED_BOX, fl_rounded_box); + return _FL_ROUNDED_BOX; +} + +Fl_Boxtype fl_define_FL_RFLAT_BOX() { + fl_internal_boxtype(_FL_RFLAT_BOX, fl_rflat_box); + return _FL_RFLAT_BOX; +} + +Fl_Boxtype fl_define_FL_RSHADOW_BOX() { + fl_internal_boxtype(_FL_RSHADOW_BOX, fl_rshadow_box); + return _FL_RSHADOW_BOX; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_scroll_area.cxx b/Utilities/FLTK/src/fl_scroll_area.cxx new file mode 100644 index 0000000000..ec32756591 --- /dev/null +++ b/Utilities/FLTK/src/fl_scroll_area.cxx @@ -0,0 +1,143 @@ +// +// "$Id$" +// +// Scrolling routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Drawing function to move the contents of a rectangle. This is passed +// a "callback" which is called to draw rectangular areas that are moved +// into the drawing area. + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#include <FL/x.H> + +// scroll a rectangle and redraw the newly exposed portions: +void fl_scroll(int X, int Y, int W, int H, int dx, int dy, + void (*draw_area)(void*, int,int,int,int), void* data) +{ + if (!dx && !dy) return; + if (dx <= -W || dx >= W || dy <= -H || dy >= H) { + // no intersection of old an new scroll + draw_area(data,X,Y,W,H); + return; + } + int src_x, src_w, dest_x, clip_x, clip_w; + if (dx > 0) { + src_x = X; + dest_x = X+dx; + src_w = W-dx; + clip_x = X; + clip_w = dx; + } else { + src_x = X-dx; + dest_x = X; + src_w = W+dx; + clip_x = X+src_w; + clip_w = W-src_w; + } + int src_y, src_h, dest_y, clip_y, clip_h; + if (dy > 0) { + src_y = Y; + dest_y = Y+dy; + src_h = H-dy; + clip_y = Y; + clip_h = dy; + } else { + src_y = Y-dy; + dest_y = Y; + src_h = H+dy; + clip_y = Y+src_h; + clip_h = H-src_h; + } +#ifdef WIN32 + BitBlt(fl_gc, dest_x, dest_y, src_w, src_h, fl_gc, src_x, src_y,SRCCOPY); + // NYI: need to redraw areas that the source of BitBlt was bad due to + // overlapped windows, probably similar to X version: + // MRS: basic code needs to redraw parts that scrolled from off-screen... + int temp, limit; + int wx, wy; + + // Compute the X position of the current window; + // this only works when scrolling in response to + // a user event; Fl_Window::x/y_root() do not work + // on WIN32... + wx = Fl::event_x_root() - Fl::event_x(); + wy = Fl::event_y_root() - Fl::event_y(); + + temp = wx + src_x; + if (temp < Fl::x()) { + draw_area(data, dest_x, dest_y, Fl::x() - temp, src_h); + } + temp = wx + src_x + src_w; + limit = Fl::x() + Fl::w(); + if (temp > limit) { + draw_area(data, dest_x + src_w - temp + limit, dest_y, temp - limit, src_h); + } + + temp = wy + src_y; + if (temp < Fl::y()) { + draw_area(data, dest_x, dest_y, src_w, Fl::y() - temp); + } + temp = wy + src_y + src_h; + limit = Fl::y() + Fl::h(); + if (temp > limit) { + draw_area(data, dest_x, dest_y + src_h - temp + limit, src_w, temp - limit); + } +#elif defined(__APPLE_QD__) + Rect src = { src_y, src_x, src_y+src_h, src_x+src_w }; + Rect dst = { dest_y, dest_x, dest_y+src_h, dest_x+src_w }; + static RGBColor bg = { 0xffff, 0xffff, 0xffff }; RGBBackColor( &bg ); + static RGBColor fg = { 0x0000, 0x0000, 0x0000 }; RGBForeColor( &fg ); + CopyBits( GetPortBitMapForCopyBits( GetWindowPort(fl_window) ), + GetPortBitMapForCopyBits( GetWindowPort(fl_window) ), &src, &dst, srcCopy, 0L); +#elif defined(__APPLE_QUARTZ__) + // warning: there does not seem to be an equivalent to this function in Quartz + Rect src = { src_y, src_x, src_y+src_h, src_x+src_w }; + Rect dst = { dest_y, dest_x, dest_y+src_h, dest_x+src_w }; + static RGBColor bg = { 0xffff, 0xffff, 0xffff }; RGBBackColor( &bg ); + static RGBColor fg = { 0x0000, 0x0000, 0x0000 }; RGBForeColor( &fg ); + CopyBits( GetPortBitMapForCopyBits( GetWindowPort(fl_window) ), + GetPortBitMapForCopyBits( GetWindowPort(fl_window) ), &src, &dst, srcCopy, 0L); +#else + XCopyArea(fl_display, fl_window, fl_window, fl_gc, + src_x, src_y, src_w, src_h, dest_x, dest_y); + // we have to sync the display and get the GraphicsExpose events! (sigh) + for (;;) { + XEvent e; XWindowEvent(fl_display, fl_window, ExposureMask, &e); + if (e.type == NoExpose) break; + // otherwise assumme it is a GraphicsExpose event: + draw_area(data, e.xexpose.x, e.xexpose.y, + e.xexpose.width, e.xexpose.height); + if (!e.xgraphicsexpose.count) break; + } +#endif + if (dx) draw_area(data, clip_x, dest_y, clip_w, src_h); + if (dy) draw_area(data, X, clip_y, W, clip_h); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_set_font.cxx b/Utilities/FLTK/src/fl_set_font.cxx new file mode 100644 index 0000000000..4cabe5e4c9 --- /dev/null +++ b/Utilities/FLTK/src/fl_set_font.cxx @@ -0,0 +1,88 @@ +// +// "$Id$" +// +// Font utilities for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Add a font to the internal table. +// Also see fl_set_fonts.cxx which adds all possible fonts. + +#include <FL/Fl.H> +#include <FL/x.H> +#include "flstring.h" +#include "Fl_Font.H" +#include <stdlib.h> + +static int table_size; + +void Fl::set_font(Fl_Font fnum, const char* name) { + while (fnum >= table_size) { + int i = table_size; + if (!i) { // don't realloc the built-in table + table_size = 2*FL_FREE_FONT; + i = FL_FREE_FONT; + Fl_Fontdesc* t = (Fl_Fontdesc*)malloc(table_size*sizeof(Fl_Fontdesc)); + memcpy(t, fl_fonts, FL_FREE_FONT*sizeof(Fl_Fontdesc)); + fl_fonts = t; + } else { + table_size = 2*table_size; + fl_fonts=(Fl_Fontdesc*)realloc(fl_fonts, table_size*sizeof(Fl_Fontdesc)); + } + for (; i < table_size; i++) { + fl_fonts[i].fontname[0] = 0; + fl_fonts[i].name = 0; +#if !defined(WIN32) && !defined(__APPLE__) + fl_fonts[i].xlist = 0; + fl_fonts[i].n = 0; +#endif // !WIN32 && !__APPLE__ + } + } + Fl_Fontdesc* s = fl_fonts+fnum; + if (s->name) { + if (!strcmp(s->name, name)) {s->name = name; return;} +#if !defined(WIN32) && !defined(__APPLE__) + if (s->xlist && s->n >= 0) XFreeFontNames(s->xlist); +#endif + for (Fl_FontSize* f = s->first; f;) { + Fl_FontSize* n = f->next; delete f; f = n; + } + s->first = 0; + } + s->name = name; + s->fontname[0] = 0; +#if !defined(WIN32) && !defined(__APPLE__) + s->xlist = 0; +#endif + s->first = 0; +} + +void Fl::set_font(Fl_Font fnum, Fl_Font from) { + Fl::set_font(fnum, get_font(from)); +} + +const char* Fl::get_font(Fl_Font fnum) {return fl_fonts[fnum].name;} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_set_fonts.cxx b/Utilities/FLTK/src/fl_set_fonts.cxx new file mode 100644 index 0000000000..2b407bdba8 --- /dev/null +++ b/Utilities/FLTK/src/fl_set_fonts.cxx @@ -0,0 +1,46 @@ +// +// "$Id$" +// +// More font utilities for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/x.H> +#include "Fl_Font.H" +#include "flstring.h" +#include <stdlib.h> + +#ifdef WIN32 +# include "fl_set_fonts_win32.cxx" +#elif defined(__APPLE__) +# include "fl_set_fonts_mac.cxx" +#elif USE_XFT +# include "fl_set_fonts_xft.cxx" +#else +# include "fl_set_fonts_x.cxx" +#endif // WIN32 + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_set_fonts_mac.cxx b/Utilities/FLTK/src/fl_set_fonts_mac.cxx new file mode 100644 index 0000000000..1195a5f770 --- /dev/null +++ b/Utilities/FLTK/src/fl_set_fonts_mac.cxx @@ -0,0 +1,214 @@ +// +// "$Id$" +// +// MacOS font utilities for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +// This function fills in the fltk font table with all the fonts that +// are found on the X server. It tries to place the fonts into families +// and to sort them so the first 4 in a family are normal, bold, italic, +// and bold italic. + +// Bug: older versions calculated the value for *ap as a side effect of +// making the name, and then forgot about it. To avoid having to change +// the header files I decided to store this value in the last character +// of the font name array. +#define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1 + +// turn a stored font name into a pretty name: +const char* Fl::get_font_name(Fl_Font fnum, int* ap) { +#ifdef __APPLE_QD__ + Fl_Fontdesc *f = fl_fonts + fnum; + if (!f->fontname[0]) { + const char* p = f->name; + if (!p || !*p) {if (ap) *ap = 0; return "";} + int type; + switch (*p) { + case 'B': type = FL_BOLD; break; + case 'I': type = FL_ITALIC; break; + case 'P': type = FL_BOLD | FL_ITALIC; break; + default: type = 0; break; + } + strlcpy(f->fontname, p+1, ENDOFBUFFER); + if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER); + if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER); + f->fontname[ENDOFBUFFER] = (char)type; + } + if (ap) *ap = f->fontname[ENDOFBUFFER]; + return f->fontname; +#elif defined(__APPLE_QUARTZ__) + Fl_Fontdesc *f = fl_fonts + fnum; + if (!f->fontname[0]) { + const char* p = f->name; + if (!p || !*p) {if (ap) *ap = 0; return "";} + strlcpy(f->fontname, p, ENDOFBUFFER); + int type = 0; + if (strstr(f->name, "Bold")) type |= FL_BOLD; + if (strstr(f->name, "Italic")) type |= FL_ITALIC; + f->fontname[ENDOFBUFFER] = (char)type; + } + if (ap) *ap = f->fontname[ENDOFBUFFER]; + return f->fontname; +#endif +} + +static int fl_free_font = FL_FREE_FONT; + +Fl_Font Fl::set_fonts(const char* xstarname) { +#pragma unused ( xstarname ) +#ifdef __APPLE_QD__ + if (fl_free_font != FL_FREE_FONT) + return (Fl_Font)fl_free_font; + static char styleLU[] = " BIP"; + FMFontFamilyInstanceIterator ffiIterator; + FMFontFamilyIterator ffIterator; + FMFontFamily family; + FMFont font; + FMFontStyle style; // bits 0..6: bold, italic underline, outline, shadow, condens, extended (FLTK supports 0 and 1 ) + FMFontSize size; + //FMFilter filter; // do we need to set a specific (or multiple) filter(s) to get ALL fonts? + + Str255 buf; + //filter.format = kFMCurrentFilterFormat; + //filter.selector = kFMGenerationFilterSelector; + //filter.filter.generationFilter = + FMCreateFontFamilyIterator( NULL, NULL, kFMUseGlobalScopeOption, &ffIterator ); + OSStatus listFamilies, listInstances; + for (;;) + { + listFamilies = FMGetNextFontFamily( &ffIterator, &family ); + if ( listFamilies != 0 ) break; + FMGetFontFamilyName( family, buf ); + buf[ buf[0]+1 ] = 0; + //printf( "Font Family: %s\n", buf+1 ); + int i; + for (i=0; i<FL_FREE_FONT; i++) // skip if one of our built-in fonts + if (!strcmp(Fl::get_font_name((Fl_Font)i),(char*)buf+1)) break; + if ( i < FL_FREE_FONT ) continue; + FMCreateFontFamilyInstanceIterator( family, &ffiIterator ); + char pStyle = 0, nStyle; + for (;;) + { + listInstances = FMGetNextFontFamilyInstance( &ffiIterator, &font, &style, &size ); + if ( listInstances != 0 ) break; + // printf(" %d %d %d\n", font, style, size ); + nStyle = styleLU[style&0x03]; + if ( ( pStyle & ( 1<<(style&0x03) ) ) == 0 ) + { + buf[0] = nStyle; + Fl::set_font((Fl_Font)(fl_free_font++), strdup((char*)buf)); + pStyle |= ( 1<<(style&0x03) ); + } + } + FMDisposeFontFamilyInstanceIterator( &ffiIterator ); + } + FMDisposeFontFamilyIterator( &ffIterator ); + return (Fl_Font)fl_free_font; +#elif defined(__APPLE_QUARTZ__) + ATSFontIterator it; + ATSFontIteratorCreate(kATSFontContextGlobal, 0L, 0L, kATSOptionFlagsRestrictedScope, &it); + for (;;) { + ATSFontRef font; + CFStringRef fname = 0; + OSStatus err = ATSFontIteratorNext(it, &font); + if (err!=noErr) break; + ATSFontGetName(font, kATSOptionFlagsDefault, &fname); + char buf[1024]; + CFStringGetCString(fname, buf, 1024, kCFStringEncodingASCII); + int i; + for (i=0; i<FL_FREE_FONT; i++) // skip if one of our built-in fonts + if (!strcmp(Fl::get_font_name((Fl_Font)i),buf)) break; + if ( i < FL_FREE_FONT ) continue; + Fl::set_font((Fl_Font)(fl_free_font++), strdup((char*)buf)); + } + ATSFontIteratorRelease(&it); + return (Fl_Font)fl_free_font; +#endif +} + +static int array[128]; +int Fl::get_font_sizes(Fl_Font fnum, int*& sizep) { + Fl_Fontdesc *s = fl_fonts+fnum; + if (!s->name) s = fl_fonts; // empty slot in table, use entry 0 + int cnt = 0; + +#ifdef __APPLE_QD__ + Str255 name; + int len = strlen( s->name ); + memcpy(((char*)name)+1, s->name+1, len ); + name[0] = len-1; + FMFontFamily family = FMGetFontFamilyFromName( name ); + if ( family == kInvalidFontFamily ) return 0; + + sizep = array; + FMFont font; + FMFontStyle style, fStyle; + switch ( s->name[0] ) { + default : + fStyle=0; + break; + case 'B' : + fStyle=1; + break; + case 'I' : + fStyle=2; + break; + case 'P' : + fStyle=3; + break; + } + FMFontSize size, pSize = -1; + FMFontFamilyInstanceIterator ffiIterator; + FMCreateFontFamilyInstanceIterator( family, &ffiIterator ); + OSStatus listInstances; + for (;;) + { + listInstances = FMGetNextFontFamilyInstance( &ffiIterator, &font, &style, &size ); + if ( listInstances != 0 ) break; + if ( style==fStyle ) + { + if ( size>pSize ) + { + array[ cnt++ ] = size; + pSize = size; + } + } + } + FMDisposeFontFamilyInstanceIterator( &ffiIterator ); +#elif defined(__APPLE_QUARTZ__) + // ATS supports all font size + array[0] = 0; + sizep = array; + cnt = 1; +#endif + + return cnt; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_set_fonts_win32.cxx b/Utilities/FLTK/src/fl_set_fonts_win32.cxx new file mode 100755 index 0000000000..449bb6314a --- /dev/null +++ b/Utilities/FLTK/src/fl_set_fonts_win32.cxx @@ -0,0 +1,149 @@ +// +// "$Id$" +// +// WIN32 font utilities for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this7 library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// This function fills in the FLTK font table with all the fonts that +// are found on the X server. It tries to place the fonts into families +// and to sort them so the first 4 in a family are normal, bold, italic, +// and bold italic. + +// Bug: older versions calculated the value for *ap as a side effect of +// making the name, and then forgot about it. To avoid having to change +// the header files I decided to store this value in the last character +// of the font name array. +#define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1 + +// turn a stored font name into a pretty name: +const char* Fl::get_font_name(Fl_Font fnum, int* ap) { + Fl_Fontdesc *f = fl_fonts + fnum; + if (!f->fontname[0]) { + const char* p = f->name; + if (!p || !*p) {if (ap) *ap = 0; return "";} + int type; + switch (*p) { + case 'B': type = FL_BOLD; break; + case 'I': type = FL_ITALIC; break; + case 'P': type = FL_BOLD | FL_ITALIC; break; + default: type = 0; break; + } + strlcpy(f->fontname, p+1, ENDOFBUFFER); + if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER); + if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER); + f->fontname[ENDOFBUFFER] = (char)type; + } + if (ap) *ap = f->fontname[ENDOFBUFFER]; + return f->fontname; +} + +static int fl_free_font = FL_FREE_FONT; + +static int CALLBACK +enumcb(CONST LOGFONT *lpelf, + CONST TEXTMETRIC * /*lpntm*/, + DWORD /*FontType*/, + LPARAM p) { + if (!p && lpelf->lfCharSet != ANSI_CHARSET) return 1; + const char *n = lpelf->lfFaceName; + for (int i=0; i<FL_FREE_FONT; i++) // skip if one of our built-in fonts + if (!strcmp(Fl::get_font_name((Fl_Font)i),n)) return 1; + char buffer[LF_FACESIZE + 1]; + strcpy(buffer+1, n); + buffer[0] = ' '; Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer)); + if (lpelf->lfWeight <= 400) + buffer[0] = 'B', Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer)); + buffer[0] = 'I'; Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer)); + if (lpelf->lfWeight <= 400) + buffer[0] = 'P', Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer)); + return 1; +} + +Fl_Font Fl::set_fonts(const char* xstarname) { + if (fl_free_font == FL_FREE_FONT) {// if not already been called + if (!fl_gc) fl_GetDC(0); + EnumFontFamilies(fl_gc, NULL, (FONTENUMPROC)enumcb, xstarname != 0); + } + return (Fl_Font)fl_free_font; +} + + +static int nbSize; +static int cyPerInch; +static int sizes[128]; + +static int CALLBACK +EnumSizeCb(CONST LOGFONT * /*lpelf*/, + CONST TEXTMETRIC *lpntm, + DWORD fontType, + LPARAM /*p*/) { + if ((fontType & RASTER_FONTTYPE) == 0) { + sizes[0] = 0; + nbSize = 1; + + // Scalable font + return 0; + } + + int add = lpntm->tmHeight - lpntm->tmInternalLeading; + add = MulDiv(add, 72, cyPerInch); + + int start = 0; + while ((start < nbSize) && (sizes[start] < add)) { + start++; + } + + if ((start < nbSize) && (sizes[start] == add)) { + return 1; + } + + for (int i=nbSize; i>start; i--) sizes[i] = sizes[i - 1]; + + sizes[start] = add; + nbSize++; + + // Stop enum if buffer overflow + return nbSize < 128; +} + + +int +Fl::get_font_sizes(Fl_Font fnum, int*& sizep) { + nbSize = 0; + Fl_Fontdesc *s = fl_fonts+fnum; + if (!s->name) s = fl_fonts; // empty slot in table, use entry 0 + + if (!fl_gc) fl_GetDC(0); + cyPerInch = GetDeviceCaps(fl_gc, LOGPIXELSY); + if (cyPerInch < 1) cyPerInch = 1; + EnumFontFamilies(fl_gc, s->name+1, (FONTENUMPROC)EnumSizeCb, 0); + + sizep = sizes; + return nbSize; +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_set_fonts_x.cxx b/Utilities/FLTK/src/fl_set_fonts_x.cxx new file mode 100644 index 0000000000..9c785167c2 --- /dev/null +++ b/Utilities/FLTK/src/fl_set_fonts_x.cxx @@ -0,0 +1,350 @@ +// +// "$Id$" +// +// X11 font utilities for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// This function fills in the fltk font table with all the fonts that +// are found on the X server. It tries to place the fonts into families +// and to sort them so the first 4 in a family are normal, bold, italic, +// and bold italic. + +// Standard X fonts are matched by a pattern that is always of +// this form, and this pattern is put in the table: +// "-*-family-weight-slant-width1-style-*-registry-encoding" + +// Non-standard font names (those not starting with '-') are matched +// by a pattern of the form "prefix*suffix", where the '*' is where +// fltk thinks the point size is, or by the actual font name if no +// point size is found. + +// Fltk knows how to pull an "attribute" out of a font name, such as +// bold or italic, by matching known x font field values. All words +// that don't match a known attribute are combined into the "name" +// of the font. Names are compared before attributes for sorting, this +// makes the bold and plain version of a font come out next to each +// other despite the poor X font naming scheme. + +// By default fl_set_fonts() only does iso8859-1 encoded fonts. You can +// do all normal X fonts by passing "-*" or every possible font with "*". + +// Fl::set_font will take strings other than the ones this stores +// and can identify any font on X that way. You may want to write your +// own system of font management and not use this code. + +// turn word N of a X font name into either some attribute bits +// (right now 0, FL_BOLD, or FL_ITALIC), or into -1 indicating that +// the word should be put into the name: + +static int attribute(int n, const char *p) { + // don't put blank things into name: + if (!*p || *p=='-' || *p=='*') return 0; + if (n == 3) { // weight + if (!strncmp(p,"normal",6) || + !strncmp(p,"light",5) || + !strncmp(p,"medium",6) || + !strncmp(p,"book",4)) return 0; + if (!strncmp(p,"bold",4) || !strncmp(p,"demi",4)) return FL_BOLD; + } else if (n == 4) { // slant + if (*p == 'r') return 0; + if (*p == 'i' || *p == 'o') return FL_ITALIC; + } else if (n == 5) { // sWidth + if (!strncmp(p,"normal",6)) return 0; + } + return -1; +} + +// return non-zero if the registry-encoding should be used: +extern const char* fl_encoding; +static int use_registry(const char *p) { + return *p && *p!='*' && strcmp(p,fl_encoding); +} + +// Bug: older versions calculated the value for *ap as a side effect of +// making the name, and then forgot about it. To avoid having to change +// the header files I decided to store this value in the last character +// of the font name array. +#define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1 + +// turn a stored (with *'s) X font name into a pretty name: +const char* Fl::get_font_name(Fl_Font fnum, int* ap) { + Fl_Fontdesc *f = fl_fonts + fnum; + if (!f->fontname[0]) { + int type = 0; + const char* p = f->name; + if (!p) { + if (ap) *ap = 0; + return ""; + } + char *o = f->fontname; + + if (*p != '-') { // non-standard font, just replace * with spaces: + if (strstr(p,"bold")) type = FL_BOLD; + if (strstr(p,"ital")) type |= FL_ITALIC; + for (;*p; p++) { + if (*p == '*' || *p == ' ' || *p == '-') { + do p++; while (*p == '*' || *p == ' ' || *p == '-'); + if (!*p) break; + if (o < (f->fontname + ENDOFBUFFER - 1)) *o++ = ' '; + } + if (o < (f->fontname + ENDOFBUFFER - 1)) *o++ = *p; + } + *o = 0; + + } else { // standard dash-seperated font: + + // get the family: + const char *x = fl_font_word(p,2); if (*x) x++; if (*x=='*') x++; + if (!*x) { + if (ap) *ap = 0; + return p; + } + const char *e = fl_font_word(x,1); + if ((e - x) < (int)(ENDOFBUFFER - 1)) { + // MRS: we want strncpy here, not strlcpy... + strncpy(o,x,e-x); + o += e-x; + } else { + strlcpy(f->fontname, x, ENDOFBUFFER); + o = f->fontname+ENDOFBUFFER-1; + } + + // collect all the attribute words: + for (int n = 3; n <= 6; n++) { + // get the next word: + if (*e) e++; x = e; e = fl_font_word(x,1); + int t = attribute(n,x); + if (t < 0) { + if (o < (f->fontname + ENDOFBUFFER - 1)) *o++ = ' '; + if ((e - x) < (int)(ENDOFBUFFER - (o - f->fontname) - 1)) { + // MRS: we want strncpy here, not strlcpy... + strncpy(o,x,e-x); + o += e-x; + } else { + strlcpy(o,x, ENDOFBUFFER - (o - f->fontname) - 1); + o = f->fontname+ENDOFBUFFER-1; + } + } else type |= t; + } + + // skip over the '*' for the size and get the registry-encoding: + x = fl_font_word(e,2); + if (*x) {x++; *o++ = '('; while (*x) *o++ = *x++; *o++ = ')';} + + *o = 0; + if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER); + if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER); + } + f->fontname[ENDOFBUFFER] = (char)type; + } + if (ap) *ap = f->fontname[ENDOFBUFFER]; + return f->fontname; +} + +extern "C" { +// sort raw (non-'*') X font names into perfect order: + +static int ultrasort(const void *aa, const void *bb) { + const char *a = *(char **)aa; + const char *b = *(char **)bb; + + // sort all non x-fonts at the end: + if (*a != '-') { + if (*b == '-') return 1; + // 2 non-x fonts are matched by "numeric sort" + int ret = 0; + for (;;) { + if (isdigit(*a) && isdigit(*b)) { + int na = strtol(a, (char **)&a, 10); + int nb = strtol(b, (char **)&b, 10); + if (!ret) ret = na-nb; + } else if (*a != *b) { + return (*a-*b); + } else if (!*a) { + return ret; + } else { + a++; b++; + } + } + } else { + if (*b != '-') return -1; + } + + // skip the foundry (assumme equal): + for (a++; *a && *a++!='-';); + for (b++; *b && *b++!='-';); + + // compare the family and all the attribute words: + int atype = 0; + int btype = 0; + for (int n = 2; n <= 6; n++) { + int at = attribute(n,a); + int bt = attribute(n,b); + if (at < 0) { + if (bt >= 0) return 1; + for (;;) {if (*a!=*b) return *a-*b; b++; if (!*a || *a++=='-') break;} + } else { + if (bt < 0) return -1; + a = fl_font_word(a,1); if (*a) a++; + b = fl_font_word(b,1); if (*b) b++; + atype |= at; btype |= bt; + } + } + + // remember the pixel size: + int asize = atoi(a); + int bsize = atoi(b); + + // compare the registry/encoding: + a = fl_font_word(a,6); if (*a) a++; + b = fl_font_word(b,6); if (*b) b++; + if (use_registry(a)) { + if (!use_registry(b)) return 1; + int r = strcmp(a,b); if (r) return r; + } else { + if (use_registry(b)) return -1; + } + + if (atype != btype) return atype-btype; + if (asize != bsize) return asize-bsize; + + // something wrong, just do a string compare... + return strcmp(*(char**)aa, *(char**)bb); +} +} + +// converts a X font name to a standard starname, returns point size: +static int to_canonical(char *to, const char *from, size_t tolen) { + char* c = fl_find_fontsize((char*)from); + if (!c) return -1; // no point size found... + const char* endptr; + int size = strtol(c,(char**)&endptr,10); + if (from[0] == '-') { + // replace the "foundry" with -*-: + *to++ = '-'; *to++ = '*'; + for (from++; *from && *from != '-'; from++); + // skip to the registry-encoding: + endptr = (char*)fl_font_word(endptr,6); + if (*endptr && !use_registry(endptr+1)) endptr = ""; + } + int n = c-from; + // MRS: we want strncpy here, not strlcpy... + if (n > (int)(tolen - 1)) return -1; + strncpy(to,from,n); + to[n++] = '*'; + strlcpy(to+n,endptr, tolen - n); + return size; +} + +static int fl_free_font = FL_FREE_FONT; + +Fl_Font Fl::set_fonts(const char* xstarname) { + if (fl_free_font > FL_FREE_FONT) // already been here + return (Fl_Font)fl_free_font; + fl_open_display(); + int xlistsize; + char buf[20]; + if (!xstarname) { + strcpy(buf,"-*-"); strcpy(buf+3,fl_encoding); + xstarname = buf; + } + char **xlist = XListFonts(fl_display, xstarname, 10000, &xlistsize); + if (!xlist) return (Fl_Font)fl_free_font; + qsort(xlist, xlistsize, sizeof(*xlist), ultrasort); + int used_xlist = 0; + for (int i=0; i<xlistsize;) { + int first_xlist = i; + const char *p = xlist[i++]; + char canon[1024]; + int size = to_canonical(canon, p, sizeof(canon)); + if (size >= 0) { + for (;;) { // find all matching fonts: + if (i >= xlistsize) break; + const char *q = xlist[i]; + char this_canon[1024]; + if (to_canonical(this_canon, q, sizeof(this_canon)) < 0) break; + if (strcmp(canon, this_canon)) break; + i++; + } + /*if (*p=='-' || i > first_xlist+1)*/ p = canon; + } + int j; + for (j = 0;; j++) { + if (j < FL_FREE_FONT) { + // see if it is one of our built-in fonts: + // if so, set the list of x fonts, since we have it anyway + if (fl_fonts[j].name && !strcmp(fl_fonts[j].name, p)) break; + } else { + j = fl_free_font++; + if (p == canon) p = strdup(p); else used_xlist = 1; + Fl::set_font((Fl_Font)j, p); + break; + } + } + if (!fl_fonts[j].xlist) { + fl_fonts[j].xlist = xlist+first_xlist; + fl_fonts[j].n = -(i-first_xlist); + used_xlist = 1; + } + } + if (!used_xlist) XFreeFontNames(xlist); + return (Fl_Font)fl_free_font; +} + +int Fl::get_font_sizes(Fl_Font fnum, int*& sizep) { + Fl_Fontdesc *s = fl_fonts+fnum; + if (!s->name) s = fl_fonts; // empty slot in table, use entry 0 + if (!s->xlist) { + fl_open_display(); + s->xlist = XListFonts(fl_display, s->name, 100, &(s->n)); + if (!s->xlist) return 0; + } + int listsize = s->n; if (listsize<0) listsize = -listsize; + static int sizes[128]; + int numsizes = 0; + for (int i = 0; i < listsize; i++) { + char *q = s->xlist[i]; + char *d = fl_find_fontsize(q); + if (!d) continue; + int s = strtol(d,0,10); + if (!numsizes || sizes[numsizes-1] < s) { + sizes[numsizes++] = s; + } else { + // insert-sort the new size into list: + int n; + for (n = numsizes-1; n > 0; n--) if (sizes[n-1] < s) break; + if (sizes[n] != s) { + for (int m = numsizes; m > n; m--) sizes[m] = sizes[m-1]; + sizes[n] = s; + numsizes++; + } + } + } + sizep = sizes; + return numsizes; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_set_fonts_xft.cxx b/Utilities/FLTK/src/fl_set_fonts_xft.cxx new file mode 100644 index 0000000000..a6cf89cf17 --- /dev/null +++ b/Utilities/FLTK/src/fl_set_fonts_xft.cxx @@ -0,0 +1,361 @@ +// +// "$Id$" +// +// More font utilities for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <X11/Xft/Xft.h> + +// This function fills in the fltk font table with all the fonts that +// are found on the X server. It tries to place the fonts into families +// and to sort them so the first 4 in a family are normal, bold, italic, +// and bold italic. + +// Bug: older versions calculated the value for *ap as a side effect of +// making the name, and then forgot about it. To avoid having to change +// the header files I decided to store this value in the last character +// of the font name array. +#define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1 + +// turn a stored font name into a pretty name: +const char* Fl::get_font_name(Fl_Font fnum, int* ap) { + Fl_Fontdesc *f = fl_fonts + fnum; + if (!f->fontname[0]) { + const char* p = f->name; + int type; + switch (p[0]) { + case 'B': type = FL_BOLD; break; + case 'I': type = FL_ITALIC; break; + case 'P': type = FL_BOLD | FL_ITALIC; break; + default: type = 0; break; + } + + // NOTE: This can cause duplications in fonts that already have Bold or Italic in + // their "name". Maybe we need to find a cleverer way? + strlcpy(f->fontname, p+1, ENDOFBUFFER); + if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER); + if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER); + f->fontname[ENDOFBUFFER] = (char)type; + } + if (ap) *ap = f->fontname[ENDOFBUFFER]; + return f->fontname; +} + +/////////////////////////////////////////////////////////// +#define LOCAL_RAW_NAME_MAX 256 + +extern "C" { +// sort returned fontconfig font names +static int name_sort(const void *aa, const void *bb) { + // What should we do here? Just do a string compare for now... + // NOTE: This yeilds some oddities - in particular a Blah Bold font will be + // listed before Blah... + // Also - the fontconfig listing returns some faces that are effectively duplicates + // as far as fltk is concerned, e.g. where there are ko or ja variants that we + // can't distinguish (since we are not yet fully UTF-*) - should we strip them here? + return strcasecmp(*(char**)aa, *(char**)bb); +} // end of name_sort +} // end of extern C section + + +// Read the "pretty" name we have derived from fontconfig then convert +// it into the format fltk uses internally for Xft names... +// This is just a mess - I should have tokenised the strings and gone from there, +// but I really thought this would be easier! +static void make_raw_name(char *raw, char *pretty) +{ + // Input name will be "Some Name:style = Bold Italic" or whatever + // The plan is this: + // - the first char in the "raw" name becomes either I, B, P or " " for + // italic, bold, bold italic or normal - this seems to be the fltk way... + + char *style = strchr(pretty, ':'); + char *last = style + strlen(style) - 2; + + if (style) + { + *style = 0; // Terminate "name" string + style ++; // point to start of style section + } + raw[0] = ' '; raw[1] = 0; // Default start of "raw name" text + strncat(raw, pretty, LOCAL_RAW_NAME_MAX); + // At this point, the name is "marked" as regular... + if (style) + { +#define PLAIN 0 +#define BOLD 1 +#define ITALIC 2 +#define BITALIC (BOLD | ITALIC) + int mods = PLAIN; + // Now try and parse the style string - look for the "=" sign + style = strchr(style, '='); + while ((style) && (style < last)) + { + int type; + while ((*style == '=') || (*style == ' ') || (*style == '\t')) + { + style++; // Start of Style string + if ((style >= last) || (*style == 0)) continue; + } + type = toupper(style[0]); + switch (type) + { + // Things we might see: Regular Normal Bold Italic Oblique (??what??) Medium + // Roman Light Demi Sans SemiCondensed SuperBold Book... etc... + // Things we actually care about: Bold Italic Oblique SuperBold - Others??? + case 'I': + if (strncasecmp(style, "Italic", 6) == 0) + { + mods |= ITALIC; + } + goto NEXT_STYLE; + + case 'B': + if (strncasecmp(style, "Bold", 4) == 0) + { + mods |= BOLD; + } + goto NEXT_STYLE; + + case 'O': + if (strncasecmp(style, "Oblique", 7) == 0) + { + mods |= ITALIC; + } + goto NEXT_STYLE; + + case 's': + if (strncasecmp(style, "SuperBold", 9) == 0) + { + mods |= BOLD; + } + goto NEXT_STYLE; + + default: // find the next gap + goto NEXT_STYLE; + } // switch end +NEXT_STYLE: + while ((*style != ' ') && (*style != '\t')) + { + style++; + if ((style >= last) || (*style == 0)) goto STYLE_DONE; + } + } +STYLE_DONE: + // Set the "modifier" character in the raw string + switch(mods) + { + case BOLD: raw[0] = 'B'; + break; + case ITALIC: raw[0] = 'I'; + break; + case BITALIC: raw[0] = 'P'; + break; + default: raw[0] = ' '; + break; + } + } +} // make_raw_name + +/////////////////////////////////////////////////////////// + +static int fl_free_font = FL_FREE_FONT; + +// Uses the fontconfig lib to construct a list of all installed fonts. +// I tried using XftListFonts for this, but the API is tricky - and when I looked +// at the XftList* code, it calls the Fc* functions anyway... so... +// Also, for now I'm ignoring the "pattern_name" and just getting everything... +// AND I don't try and skip the fonts we've already loaded in the defaults. +// Blimey! What a hack! +Fl_Font Fl::set_fonts(const char* pattern_name) +{ + FcFontSet *fnt_set; // Will hold the list of fonts we find + FcPattern *fnt_pattern; // Holds the generic "match all names" pattern + FcObjectSet *fnt_obj_set = 0; // Holds the generic "match all objects" + + int j; // loop iterator variable + int font_count; // Total number of fonts found to process + char **full_list; // The list of font names we build + + if (fl_free_font > FL_FREE_FONT) // already been here + return (Fl_Font)fl_free_font; + + fl_open_display(); // Just in case... + + // Make sure fontconfig is ready... is this necessary? The docs say it is + // safe to call it multiple times, so just go for it anyway! + if (!FcInit ()) + { + // What to do? Just return defaults... + return FL_FREE_FONT; + } + + // Create a search pattern that will match every font name - I think this does the + // Right Thing... but am not certain... + // This could possibly be "enhanced" to pay attention to the requested "pattern_name"? + fnt_pattern = FcPatternCreate (); + fnt_obj_set = FcObjectSetBuild (FC_FAMILY, FC_STYLE, 0); + + // Hopefully, this is a set of all the fonts... + fnt_set = FcFontList (0, fnt_pattern, fnt_obj_set); + + // We don't need the fnt_pattern any more, release it + FcPatternDestroy (fnt_pattern); + + // Now, if we got any fonts, iterate through them... + if (fnt_set) + { + char *stop; + char *start; + char *first; + + font_count = fnt_set->nfont; // How many fonts? + + // Allocate array of char*'s to hold the name strings + full_list = (char **)malloc(sizeof(char *) * font_count); + + // iterate through all the font patterns and get the names out... + for (j = 0; j < font_count; j++) + { + // NOTE: FcChar8 is a typedef of "unsigned char"... + FcChar8 *font; // String to hold the font's name + + // Convert from fontconfig internal pattern to human readable name + // NOTE: This WILL malloc storage, so we need to free it later... + font = FcNameUnparse (fnt_set->fonts[j]); + + // The returned strings look like this... + // Century Schoolbook:style=Bold Italic,fed kursiv,Fett Kursiv,... + // So the bit we want is up to the first comma - BUT some strings have + // more than one name, separated by, guess what?, a comma... + stop = start = first = 0; + stop = strchr((const char *)font, ','); + start = strchr((const char *)font, ':'); + if ((stop) && (start) && (stop < start)) + { + first = stop + 1; // discard first version of name + // find first comma *after* the end of the name + stop = strchr((const char *)start, ','); + } + else + { + first = (char *)font; // name is just what was returned + } + // Truncate the name after the (english) modifiers description + if (stop) + { + *stop = 0; // Terminate the string at the first comma, if there is one + } + + // Copy the font description into our list + if (first == (char *)font) + { // The listed name is still OK + full_list[j] = (char *)font; + } + else + { // The listed name has been modified + full_list[j] = strdup(first); + // Free the font name storage + free (font); + } + // replace "style=Regular" so strcmp sorts it first + if (start) { + char *reg = strstr(full_list[j], "=Regular"); + if (reg) reg[1]='.'; + } + } + + // Release the fnt_set - we don't need it any more + FcFontSetDestroy (fnt_set); + + // Sort the list into alphabetic order + qsort(full_list, font_count, sizeof(*full_list), name_sort); + + // Now let us add the names we got to fltk's font list... + for (j = 0; j < font_count; j++) + { + if (full_list[j]) + { + char xft_name[LOCAL_RAW_NAME_MAX]; + char *stored_name; + // Parse the strings into FLTK-XFT style.. + make_raw_name(xft_name, full_list[j]); + // NOTE: This just adds on AFTER the default fonts - no attempt is made + // to identify already loaded fonts. Is this bad? + stored_name = strdup(xft_name); + Fl::set_font((Fl_Font)(j + FL_FREE_FONT), stored_name); + fl_free_font ++; + + free(full_list[j]); // release that name from our internal array + } + } + // Now we are done with the list, release it fully + free (full_list); + } + return (Fl_Font)fl_free_font; +} // ::set_fonts +//////////////////////////////////////////////////////////////// + + +extern "C" { +static int int_sort(const void *aa, const void *bb) { + return (*(int*)aa)-(*(int*)bb); +} +} + +//////////////////////////////////////////////////////////////// + +// Return all the point sizes supported by this font: +// Suprisingly enough Xft works exactly like fltk does and returns +// the same list. Except there is no way to tell if the font is scalable. +int Fl::get_font_sizes(Fl_Font fnum, int*& sizep) { + Fl_Fontdesc *s = fl_fonts+fnum; + if (!s->name) s = fl_fonts; // empty slot in table, use entry 0 + + fl_open_display(); + XftFontSet* fs = XftListFonts(fl_display, fl_screen, + XFT_FAMILY, XftTypeString, s->name+1, 0, + XFT_PIXEL_SIZE, 0); + static int* array = 0; + static int array_size = 0; + if (fs->nfont >= array_size) { + delete[] array; + array = new int[array_size = fs->nfont+1]; + } + array[0] = 0; int j = 1; // claim all fonts are scalable + for (int i = 0; i < fs->nfont; i++) { + double v; + if (XftPatternGetDouble(fs->fonts[i], XFT_PIXEL_SIZE, 0, &v) == XftResultMatch) { + array[j++] = int(v); + } + } + qsort(array+1, j-1, sizeof(int), int_sort); + XftFontSetDestroy(fs); + sizep = array; + return j; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_shadow_box.cxx b/Utilities/FLTK/src/fl_shadow_box.cxx new file mode 100644 index 0000000000..691c72971c --- /dev/null +++ b/Utilities/FLTK/src/fl_shadow_box.cxx @@ -0,0 +1,56 @@ +// +// "$Id$" +// +// Shadow box drawing routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/fl_draw.H> + +#define BW 3 + +static void fl_shadow_frame(int x, int y, int w, int h, Fl_Color c) { + fl_color(FL_DARK3); + fl_rectf(x+BW, y+h-BW, w - BW, BW); + fl_rectf(x+w-BW, y+BW, BW, h - BW); + fl_color(c); + fl_rect(x,y,w-BW,h-BW); +} + +static void fl_shadow_box(int x, int y, int w, int h, Fl_Color c) { + fl_color(c); + fl_rectf(x+1,y+1,w-2-BW,h-2-BW); + fl_shadow_frame(x,y,w,h,FL_GRAY0); +} + +extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*); +Fl_Boxtype fl_define_FL_SHADOW_BOX() { + fl_internal_boxtype(_FL_SHADOW_FRAME, fl_shadow_frame); + fl_internal_boxtype(_FL_SHADOW_BOX, fl_shadow_box); + return _FL_SHADOW_BOX; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_shortcut.cxx b/Utilities/FLTK/src/fl_shortcut.cxx new file mode 100644 index 0000000000..69e11ede5a --- /dev/null +++ b/Utilities/FLTK/src/fl_shortcut.cxx @@ -0,0 +1,221 @@ +// +// "$Id$" +// +// Shortcut support routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Code to test and parse fltk shortcut numbers. +// +// A shortcut is a keysym or'd with shift flags. In the simplest +// sense a shortcut is matched if the shift state is exactly as +// given and the key returning that keysym is pressed. +// +// To make it easier to match some things it is more complex: +// +// Only FL_META, FL_ALT, FL_SHIFT, and FL_CTRL must be "off". A +// zero in the other shift flags indicates "dont care". +// +// It also checks against the first character of Fl::event_text(), +// and zero for FL_SHIFT means "don't care". +// This allows punctuation shortcuts like "#" to work (rather than +// calling it "shift+3") + +#include <FL/Fl.H> +#include <FL/Fl_Widget.H> +#include <FL/Fl_Button.H> +#include <FL/fl_draw.H> +#include <ctype.h> +#include "flstring.h" +#if !defined(WIN32) && !defined(__APPLE__) +#include <FL/x.H> +#endif + +int Fl::test_shortcut(int shortcut) { + if (!shortcut) return 0; + + int v = shortcut & 0xffff; + if (v > 32 && v < 0x7f || v > 0xa0 && v <= 0xff) { + if (isupper(v)) { + shortcut |= FL_SHIFT; + } + } + + int shift = Fl::event_state(); + // see if any required shift flags are off: + if ((shortcut&shift) != (shortcut&0x7fff0000)) return 0; + // record shift flags that are wrong: + int mismatch = (shortcut^shift)&0x7fff0000; + // these three must always be correct: + if (mismatch&(FL_META|FL_ALT|FL_CTRL)) return 0; + + int key = shortcut & 0xffff; + + // if shift is also correct, check for exactly equal keysyms: + if (!(mismatch&(FL_SHIFT)) && key == Fl::event_key()) return 1; + + // try matching ascii, ignore shift: + if (key == event_text()[0]) return 1; + + // kludge so that Ctrl+'_' works (as opposed to Ctrl+'^_'): + if ((shift&FL_CTRL) && key >= 0x3f && key <= 0x5F + && event_text()[0]==(key^0x40)) return 1; + return 0; +} + +#if defined(WIN32) || defined(__APPLE__) // if not X +// This table must be in numeric order by fltk (X) keysym number: +struct Keyname {int key; const char* name;}; +static Keyname table[] = { + {' ', "Space"}, + {FL_BackSpace, "Backspace"}, + {FL_Tab, "Tab"}, + {0xff0b/*XK_Clear*/, "Clear"}, + {FL_Enter, "Enter"}, // X says "Enter" + {FL_Pause, "Pause"}, + {FL_Scroll_Lock, "Scroll_Lock"}, + {FL_Escape, "Escape"}, + {FL_Home, "Home"}, + {FL_Left, "Left"}, + {FL_Up, "Up"}, + {FL_Right, "Right"}, + {FL_Down, "Down"}, + {FL_Page_Up, "Page_Up"}, // X says "Prior" + {FL_Page_Down,"Page_Down"}, // X says "Next" + {FL_End, "End"}, + {FL_Print, "Print"}, + {FL_Insert, "Insert"}, + {FL_Menu, "Menu"}, + {FL_Num_Lock, "Num_Lock"}, + {FL_KP_Enter, "KP_Enter"}, + {FL_Shift_L, "Shift_L"}, + {FL_Shift_R, "Shift_R"}, + {FL_Control_L,"Control_L"}, + {FL_Control_R,"Control_R"}, + {FL_Caps_Lock,"Caps_Lock"}, + {FL_Meta_L, "Meta_L"}, + {FL_Meta_R, "Meta_R"}, + {FL_Alt_L, "Alt_L"}, + {FL_Alt_R, "Alt_R"}, + {FL_Delete, "Delete"} +}; +#endif + +const char * fl_shortcut_label(int shortcut) { + static char buf[20]; + char *p = buf; + if (!shortcut) {*p = 0; return buf;} + // fix upper case shortcuts + int v = shortcut & 0xffff; + if (v > 32 && v < 0x7f || v > 0xa0 && v <= 0xff) { + if (isupper(v)) { + shortcut |= FL_SHIFT; + } + } +#ifdef __APPLE__ + // \todo Mac : we might want to change the symbols for Mac users - consider drawing Apple Symbols... . + if (shortcut & FL_SHIFT) {strcpy(p,"Shift+"); p += 6;} //: Mac hollow up arrow + if (shortcut & FL_META) {strcpy(p,"Cmd+"); p += 4;} //: Mac 'Apple' key + if (shortcut & FL_ALT) {strcpy(p,"Option+"); p += 7;} //: Mac 'Alt/Option' or fancy switch symbol + if (shortcut & FL_CTRL) {strcpy(p,"Ctrl+"); p += 5;} //: Mac ctrl key +#else + if (shortcut & FL_META) {strcpy(p,"Meta+"); p += 5;} + if (shortcut & FL_ALT) {strcpy(p,"Alt+"); p += 4;} + if (shortcut & FL_SHIFT) {strcpy(p,"Shift+"); p += 6;} + if (shortcut & FL_CTRL) {strcpy(p,"Ctrl+"); p += 5;} +#endif // __APPLE__ + int key = shortcut & 0xFFFF; +#if defined(WIN32) || defined(__APPLE__) // if not X + if (key >= FL_F && key <= FL_F_Last) { + *p++ = 'F'; + if (key > FL_F+9) *p++ = (key-FL_F)/10+'0'; + *p++ = (key-FL_F)%10 + '0'; + } else { + // binary search the table for a match: + int a = 0; + int b = sizeof(table)/sizeof(*table); + while (a < b) { + int c = (a+b)/2; + if (table[c].key == key) { + if (p > buf) {strcpy(p,table[c].name); return buf;} + return table[c].name; + } + if (table[c].key < key) a = c+1; + else b = c; + } + if (key >= FL_KP && key <= FL_KP_Last) { + // mark keypad keys with KP_ prefix + strcpy(p,"KP_"); p += 3; + *p++ = uchar(key & 127); + } else { + // if none found, use the keystroke as a match: + *p++ = uchar(toupper(key & 255)); + } + } + *p = 0; + return buf; +#else + const char* q; + if (key == FL_Enter || key == '\r') q="Enter"; // don't use Xlib's "Return": + else if (key > 32 && key < 0x100) q = 0; + else q = XKeysymToString(key); + if (!q) {*p++ = uchar(toupper(key & 255)); *p = 0; return buf;} + if (p > buf) {strcpy(p,q); return buf;} else return q; +#endif +} + +// Emulation of XForms named shortcuts +#include <stdlib.h> +int fl_old_shortcut(const char* s) { + if (!s || !*s) return 0; + int n = 0; + if (*s == '#') {n |= FL_ALT; s++;} + if (*s == '+') {n |= FL_SHIFT; s++;} + if (*s == '^') {n |= FL_CTRL; s++;} + if (*s && s[1]) return n | (int)strtol(s,0,0); // allow 0xf00 to get any key + return n | *s; +} + +// Tests for &x shortcuts in button labels: + +int Fl_Widget::test_shortcut(const char *l) { + char c = Fl::event_text()[0]; + if (!c || !l) return 0; + for (;;) { + if (!*l) return 0; + if (*l++ == '&' && *l) { + if (*l == '&') l++; + else if (*l == c) return 1; + else return 0; + } + } +} + +int Fl_Widget::test_shortcut() { + if (!(flags()&SHORTCUT_LABEL)) return 0; + return test_shortcut(label()); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_show_colormap.cxx b/Utilities/FLTK/src/fl_show_colormap.cxx new file mode 100644 index 0000000000..6d52022a75 --- /dev/null +++ b/Utilities/FLTK/src/fl_show_colormap.cxx @@ -0,0 +1,162 @@ +// +// "$Id$" +// +// Colormap color selection dialog for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Select a color from the colormap. +// Pretty much unchanged from Forms. + +#include <FL/Fl.H> +#include <FL/Fl_Single_Window.H> +#include <FL/fl_draw.H> +#include <FL/fl_show_colormap.H> +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#define BOXSIZE 14 +#define BORDER 4 + +class ColorMenu : public Fl_Window { + Fl_Color initial; + Fl_Color which, previous; + int done; + void drawbox(Fl_Color); + void draw(); + int handle(int); +public: + ColorMenu(Fl_Color oldcol); + Fl_Color run(); +}; + +ColorMenu::ColorMenu(Fl_Color oldcol) : + Fl_Window(BOXSIZE*8+1+2*BORDER, BOXSIZE*32+1+2*BORDER) { + clear_border(); + set_modal(); + initial = which = oldcol; +} + +void ColorMenu::drawbox(Fl_Color c) { + if (c < 0 || c > 255) return; + int X = (c%8)*BOXSIZE+BORDER; + int Y = (c/8)*BOXSIZE+BORDER; +#if BORDER_WIDTH < 3 + if (c == which) fl_draw_box(FL_DOWN_BOX, X+1, Y+1, BOXSIZE-1, BOXSIZE-1, c); + else fl_draw_box(FL_BORDER_BOX, X, Y, BOXSIZE+1, BOXSIZE+1, c); +#else + fl_draw_box(c == which ? FL_DOWN_BOX : FL_BORDER_BOX, + X, Y, BOXSIZE+1, BOXSIZE+1, c); +#endif +} + +void ColorMenu::draw() { + if (damage() != FL_DAMAGE_CHILD) { + fl_draw_box(FL_UP_BOX,0,0,w(),h(),color()); + for (int c = 0; c < 256; c++) drawbox((Fl_Color)c); + } else { + drawbox(previous); + drawbox(which); + } + previous = which; +} + +int ColorMenu::handle(int e) { + int c = which; + switch (e) { + case FL_PUSH: + case FL_DRAG: { + int X = (Fl::event_x_root() - x() - BORDER); + if (X >= 0) X = X/BOXSIZE; + int Y = (Fl::event_y_root() - y() - BORDER); + if (Y >= 0) Y = Y/BOXSIZE; + if (X >= 0 && X < 8 && Y >= 0 && Y < 32) + c = 8*Y + X; + else + c = initial; + } break; + case FL_RELEASE: + done = 1; + return 1; + case FL_KEYBOARD: + switch (Fl::event_key()) { + case FL_Up: if (c > 7) c -= 8; break; + case FL_Down: if (c < 256-8) c += 8; break; + case FL_Left: if (c > 0) c--; break; + case FL_Right: if (c < 255) c++; break; + case FL_Escape: which = initial; done = 1; return 1; + case FL_KP_Enter: + case FL_Enter: done = 1; return 1; + default: return 0; + } + break; + default: + return 0; + } + if (c != which) { + which = (Fl_Color)c; damage(FL_DAMAGE_CHILD); + int bx = (c%8)*BOXSIZE+BORDER; + int by = (c/8)*BOXSIZE+BORDER; + int px = x(); + int py = y(); + int scr_x, scr_y, scr_w, scr_h; + Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h); + if (px < scr_x) px = scr_x; + if (px+bx+BOXSIZE+BORDER >= scr_x+scr_w) px = scr_x+scr_w-bx-BOXSIZE-BORDER; + if (py < scr_y) py = scr_y; + if (py+by+BOXSIZE+BORDER >= scr_y+scr_h) py = scr_y+scr_h-by-BOXSIZE-BORDER; + if (px+bx < BORDER) px = BORDER-bx; + if (py+by < BORDER) py = BORDER-by; + position(px,py); + } + return 1; +} + +extern char fl_override_redirect; // hack for menus + +#ifdef _MSC_VER +#pragma optimize("a",off) // needed to get the done check to work +#endif +Fl_Color ColorMenu::run() { + if (which < 0 || which > 255) { + position(Fl::event_x_root()-w()/2, Fl::event_y_root()-y()/2); + } else { + position(Fl::event_x_root()-(initial%8)*BOXSIZE-BOXSIZE/2-BORDER, + Fl::event_y_root()-(initial/8)*BOXSIZE-BOXSIZE/2-BORDER); + } + show(); + Fl::grab(*this); + done = 0; + while (!done) Fl::wait(); + Fl::release(); + return which; +} + +Fl_Color fl_show_colormap(Fl_Color oldcol) { + ColorMenu m(oldcol); + return m.run(); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_symbols.cxx b/Utilities/FLTK/src/fl_symbols.cxx new file mode 100644 index 0000000000..e25fea6157 --- /dev/null +++ b/Utilities/FLTK/src/fl_symbols.cxx @@ -0,0 +1,700 @@ +// +// "$Id$" +// +// Symbol drawing code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// These are small graphics drawn by the normal label-drawing +// code when the string starts with an '@' sign. + +// Adapted from original code written by: + +// Written by Mark Overmars +// Version 2.1 a +// Date: Oct 2, 1992 + +#include <FL/Fl.H> +#include <FL/fl_draw.H> +#include <FL/math.h> +#include "flstring.h" + +typedef struct { + const char *name; + void (*drawit)(Fl_Color); + char scalable; + char notempty; +} SYMBOL; + +#define MAXSYMBOL 211 + /* Maximal number of symbols in table. Only half of them are + used. Should be prime. */ + +static SYMBOL symbols[MAXSYMBOL]; /* The symbols */ +static int symbnumb = -1; /* Their number */ + +static int find(const char *name) { +// returns hash entry if it exists, or first empty slot: + int pos = name[0] ? ( + name[1] ? ( + name[2] ? 71*name[0]+31*name[1]+name[2] : 31*name[0]+name[1] + ) : + name[0] + ) : 0; + pos %= MAXSYMBOL; + int hh2 = name[0] ? ( + (name[1]) ? 51*name[0]+3*name[1] : 3*name[0] + ) : 1; + hh2 %= MAXSYMBOL; if (!hh2) hh2 = 1; + for (;;) { + if (!symbols[pos].notempty) return pos; + if (!strcmp(symbols[pos].name,name)) return pos; + pos = (pos + hh2) % MAXSYMBOL; + } +} + +static void fl_init_symbols(void); + +/**************** The routines seen by the user *************************/ + +int fl_add_symbol(const char *name, void (*drawit)(Fl_Color), int scalable) +/* Adds a symbol to the system. Returns whether correct. */ +{ + fl_init_symbols(); + int pos; + if (symbnumb > MAXSYMBOL / 2) return 0; // table is full + pos = find(name); + symbols[pos].name = name; + symbols[pos].drawit = drawit; + symbols[pos].notempty = 1; + symbols[pos].scalable = scalable; + symbnumb++; + return 1; +} + +int fl_return_arrow(int x,int y,int w,int h); + +// provided for back compatability: +int fl_draw_symbol(const char *label,int x,int y,int w,int h,Fl_Color col) { + const char *p = label; + if (*p++ != '@') return 0; + fl_init_symbols(); + int equalscale = 0; + if (*p == '#') {equalscale = 1; p++;} + if (*p == '-' && p[1]>='1' && p[1]<='9') { + int n = p[1]-'0'; + x += n; y += n; w -= 2*n; h -= 2*n; + p += 2; + } else if (*p == '+' && p[1]>='1' && p[1]<='9') { + int n = p[1]-'0'; + x -= n; y -= n; w += 2*n; h += 2*n; + p += 2; + } + if (w < 10) {x -= (10-w)/2; w = 10;} + if (h < 10) {y -= (10-h)/2; h = 10;} + w = (w-1)|1; h = (h-1)|1; + char flip_x = 0, flip_y = 0; + if (*p=='$') { + flip_x = 1; + p++; + } + if (*p=='%') { + flip_y = 1; + p++; + } + int rotangle; + switch (*p++) { + case '0': + rotangle = 1000*(p[1]-'0') + 100*(p[2]-'0') + 10*(p[3]-'0'); + p += 4; + break; + case '1': rotangle = 2250; break; + case '2': rotangle = 2700; break; + case '3': rotangle = 3150; break; + case '4': rotangle = 1800; break; + case '5': + case '6': rotangle = 0; break; + case '7': rotangle = 1350; break; + case '8': rotangle = 900; break; + case '9': rotangle = 450; break; + default: rotangle = 0; p--; break; + } + int pos = find(p); + if (!symbols[pos].notempty) return 0; + if (symbols[pos].scalable == 3) { // kludge to detect return arrow + fl_return_arrow(x,y,w,h); + return 1; + } + fl_push_matrix(); + fl_translate(x+w/2,y+h/2); + if (symbols[pos].scalable) { + if (equalscale) {if (w<h) h = w; else w = h;} + fl_scale(0.5*w, 0.5*h); + fl_rotate(rotangle/10.0); + if (flip_x) fl_scale(-1.0, 1.0); + if (flip_y) fl_scale(1.0, -1.0); + } + (symbols[pos].drawit)(col); + fl_pop_matrix(); + return 1; +} + +/******************** THE DEFAULT SYMBOLS ****************************/ + +/* Some help stuff */ + +#define BP fl_begin_polygon() +#define EP fl_end_polygon() +#define BCP fl_begin_complex_polygon() +#define ECP fl_end_complex_polygon() +#define BL fl_begin_line() +#define EL fl_end_line() +#define BC fl_begin_loop() +#define EC fl_end_loop() +#define vv(x,y) fl_vertex(x,y) + +//for the outline color +static void set_outline_color(Fl_Color c) { + fl_color(fl_darker(c)); +} + +static void rectangle(double x,double y,double x2,double y2,Fl_Color col) { + fl_color(col); + BP; vv(x,y); vv(x2,y); vv(x2,y2); vv(x,y2); EP; + set_outline_color(col); + BC; vv(x,y); vv(x2,y); vv(x2,y2); vv(x,y2); EC; +} + +/* The drawing routines */ + +static void draw_fltk(Fl_Color col) +{ + fl_color(col); + // F fill + BCP; vv(-2.0, -0.5); vv(-1.0, -0.5); vv(-1.0, -0.3); vv(-1.8, -0.3); + vv(-1.8, -0.1); vv(-1.2, -0.1); vv(-1.2, 0.1); vv(-1.8, 0.1); + vv(-1.8, 0.5); vv(-2.0, 0.5); ECP; + // L fill + BCP; vv(-1.0, -0.5); vv(-0.8, -0.5); vv(-0.8, 0.3); vv(0.0, 0.3); + vv(0.0, 0.5); vv(-1.0, 0.5); ECP; + // T outline + BCP; vv(-0.1, -0.5); vv(1.1, -0.5); vv(1.1, -0.3); vv(0.6, -0.3); + vv(0.6, 0.5); vv(0.4, 0.5); vv(0.4, -0.3); vv(-0.1, -0.3); ECP; + // K outline + BCP; vv(1.1, -0.5); vv(1.3, -0.5); vv(1.3, -0.15); vv(1.70, -0.5); + vv(2.0, -0.5); vv(1.43, 0.0); vv(2.0, 0.5); vv(1.70, 0.5); + vv(1.3, 0.15); vv(1.3, 0.5); vv(1.1, 0.5); ECP; + set_outline_color(col); + // F outline + BC; vv(-2.0, -0.5); vv(-1.0, -0.5); vv(-1.0, -0.3); vv(-1.8, -0.3); + vv(-1.8, -0.1); vv(-1.2, -0.1); vv(-1.2, 0.1); vv(-1.8, 0.1); + vv(-1.8, 0.5); vv(-2.0, 0.5); EC; + // L outline + BC; vv(-1.0, -0.5); vv(-0.8, -0.5); vv(-0.8, 0.3); vv(0.0, 0.3); + vv(0.0, 0.5); vv(-1.0, 0.5); EC; + // T outline + BC; vv(-0.1, -0.5); vv(1.1, -0.5); vv(1.1, -0.3); vv(0.6, -0.3); + vv(0.6, 0.5); vv(0.4, 0.5); vv(0.4, -0.3); vv(-0.1, -0.3); EC; + // K outline + BC; vv(1.1, -0.5); vv(1.3, -0.5); vv(1.3, -0.15); vv(1.70, -0.5); + vv(2.0, -0.5); vv(1.43, 0.0); vv(2.0, 0.5); vv(1.70, 0.5); + vv(1.3, 0.15); vv(1.3, 0.5); vv(1.1, 0.5); EC; +} + +static void draw_search(Fl_Color col) +{ + fl_color(col); + BP; vv(-.4, .13); vv(-1.0, .73); vv(-.73, 1.0); vv(-.13, .4); EP; + set_outline_color(col); + fl_line_style(FL_SOLID, 3, 0); + BC; fl_circle(.2, -.2, .6); EC; + fl_line_style(FL_SOLID, 1, 0); + BC; vv(-.4, .13); vv(-1.0, .73); vv(-.73, 1.0); vv(-.13, .4); EC; +} + +static void draw_arrow1(Fl_Color col) +{ + fl_color(col); + BP; vv(-0.8,-0.4); vv(-0.8,0.4); vv(0.0,0.4); vv(0.0,-0.4); EP; + BP; vv(0.0,0.8); vv(0.8,0.0); vv(0.0,-0.8); vv(0.0,-0.4); vv(0.0,0.4); EP; + set_outline_color(col); + BC; vv(-0.8,-0.4); vv(-0.8,0.4); vv(0.0,0.4); vv(0.0,0.8); vv(0.8,0.0); + vv(0.0,-0.8); vv(0.0,-0.4); EC; +} + +static void draw_arrow1bar(Fl_Color col) +{ + draw_arrow1(col); + rectangle(.6,-.8,.9,.8,col); +} + +static void draw_arrow2(Fl_Color col) +{ + fl_color(col); + BP; vv(-0.3,0.8); vv(0.50,0.0); vv(-0.3,-0.8); EP; + set_outline_color(col); + BC; vv(-0.3,0.8); vv(0.50,0.0); vv(-0.3,-0.8); EC; +} + +static void draw_arrow3(Fl_Color col) +{ + fl_color(col); + BP; vv(0.1,0.8); vv(0.9,0.0); vv(0.1,-0.8); EP; + BP; vv(-0.7,0.8); vv(0.1,0.0); vv(-0.7,-0.8); EP; + set_outline_color(col); + BC; vv(0.1,0.8); vv(0.9,0.0); vv(0.1,-0.8); EC; + BC; vv(-0.7,0.8); vv(0.1,0.0); vv(-0.7,-0.8); EC; +} + +static void draw_arrowbar(Fl_Color col) +{ + fl_color(col); + BP; vv(0.2,0.8); vv(0.6,0.8); vv(0.6,-0.8); vv(0.2,-0.8); EP; + BP; vv(-0.6,0.8); vv(0.2,0.0); vv(-0.6,-0.8); EP; + set_outline_color(col); + BC; vv(0.2,0.8); vv(0.6,0.8); vv(0.6,-0.8); vv(0.2,-0.8); EC; + BC; vv(-0.6,0.8); vv(0.2,0.0); vv(-0.6,-0.8); EC; +} + +static void draw_arrowbox(Fl_Color col) +{ + fl_color(col); + BP; vv(-0.6,0.8); vv(0.2,0.0); vv(-0.6,-0.8); EP; + BC; vv(0.2,0.8); vv(0.6,0.8); vv(0.6,-0.8); vv(0.2,-0.8); EC; + set_outline_color(col); + BC; vv(0.2,0.8); vv(0.6,0.8); vv(0.6,-0.8); vv(0.2,-0.8); EC; + BC; vv(-0.6,0.8); vv(0.2,0.0); vv(-0.6,-0.8); EC; +} + +static void draw_bararrow(Fl_Color col) +{ + fl_color(col); + BP; vv(0.1,0.8); vv(0.9,0.0); vv(0.1,-0.8); EP; + BP; vv(-0.5,0.8); vv(-0.1,0.8); vv(-0.1,-0.8); vv(-0.5,-0.8); EP; + set_outline_color(col); + BC; vv(0.1,0.8); vv(0.9,0.0); vv(0.1,-0.8); EC; + BC; vv(-0.5,0.8); vv(-0.1,0.8); vv(-0.1,-0.8); vv(-0.5,-0.8); EC; +} + +static void draw_doublebar(Fl_Color col) { + rectangle(-0.6,-0.8,-.1,.8,col); + rectangle(.1,-0.8,.6,.8,col); +} + +static void draw_arrow01(Fl_Color col) + { fl_rotate(180); draw_arrow1(col); } + +static void draw_arrow02(Fl_Color col) + { fl_rotate(180); draw_arrow2(col); } + +static void draw_arrow03(Fl_Color col) + { fl_rotate(180); draw_arrow3(col); } + +static void draw_0arrowbar(Fl_Color col) + { fl_rotate(180); draw_arrowbar(col); } + +static void draw_0arrowbox(Fl_Color col) + { fl_rotate(180); draw_arrowbox(col); } + +static void draw_0bararrow(Fl_Color col) + { fl_rotate(180); draw_bararrow(col); } + +static void draw_doublearrow(Fl_Color col) +{ + fl_color(col); + BP; vv(-0.35,-0.4); vv(-0.35,0.4); vv(0.35,0.4); vv(0.35,-0.4); EP; + BP; vv(0.15,0.8); vv(0.95,0.0); vv(0.15,-0.8); EP; + BP; vv(-0.15,0.8); vv(-0.95,0.0); vv(-0.15,-0.8); EP; + set_outline_color(col); + BC; vv(-0.15,0.4); vv(0.15,0.4); vv(0.15,0.8); vv(0.95,0.0); + vv(0.15,-0.8); vv(0.15,-0.4); vv(-0.15,-0.4); vv(-0.15,-0.8); + vv(-0.95,0.0); vv(-0.15,0.8); EC; +} + +static void draw_arrow(Fl_Color col) +{ + fl_color(col); + BP; vv(0.65,0.1); vv(1.0,0.0); vv(0.65,-0.1); EP; + BL; vv(-1.0,0.0); vv(0.65,0.0); EL; + set_outline_color(col); + BL; vv(-1.0,0.0); vv(0.65,0.0); EL; + BC; vv(0.65,0.1); vv(1.0,0.0); vv(0.65,-0.1); EC; +} + +static void draw_square(Fl_Color col) + { rectangle(-1,-1,1,1,col); } + +static void draw_circle(Fl_Color col) { + fl_color(col); BP; fl_circle(0,0,1); EP; + set_outline_color(col); + BC; fl_circle(0,0,1); EC; +} + +static void draw_line(Fl_Color col) + { fl_color(col); BL; vv(-1.0,0.0); vv(1.0,0.0); EL; } + +static void draw_plus(Fl_Color col) +{ + fl_color(col); + BP; vv(-0.9,-0.15); vv(-0.9,0.15); vv(0.9,0.15); vv(0.9,-0.15); EP; + BP; vv(-0.15,-0.9); vv(-0.15,0.9); vv(0.15,0.9); vv(0.15,-0.9); EP; + set_outline_color(col); + BC; + vv(-0.9,-0.15); vv(-0.9,0.15); vv(-0.15,0.15); vv(-0.15,0.9); + vv(0.15,0.9); vv(0.15,0.15); vv(0.9,0.15); vv(0.9,-0.15); + vv(0.15,-0.15); vv(0.15,-0.9); vv(-0.15,-0.9); vv(-0.15,-0.15); + EC; +} + +static void draw_uparrow(Fl_Color) { + fl_color(FL_LIGHT3); + BL; vv(-.8,.8); vv(-.8,-.8); vv(.8,0); EL; + fl_color(FL_DARK3); + BL; vv(-.8,.8); vv(.8, 0); EL; +} + +static void draw_downarrow(Fl_Color) { + fl_color(FL_DARK3); + BL; vv(-.8,.8); vv(-.8,-.8); vv(.8,0); EL; + fl_color(FL_LIGHT3); + BL; vv(-.8,.8); vv(.8, 0); EL; +} + +static void draw_menu(Fl_Color col) +{ + rectangle(-0.65, 0.85, 0.65, -0.25, col); + rectangle(-0.65, -0.6, 0.65, -1.0, col); +} + +// Standard UI icons... +static void draw_filenew(Fl_Color c) { + fl_color(c); + BCP; + vv(-0.7, -1.0); + vv(0.1, -1.0); + vv(0.1, -0.4); + vv(0.7, -0.4); + vv(0.7, 1.0); + vv(-0.7, 1.0); + ECP; + + fl_color(fl_lighter(c)); + BP; + vv(0.1, -1.0); + vv(0.1, -0.4); + vv(0.7, -0.4); + EP; + + fl_color(fl_darker(c)); + BC; + vv(-0.7, -1.0); + vv(0.1, -1.0); + vv(0.1, -0.4); + vv(0.7, -0.4); + vv(0.7, 1.0); + vv(-0.7, 1.0); + EC; + + BL; + vv(0.1, -1.0); + vv(0.7, -0.4); + EL; +} + +static void draw_fileopen(Fl_Color c) { + fl_color(c); + BP; + vv(-1.0, -0.7); + vv(-0.9, -0.8); + vv(-0.4, -0.8); + vv(-0.3, -0.7); + vv(0.6, -0.7); + vv(0.6, 0.7); + vv(-1.0, 0.7); + EP; + + fl_color(fl_darker(c)); + BC; + vv(-1.0, -0.7); + vv(-0.9, -0.8); + vv(-0.4, -0.8); + vv(-0.3, -0.7); + vv(0.6, -0.7); + vv(0.6, 0.7); + vv(-1.0, 0.7); + EC; + + fl_color(fl_lighter(c)); + BP; + vv(-1.0, 0.7); + vv(-0.6, -0.3); + vv(1.0, -0.3); + vv(0.6, 0.7); + EP; + + fl_color(fl_darker(c)); + BC; + vv(-1.0, 0.7); + vv(-0.6, -0.3); + vv(1.0, -0.3); + vv(0.6, 0.7); + EC; +} + +static void draw_filesave(Fl_Color c) { + fl_color(c); + BP; + vv(-0.9, -1.0); + vv(0.9, -1.0); + vv(1.0, -0.9); + vv(1.0, 0.9); + vv(0.9, 1.0); + vv(-0.9, 1.0); + vv(-1.0, 0.9); + vv(-1.0, -0.9); + EP; + + fl_color(fl_lighter(c)); + BP; + vv(-0.7, -1.0); + vv(0.7, -1.0); + vv(0.7, -0.4); + vv(-0.7, -0.4); + EP; + + BP; + vv(-0.7, 0.0); + vv(0.7, 0.0); + vv(0.7, 1.0); + vv(-0.7, 1.0); + EP; + + fl_color(c); + BP; + vv(-0.5, -0.9); + vv(-0.3, -0.9); + vv(-0.3, -0.5); + vv(-0.5, -0.5); + EP; + + fl_color(fl_darker(c)); + BC; + vv(-0.9, -1.0); + vv(0.9, -1.0); + vv(1.0, -0.9); + vv(1.0, 0.9); + vv(0.9, 1.0); + vv(-0.9, 1.0); + vv(-1.0, 0.9); + vv(-1.0, -0.9); + EC; +} + +static void draw_filesaveas(Fl_Color c) { + draw_filesave(c); + + fl_color(fl_color_average(c, FL_WHITE, 0.25f)); + BP; + vv(0.6, -0.8); + vv(1.0, -0.4); + vv(0.0, 0.6); + vv(-0.4, 0.6); + vv(-0.4, 0.2); + EP; + + fl_color(fl_darker(c)); + BC; + vv(0.6, -0.8); + vv(1.0, -0.4); + vv(0.0, 0.6); + vv(-0.4, 0.6); + vv(-0.4, 0.2); + EC; + + BP; + vv(-0.1, 0.6); + vv(-0.4, 0.6); + vv(-0.4, 0.3); + EP; +} + +static void draw_fileprint(Fl_Color c) { + fl_color(c); + BP; + vv(-0.8, 0.0); + vv(0.8, 0.0); + vv(1.0, 0.2); + vv(1.0, 1.0); + vv(-1.0, 1.0); + vv(-1.0, 0.2); + EP; + + fl_color(fl_color_average(c, FL_WHITE, 0.25f)); + BP; + vv(-0.6, 0.0); + vv(-0.6, -1.0); + vv(0.6, -1.0); + vv(0.6, 0.0); + EP; + + fl_color(fl_lighter(c)); + BP; + vv(-0.6, 0.6); + vv(0.6, 0.6); + vv(0.6, 1.0); + vv(-0.6, 1.0); + EP; + + fl_color(fl_darker(c)); + BC; + vv(-0.8, 0.0); + vv(-0.6, 0.0); + vv(-0.6, -1.0); + vv(0.6, -1.0); + vv(0.6, 0.0); + vv(0.8, 0.0); + vv(1.0, 0.2); + vv(1.0, 1.0); + vv(-1.0, 1.0); + vv(-1.0, 0.2); + EC; + + BC; + vv(-0.6, 0.6); + vv(0.6, 0.6); + vv(0.6, 1.0); + vv(-0.6, 1.0); + EC; +} + +static void draw_round_arrow(Fl_Color c, float da=5.0) { + double a, r, dr1=0.005, dr2=0.015; + int i, j; + for (j=0; j<2; j++) { + if (j&1) { + fl_color(c); + set_outline_color(c); + BC; + } else { + fl_color(c); + BCP; + } + vv(-0.1, 0.0); + vv(-1.0, 0.0); + vv(-1.0, 0.9); + for (i=27, a=140.0, r=1.0; i>0; i--, a-=da, r-=dr1) { + double ar = a/180.0 * M_PI; + vv(cos(ar)*r, sin(ar)*r); + } + for (i=27; i>=0; a+=da, i--, r-=dr2) { + double ar = a/180.0 * M_PI; + vv(cos(ar)*r, sin(ar)*r); + } + if (j&1) { + EC; + } else { + ECP; + } + } +} + +static void draw_refresh(Fl_Color c) { + draw_round_arrow(c); + fl_rotate(180.0); + draw_round_arrow(c); + fl_rotate(-180.0); +} + +static void draw_reload(Fl_Color c) { + fl_rotate(-135.0); + draw_round_arrow(c, 10); + fl_rotate(135.0); +} + +static void draw_undo(Fl_Color c) { + fl_translate(0.0, 0.2); + fl_scale(1.0, -1.0); + draw_round_arrow(c, 6); + fl_scale(1.0, -1.0); + fl_translate(0.0, -0.2); +} + +static void draw_redo(Fl_Color c) { + fl_scale(-1.0, 1.0); + draw_undo(c); + fl_scale(-1.0, 1.0); +} + +static void fl_init_symbols(void) { + static char beenhere; + if (beenhere) return; + beenhere = 1; + symbnumb = 0; + + fl_add_symbol("", draw_arrow1, 1); + fl_add_symbol("->", draw_arrow1, 1); + fl_add_symbol(">", draw_arrow2, 1); + fl_add_symbol(">>", draw_arrow3, 1); + fl_add_symbol(">|", draw_arrowbar, 1); + fl_add_symbol(">[]", draw_arrowbox, 1); + fl_add_symbol("|>", draw_bararrow, 1); + fl_add_symbol("<-", draw_arrow01, 1); + fl_add_symbol("<", draw_arrow02, 1); + fl_add_symbol("<<", draw_arrow03, 1); + fl_add_symbol("|<", draw_0arrowbar, 1); + fl_add_symbol("[]<", draw_0arrowbox, 1); + fl_add_symbol("<|", draw_0bararrow, 1); + fl_add_symbol("<->", draw_doublearrow, 1); + fl_add_symbol("-->", draw_arrow, 1); + fl_add_symbol("+", draw_plus, 1); + fl_add_symbol("->|", draw_arrow1bar, 1); + fl_add_symbol("arrow", draw_arrow, 1); + fl_add_symbol("returnarrow", 0, 3); + fl_add_symbol("square", draw_square, 1); + fl_add_symbol("circle", draw_circle, 1); + fl_add_symbol("line", draw_line, 1); + fl_add_symbol("plus", draw_plus, 1); + fl_add_symbol("menu", draw_menu, 1); + fl_add_symbol("UpArrow", draw_uparrow, 1); + fl_add_symbol("DnArrow", draw_downarrow, 1); + fl_add_symbol("||", draw_doublebar, 1); + fl_add_symbol("search", draw_search, 1); + fl_add_symbol("FLTK", draw_fltk, 1); + + fl_add_symbol("filenew", draw_filenew, 1); + fl_add_symbol("fileopen", draw_fileopen, 1); + fl_add_symbol("filesave", draw_filesave, 1); + fl_add_symbol("filesaveas", draw_filesaveas, 1); + fl_add_symbol("fileprint", draw_fileprint, 1); + + fl_add_symbol("refresh", draw_refresh, 1); + fl_add_symbol("reload", draw_reload, 1); + fl_add_symbol("undo", draw_undo, 1); + fl_add_symbol("redo", draw_redo, 1); + +// fl_add_symbol("file", draw_file, 1); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/fl_vertex.cxx b/Utilities/FLTK/src/fl_vertex.cxx new file mode 100644 index 0000000000..da6d32ccbc --- /dev/null +++ b/Utilities/FLTK/src/fl_vertex.cxx @@ -0,0 +1,326 @@ +// +// "$Id$" +// +// Portable drawing routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Portable drawing code for drawing arbitrary shapes with +// simple 2D transformations. See also fl_arc.cxx + +// matt: the Quartz implementation purposly doesn't use the Quartz matrix +// operations for reasons of compatibility and maintainability + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#include <FL/x.H> +#include <FL/Fl.H> +#include <FL/math.h> +#include <stdlib.h> + +struct matrix {double a, b, c, d, x, y;}; + +static matrix m = {1, 0, 0, 1, 0, 0}; + +static matrix stack[32]; +static int sptr = 0; + +void fl_push_matrix() { + if (sptr==32) + Fl::error("fl_push_matrix(): matrix stack overflow."); + else + stack[sptr++] = m; +} + +void fl_pop_matrix() { + if (sptr==0) + Fl::error("fl_pop_matrix(): matrix stack underflow."); + else + m = stack[--sptr]; +} + +void fl_mult_matrix(double a, double b, double c, double d, double x, double y) { + matrix o; + o.a = a*m.a + b*m.c; + o.b = a*m.b + b*m.d; + o.c = c*m.a + d*m.c; + o.d = c*m.b + d*m.d; + o.x = x*m.a + y*m.c + m.x; + o.y = x*m.b + y*m.d + m.y; + m = o; +} + +void fl_scale(double x,double y) {fl_mult_matrix(x,0,0,y,0,0);} + +void fl_scale(double x) {fl_mult_matrix(x,0,0,x,0,0);} + +void fl_translate(double x,double y) {fl_mult_matrix(1,0,0,1,x,y);} + +void fl_rotate(double d) { + if (d) { + double s, c; + if (d == 0) {s = 0; c = 1;} + else if (d == 90) {s = 1; c = 0;} + else if (d == 180) {s = 0; c = -1;} + else if (d == 270 || d == -90) {s = -1; c = 0;} + else {s = sin(d*M_PI/180); c = cos(d*M_PI/180);} + fl_mult_matrix(c,-s,s,c,0,0); + } +} + +// typedef what the x,y fields in a point are: +#ifdef WIN32 +typedef int COORD_T; +# define XPOINT XPoint +#elif defined(__APPLE_QUARTZ__) +typedef float COORD_T; +typedef struct { float x; float y; } QPoint; +# define XPOINT QPoint +extern float fl_quartz_line_width_; +#else +typedef short COORD_T; +# define XPOINT XPoint +#endif + +static XPOINT *p = (XPOINT *)0; + +static int p_size; +static int n; +static int what; +enum {LINE, LOOP, POLYGON, POINT_}; + +void fl_begin_points() {n = 0; what = POINT_;} + +void fl_begin_line() {n = 0; what = LINE;} + +void fl_begin_loop() {n = 0; what = LOOP;} + +void fl_begin_polygon() {n = 0; what = POLYGON;} + +double fl_transform_x(double x, double y) {return x*m.a + y*m.c + m.x;} + +double fl_transform_y(double x, double y) {return x*m.b + y*m.d + m.y;} + +double fl_transform_dx(double x, double y) {return x*m.a + y*m.c;} + +double fl_transform_dy(double x, double y) {return x*m.b + y*m.d;} + +static void fl_transformed_vertex(COORD_T x, COORD_T y) { + if (!n || x != p[n-1].x || y != p[n-1].y) { + if (n >= p_size) { + p_size = p ? 2*p_size : 16; + p = (XPOINT*)realloc((void*)p, p_size*sizeof(*p)); + } + p[n].x = x; + p[n].y = y; + n++; + } +} + +void fl_transformed_vertex(double xf, double yf) { +#ifdef __APPLE_QUARTZ__ + fl_transformed_vertex(COORD_T(xf), COORD_T(yf)); +#else + fl_transformed_vertex(COORD_T(rint(xf)), COORD_T(rint(yf))); +#endif +} + +void fl_vertex(double x,double y) { + fl_transformed_vertex(x*m.a + y*m.c + m.x, x*m.b + y*m.d + m.y); +} + +void fl_end_points() { +#ifdef WIN32 + for (int i=0; i<n; i++) SetPixel(fl_gc, p[i].x, p[i].y, fl_RGB()); +#elif defined(__APPLE_QD__) + for (int i=0; i<n; i++) { MoveTo(p[i].x, p[i].y); Line(0, 0); } +#elif defined(__APPLE_QUARTZ__) + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false); + for (int i=0; i<n; i++) { + CGContextMoveToPoint(fl_gc, p[i].x, p[i].y); + CGContextAddLineToPoint(fl_gc, p[i].x, p[i].y); + CGContextStrokePath(fl_gc); + } + if (fl_quartz_line_width_==1.0f) CGContextSetShouldAntialias(fl_gc, false); +#else + if (n>1) XDrawPoints(fl_display, fl_window, fl_gc, p, n, 0); +#endif +} + +void fl_end_line() { + if (n < 2) { + fl_end_points(); + return; + } +#ifdef WIN32 + if (n>1) Polyline(fl_gc, p, n); +#elif defined(__APPLE_QD__) + if (n<=1) return; + MoveTo(p[0].x, p[0].y); + for (int i=1; i<n; i++) LineTo(p[i].x, p[i].y); +#elif defined(__APPLE_QUARTZ__) + if (n<=1) return; + CGContextMoveToPoint(fl_gc, p[0].x, p[0].y); + for (int i=1; i<n; i++) + CGContextAddLineToPoint(fl_gc, p[i].x, p[i].y); + CGContextStrokePath(fl_gc); +#else + if (n>1) XDrawLines(fl_display, fl_window, fl_gc, p, n, 0); +#endif +} + +static void fixloop() { // remove equal points from closed path + while (n>2 && p[n-1].x == p[0].x && p[n-1].y == p[0].y) n--; +} + +void fl_end_loop() { + fixloop(); + if (n>2) fl_transformed_vertex((COORD_T)p[0].x, (COORD_T)p[0].y); + fl_end_line(); +} + +void fl_end_polygon() { + fixloop(); + if (n < 3) { + fl_end_line(); + return; + } +#ifdef WIN32 + if (n>2) { + SelectObject(fl_gc, fl_brush()); + Polygon(fl_gc, p, n); + } +#elif defined(__APPLE_QD__) + if (n<=1) return; + PolyHandle ph = OpenPoly(); + MoveTo(p[0].x, p[0].y); + for (int i=1; i<n; i++) LineTo(p[i].x, p[i].y); + ClosePoly(); + PaintPoly(ph); + KillPoly(ph); +#elif defined(__APPLE_QUARTZ__) + if (n<=1) return; + CGContextMoveToPoint(fl_gc, p[0].x, p[0].y); + for (int i=1; i<n; i++) + CGContextAddLineToPoint(fl_gc, p[i].x, p[i].y); + CGContextClosePath(fl_gc); + CGContextFillPath(fl_gc); +#else + if (n>2) XFillPolygon(fl_display, fl_window, fl_gc, p, n, Convex, 0); +#endif +} + +static int gap; +#ifdef WIN32 +static int counts[20]; +static int numcount; +#endif + +void fl_begin_complex_polygon() { + fl_begin_polygon(); + gap = 0; +#ifdef WIN32 + numcount = 0; +#endif +} + +void fl_gap() { + while (n>gap+2 && p[n-1].x == p[gap].x && p[n-1].y == p[gap].y) n--; + if (n > gap+2) { + fl_transformed_vertex((COORD_T)p[gap].x, (COORD_T)p[gap].y); +#ifdef WIN32 + counts[numcount++] = n-gap; +#endif + gap = n; + } else { + n = gap; + } +} + +void fl_end_complex_polygon() { + fl_gap(); + if (n < 3) { + fl_end_line(); + return; + } +#ifdef WIN32 + if (n>2) { + SelectObject(fl_gc, fl_brush()); + PolyPolygon(fl_gc, p, counts, numcount); + } +#elif defined(__APPLE_QD__) + if (n<=1) return; + PolyHandle ph = OpenPoly(); + MoveTo(p[0].x, p[0].y); + for (int i=1; i<n; i++) LineTo(p[i].x, p[i].y); + ClosePoly(); + PaintPoly(ph); + KillPoly(ph); +#elif defined(__APPLE_QUARTZ__) + if (n<=1) return; + CGContextMoveToPoint(fl_gc, p[0].x, p[0].y); + for (int i=1; i<n; i++) + CGContextAddLineToPoint(fl_gc, p[i].x, p[i].y); + CGContextClosePath(fl_gc); + CGContextFillPath(fl_gc); +#else + if (n>2) XFillPolygon(fl_display, fl_window, fl_gc, p, n, 0, 0); +#endif +} + +// shortcut the closed circles so they use XDrawArc: +// warning: these do not draw rotated ellipses correctly! +// See fl_arc.c for portable version. + +void fl_circle(double x, double y,double r) { + double xt = fl_transform_x(x,y); + double yt = fl_transform_y(x,y); + double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a)); + double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d)); + int llx = (int)rint(xt-rx); + int w = (int)rint(xt+rx)-llx; + int lly = (int)rint(yt-ry); + int h = (int)rint(yt+ry)-lly; +#ifdef WIN32 + if (what==POLYGON) { + SelectObject(fl_gc, fl_brush()); + Pie(fl_gc, llx, lly, llx+w, lly+h, 0,0, 0,0); + } else + Arc(fl_gc, llx, lly, llx+w, lly+h, 0,0, 0,0); +#elif defined(__APPLE_QD__) + Rect rt; rt.left=llx; rt.right=llx+w; rt.top=lly; rt.bottom=lly+h; + (what == POLYGON ? PaintOval : FrameOval)(&rt); +#elif defined(__APPLE_QUARTZ__) + // Quartz warning : circle won't scale to current matrix! + CGContextAddArc(fl_gc, xt, yt, (w+h)*0.25f, 0, 2.0f*M_PI, 1); + (what == POLYGON ? CGContextFillPath : CGContextStrokePath)(fl_gc); +#else + (what == POLYGON ? XFillArc : XDrawArc) + (fl_display, fl_window, fl_gc, llx, lly, w, h, 0, 360*64); +#endif +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/flstring.c b/Utilities/FLTK/src/flstring.c new file mode 100644 index 0000000000..754dd143f0 --- /dev/null +++ b/Utilities/FLTK/src/flstring.c @@ -0,0 +1,105 @@ +/* + * "$Id$" + * + * BSD string functions for the Fast Light Tool Kit (FLTK). + * + * Copyright 1998-2005 by Bill Spitzak and others. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems on the following page: + * + * http://www.fltk.org/str.php + */ + +#include "flstring.h" + + +/* + * 'fl_strlcat()' - Safely concatenate two strings. + */ + +size_t /* O - Length of string */ +fl_strlcat(char *dst, /* O - Destination string */ + const char *src, /* I - Source string */ + size_t size) { /* I - Size of destination string buffer */ + size_t srclen; /* Length of source string */ + size_t dstlen; /* Length of destination string */ + + + /* + * Figure out how much room is left... + */ + + dstlen = strlen(dst); + size -= dstlen + 1; + + if (!size) return (dstlen); /* No room, return immediately... */ + + /* + * Figure out how much room is needed... + */ + + srclen = strlen(src); + + /* + * Copy the appropriate amount... + */ + + if (srclen > size) srclen = size; + + memcpy(dst + dstlen, src, srclen); + dst[dstlen + srclen] = '\0'; + + return (dstlen + srclen); +} + + +/* + * 'fl_strlcpy()' - Safely copy two strings. + */ + +size_t /* O - Length of string */ +fl_strlcpy(char *dst, /* O - Destination string */ + const char *src, /* I - Source string */ + size_t size) { /* I - Size of destination string buffer */ + size_t srclen; /* Length of source string */ + + + /* + * Figure out how much room is needed... + */ + + size --; + + srclen = strlen(src); + + /* + * Copy the appropriate amount... + */ + + if (srclen > size) srclen = size; + + memcpy(dst, src, srclen); + dst[srclen] = '\0'; + + return (srclen); +} + + +/* + * End of "$Id$". + */ diff --git a/Utilities/FLTK/src/flstring.h b/Utilities/FLTK/src/flstring.h new file mode 100644 index 0000000000..6e1fe36a81 --- /dev/null +++ b/Utilities/FLTK/src/flstring.h @@ -0,0 +1,115 @@ +/* + * "$Id$" + * + * Common string header file for the Fast Light Tool Kit (FLTK). + * + * Copyright 1998-2005 by Bill Spitzak and others. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems on the following page: + * + * http://www.fltk.org/str.php + */ + +#ifndef flstring_h +# define flstring_h + +# include <FL/Fl_Export.H> +/*# include <config.h>*/ +# include "fltk-config.h" + +# include <stdio.h> +# include <stdarg.h> +# include <string.h> +# ifdef HAVE_STRINGS_H +# include <strings.h> +# endif /* HAVE_STRINGS_H */ +# include <ctype.h> + +/* + * Apparently Unixware defines "index" to strchr (!) rather than + * providing a proper entry point or not providing the (obsolete) + * BSD function. Make sure index is not defined... + */ + +# ifdef index +# undef index +# endif /* index */ + +# if defined(WIN32) && !defined(__CYGWIN__) +# define strcasecmp(s,t) _stricmp((s), (t)) +# define strncasecmp(s,t,n) _strnicmp((s), (t), (n)) +// Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs +// on Windows, which is supposed to be POSIX compliant... Some of these functions +// are also defined in ISO C99... +# define strdup _strdup +# define unlink _unlink +# elif defined(__EMX__) +# define strcasecmp(s,t) stricmp((s), (t)) +# define strncasecmp(s,t,n) strnicmp((s), (t), (n)) +# endif /* WIN32 */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + +/* + * MetroWerks' CodeWarrior put thes "non-standard" functions in + * <extras.h> which unfortunatly does not play well otherwise + * when included - to be resolved... + */ + +# if defined(__APPLE__) && defined(__MWERKS__) && defined(_MSL_USING_MW_C_HEADERS) +int strcasecmp(const char*,const char*); +int strncasecmp(const char*,const char*,int); +char *strdup(const char*); +# endif + +FL_EXPORT extern int fl_snprintf(char *, size_t, const char *, ...); +# if !HAVE_SNPRINTF +# define snprintf fl_snprintf +# endif /* !HAVE_SNPRINTF */ + +FL_EXPORT extern int fl_vsnprintf(char *, size_t, const char *, va_list ap); +# if !HAVE_VSNPRINTF +# define vsnprintf fl_vsnprintf +# endif /* !HAVE_VSNPRINTF */ + +/* + * strlcpy() and strlcat() are some really useful BSD string functions + * that work the way strncpy() and strncat() *should* have worked. + */ + +FL_EXPORT extern size_t fl_strlcat(char *, const char *, size_t); +# if !HAVE_STRLCAT +# define strlcat fl_strlcat +# endif /* !HAVE_STRLCAT */ + +FL_EXPORT extern size_t fl_strlcpy(char *, const char *, size_t); +# if !HAVE_STRLCPY +# define strlcpy fl_strlcpy +# endif /* !HAVE_STRLCPY */ + +# ifdef __cplusplus +} +# endif /* __cplusplus */ +#endif /* !flstring_h */ + + +/* + * End of "$Id$". + */ diff --git a/Utilities/FLTK/src/forms_bitmap.cxx b/Utilities/FLTK/src/forms_bitmap.cxx new file mode 100644 index 0000000000..644d3b474c --- /dev/null +++ b/Utilities/FLTK/src/forms_bitmap.cxx @@ -0,0 +1,52 @@ +// +// "$Id$" +// +// Forms compatible bitmap function for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/forms.H> + +Fl_FormsBitmap::Fl_FormsBitmap( + Fl_Boxtype t, int X, int Y, int W, int H, const char* l) +: Fl_Widget(X, Y, W, H, l) { + box(t); + b = 0; + color(FL_BLACK); + align(FL_ALIGN_BOTTOM); +} + +void Fl_FormsBitmap::set(int W, int H, const uchar *bits) { + delete b; + bitmap(new Fl_Bitmap(bits, W, H)); +} + +void Fl_FormsBitmap::draw() { + draw_box(box(), selection_color()); + if (b) {fl_color(color()); b->draw(x(), y(), w(), h());} + draw_label(); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/forms_compatability.cxx b/Utilities/FLTK/src/forms_compatability.cxx new file mode 100755 index 0000000000..0fe44bacdd --- /dev/null +++ b/Utilities/FLTK/src/forms_compatability.cxx @@ -0,0 +1,211 @@ +// +// "$Id$" +// +// Forms compatibility functions for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Forms library compatability functions. +// Many more functions are defined as inlines in forms.h! + +#include <FL/forms.H> +#include <stdlib.h> + +char fl_flip = 2; +void fl_end_form() { + while (Fl_Group::current()) Fl_Group::current()->forms_end(); +} +void Fl_Group::forms_end() { + // set the dimensions of a group to surround contents + if (children() && !w()) { + Fl_Widget*const* a = array(); + Fl_Widget* o = *a++; + int rx = o->x(); + int ry = o->y(); + int rw = rx+o->w(); + int rh = ry+o->h(); + for (int i=children_-1; i--;) { + o = *a++; + if (o->x() < rx) rx = o->x(); + if (o->y() < ry) ry = o->y(); + if (o->x()+o->w() > rw) rw = o->x()+o->w(); + if (o->y()+o->h() > rh) rh = o->y()+o->h(); + } + x(rx); + y(ry); + w(rw-rx); + h(rh-ry); + } + // flip all the children's coordinate systems: + if (fl_flip) { + Fl_Widget* o = (type()>=FL_WINDOW) ? this : window(); + int Y = o->h(); + Fl_Widget*const* a = array(); + for (int i=children(); i--;) { + Fl_Widget* ow = *a++; + int newy = Y-ow->y()-ow->h(); + ow->y(newy); + } + } + end(); +} + +static int initargc; +static char **initargv; + +void fl_initialize(int *argc, char **argv, const char *, FL_CMD_OPT *, int) { + initargc = *argc; + initargv = new char*[*argc+1]; + int i,j; + for (i=0; i<=*argc; i++) initargv[i] = argv[i]; + for (i=j=1; i<*argc; ) { + if (Fl::arg(*argc,argv,i)); + else argv[j++] = argv[i++]; + } + argv[j] = 0; + *argc = j; + if (fl_flip==2) fl_flip = 0; +} + +char fl_modal_next; // set by fl_freeze_forms() + +void fl_show_form(Fl_Window *f,int place,int b,const char *n) { + + f->label(n); + if (!b) f->clear_border(); + if (fl_modal_next || b==FL_TRANSIENT) {f->set_modal(); fl_modal_next = 0;} + + if (place & FL_PLACE_MOUSE) f->hotspot(f); + + if (place & FL_PLACE_CENTER) { + int scr_x, scr_y, scr_w, scr_h; + Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h); + f->position(scr_x+(scr_w-f->w())/2, scr_y+(scr_h-f->h())/2); + } + + if (place & FL_PLACE_FULLSCREEN) + f->fullscreen(); + + if (place & (FL_PLACE_POSITION | FL_PLACE_GEOMETRY)) + f->position( + (f->x() < 0) ? Fl::w()-f->w()+f->x()-1 : f->x(), + (f->y() < 0) ? Fl::h()-f->h()+f->y()-1 : f->y()); + +// if (place & FL_PLACE_ASPECT) { +// this is not yet implemented +// it can be done by setting size_range(). + + if (place == FL_PLACE_FREE || place == FL_PLACE_SIZE) + f->free_position(); + + if (place == FL_PLACE_FREE || place & FL_FREE_SIZE) + if (!f->resizable()) f->resizable(f); + + if (initargc) {f->show(initargc,initargv); initargc = 0;} + else f->show(); +} + +Fl_Widget *fl_do_forms(void) { + Fl_Widget *obj; + while (!(obj = Fl::readqueue())) if (!Fl::wait()) exit(0); + return obj; +} + +Fl_Widget *fl_check_forms() { + Fl::check(); + return Fl::readqueue(); +} + +void fl_set_graphics_mode(int /*r*/,int /*d*/) {} + +void Fl_FormsText::draw() { + draw_box(); + align(align()|FL_ALIGN_INSIDE); // questionable method of compatability + draw_label(); +} + +// Create a forms button by selecting correct fltk subclass: + +#include <FL/Fl_Return_Button.H> +#include <FL/Fl_Repeat_Button.H> + +Fl_Button *fl_add_button(uchar t,int x,int y,int w,int h,const char *l) { + Fl_Button *b; + switch (t) { + case FL_RETURN_BUTTON: + case FL_HIDDEN_RET_BUTTON: + b = new Fl_Return_Button(x,y,w,h,l); + break; + case FL_TOUCH_BUTTON: + b = new Fl_Repeat_Button(x,y,w,h,l); + break; + default: + b = new Fl_Button(x,y,w,h,l); + } + switch (t) { + case FL_TOGGLE_BUTTON: + case FL_RADIO_BUTTON: + b->type(t); + break; + case FL_HIDDEN_BUTTON: + case FL_HIDDEN_RET_BUTTON: + b->type(FL_HIDDEN_BUTTON); + break; + case FL_INOUT_BUTTON: + b->when(FL_WHEN_CHANGED); + break; + } + return b; +} + +void fl_show_message(const char *q1,const char *q2,const char *q3) { + fl_message("%s\n%s\n%s", q1?q1:"", q2?q2:"", q3?q3:""); +} + +void fl_show_alert(const char *q1,const char *q2,const char *q3,int) { + fl_alert("%s\n%s\n%s", q1?q1:"", q2?q2:"", q3?q3:""); +} + +int fl_show_question(const char *q1,const char *q2,const char *q3) { + return fl_choice("%s\n%s\n%s", "No", "Yes", 0L, q1?q1:"", q2?q2:"", q3?q3:""); +} + +int fl_show_choice( + const char *q1, + const char *q2, + const char *q3, + int, // number of buttons, ignored + const char *b0, + const char *b1, + const char *b2) { + return fl_choice("%s\n%s\n%s", q1?q1:"", q2?q2:"", q3?q3:"", b0,b1,b2)+1; +} + +char *fl_show_simple_input(const char *str1, const char *defstr) { + const char *r = fl_input(str1, defstr); + return (char *)(r ? r : defstr); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/forms_free.cxx b/Utilities/FLTK/src/forms_free.cxx new file mode 100644 index 0000000000..5855f8b093 --- /dev/null +++ b/Utilities/FLTK/src/forms_free.cxx @@ -0,0 +1,81 @@ +// +// "$Id$" +// +// Forms free widget routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Emulation of the Forms "free" widget. +// This emulation allows the free demo to run, and has allowed +// me to port several other programs, but it is in no way +// complete. + +#include <FL/Fl.H> +#include <FL/Fl_Free.H> + +void Fl_Free::step(void *v) { + Fl_Free *f = (Fl_Free *)v; + int old_event = Fl::e_number; + f->handle(Fl::e_number == FL_STEP); + Fl::e_number = old_event; + Fl::add_timeout(.01,step,v); +} + +Fl_Free::Fl_Free(uchar t,int X, int Y, int W, int H,const char *l, + FL_HANDLEPTR hdl) : +Fl_Widget(X,Y,W,H,l) { + type(t); + hfunc = hdl; + if (t == FL_SLEEPING_FREE) set_flag(INACTIVE); + if (t == FL_CONTINUOUS_FREE || t == FL_ALL_FREE) + Fl::add_timeout(.01,step,this); +} + +Fl_Free::~Fl_Free() { + Fl::remove_timeout(step,this); + hfunc(this,FL_FREEMEM,0,0,0); +} + +void Fl_Free::draw() {hfunc(this,FL_DRAW,0,0,0);} + +int Fl_Free::handle(int e) { + char key = Fl::event_key(); + switch (e) { + case FL_FOCUS: + if (type()!=FL_INPUT_FREE && type()!=FL_ALL_FREE) return 0; + break; + case FL_PUSH: + case FL_DRAG: + case FL_RELEASE: + key = 4-Fl::event_button(); + break; + case FL_SHORTCUT: + return 0; + } + if (hfunc(this, e, float(Fl::event_x()), float(Fl::event_y()), key)) do_callback(); + return 1; +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/forms_fselect.cxx b/Utilities/FLTK/src/forms_fselect.cxx new file mode 100644 index 0000000000..f68a3db957 --- /dev/null +++ b/Utilities/FLTK/src/forms_fselect.cxx @@ -0,0 +1,67 @@ +// +// "$Id$" +// +// Forms file selection routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Emulate the Forms file chooser using the fltk file chooser. + +#include <FL/forms.H> +#include "flstring.h" + +static char fl_directory[1024]; +static const char *fl_pattern; // assummed passed value is static +static char fl_filename[1024]; + +char* fl_show_file_selector(const char *message,const char *dir, + const char *pat,const char *fname) { + if (dir && dir[0]) strlcpy(fl_directory,dir,sizeof(fl_directory)); + if (pat && pat[0]) fl_pattern = pat; + if (fname && fname[0]) strlcpy(fl_filename,fname,sizeof(fl_filename)); + char *p = fl_directory+strlen(fl_directory); + if (p > fl_directory && *(p-1)!='/' +#ifdef WIN32 + && *(p-1)!='\\' && *(p-1)!=':' +#endif + ) *p++ = '/'; + strlcpy(p,fl_filename,sizeof(fl_directory) - (p - fl_directory)); + const char *q = fl_file_chooser(message,fl_pattern,fl_directory); + if (!q) return 0; + strlcpy(fl_directory, q, sizeof(fl_directory)); + p = (char *)fl_filename_name(fl_directory); + strlcpy(fl_filename, p, sizeof(fl_filename)); + if (p > fl_directory+1) p--; + *p = 0; + return (char *)q; +} + +char* fl_get_directory() {return fl_directory;} + +char* fl_get_pattern() {return (char *)fl_pattern;} + +char* fl_get_filename() {return fl_filename;} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/forms_pixmap.cxx b/Utilities/FLTK/src/forms_pixmap.cxx new file mode 100644 index 0000000000..94419ae284 --- /dev/null +++ b/Utilities/FLTK/src/forms_pixmap.cxx @@ -0,0 +1,52 @@ +// +// "$Id$" +// +// Forms pixmap drawing routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/forms.H> + +Fl_FormsPixmap::Fl_FormsPixmap( + Fl_Boxtype t, int X, int Y, int W, int H, const char* l) +: Fl_Widget(X, Y, W, H, l) { + box(t); + b = 0; + color(FL_BLACK); + align(FL_ALIGN_BOTTOM); +} + +void Fl_FormsPixmap::set(char*const* bits) { + delete b; + b = new Fl_Pixmap(bits); +} + +void Fl_FormsPixmap::draw() { + draw_box(box(), selection_color()); + if (b) {fl_color(color()); b->draw(x(), y(), w(), h());} + draw_label(); +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/forms_timer.cxx b/Utilities/FLTK/src/forms_timer.cxx new file mode 100644 index 0000000000..031d67f271 --- /dev/null +++ b/Utilities/FLTK/src/forms_timer.cxx @@ -0,0 +1,169 @@ +// +// "$Id$" +// +// Forms timer object for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Emulate the Forms Timer object +// You don't want to use this if you just want a timeout, call +// Fl::add_timeout directly! + +#include <FL/Fl.H> +#include <FL/Fl_Timer.H> +#include <FL/fl_draw.H> +#ifdef WIN32 +# ifdef __MWERKS__ +# include <time.h> +# else +# include <sys/types.h> +# include <sys/timeb.h> +# endif +#else +# include <time.h> +# include <sys/time.h> +#endif +#include <stdio.h> + +#define FL_TIMER_BLINKRATE 0.2 + +void fl_gettime(long* sec, long* usec) { +#ifdef WIN32 +# ifdef __MWERKS__ + time_t localTime = time(NULL); + struct tm *now = localtime(&localTime); + *sec = now->tm_sec + 60*now->tm_min + 3600*now->tm_hour + 24*3600*now->tm_yday; + *usec = 0; +# else + struct timeb tp; + ftime(&tp); + *sec = tp.time; + *usec = tp.millitm * 1000; +# endif +#else + struct timeval tp; + struct timezone tzp; + gettimeofday(&tp, &tzp); + *sec = tp.tv_sec; + *usec = tp.tv_usec; +#endif +} + +void Fl_Timer::draw() { + int tt; + Fl_Color col; + char str[32]; + if (!on || delay>0.0) + col = color(); + else if ((int) (delay / FL_TIMER_BLINKRATE) % 2) + col = color(); + else + col = selection_color(); + draw_box(box(), col); + if (type() == FL_VALUE_TIMER && delay>0.0) { + double d = direction_ ? total-delay : delay; + if (d < 60.0) + sprintf(str, "%.1f", d); + else { + tt = (int) ((d+0.05) / 60.0); + sprintf(str, "%d:%04.1f", tt, d - 60.0 * tt); + } + fl_font(labelfont(), labelsize()); + fl_color(labelcolor()); + fl_draw(str, x(), y(), w(), h(), FL_ALIGN_CENTER); + } else + draw_label(); +} + +void Fl_Timer::stepcb(void* v) { + ((Fl_Timer*)v)->step(); +} + +void Fl_Timer::step() { + if (!on) return; + double lastdelay = delay; + long sec, usec; fl_gettime(&sec, &usec); + delay -= (double) (sec - lastsec) + (double) (usec - lastusec) / 1000000.0; + lastsec = sec; lastusec = usec; + if (lastdelay > 0.0 && delay <= 0.0) { + if (type() == FL_HIDDEN_TIMER) { + on = 0; + delay = 0; + } else { + redraw(); + Fl::add_timeout(FL_TIMER_BLINKRATE, stepcb, this); + } + set_changed(); + do_callback(); + } else { + if (type() == FL_VALUE_TIMER) redraw(); + Fl::add_timeout(FL_TIMER_BLINKRATE, stepcb, this); + } +} + +int Fl_Timer::handle(int event) { + if (event == FL_RELEASE && delay <= 0) value(0.0); + return 0; +} + +Fl_Timer::~Fl_Timer() { + Fl::remove_timeout(stepcb, this); +} + +Fl_Timer::Fl_Timer(uchar t, int X, int Y, int W, int H, const char* l) +: Fl_Widget(X, Y, W, H, l) { + box(FL_DOWN_BOX); + selection_color(FL_RED); + delay = 0; + on = 0; + direction_ = 0; + type(t); + if (t == FL_HIDDEN_TIMER) clear_visible(); + if (t == FL_VALUE_TIMER) align(FL_ALIGN_LEFT); +} + +void Fl_Timer::value(double d) { + delay = total = d; + on = (d > 0.0); + fl_gettime(&(lastsec), &(lastusec)); + if (type() != FL_HIDDEN_TIMER) redraw(); + Fl::remove_timeout(stepcb, this); + if (on) Fl::add_timeout(FL_TIMER_BLINKRATE, stepcb, this); +} + +void Fl_Timer::suspended(char d) { + if (!d) { + if (on) return; + on = (delay > 0.0); + fl_gettime(&(lastsec), &(lastusec)); + if (on) Fl::add_timeout(FL_TIMER_BLINKRATE, stepcb, this); + } else { + if (!on) return; + on = 0; + Fl::remove_timeout(stepcb, this); + } +} + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/gl_draw.cxx b/Utilities/FLTK/src/gl_draw.cxx new file mode 100644 index 0000000000..6eac7a7ed1 --- /dev/null +++ b/Utilities/FLTK/src/gl_draw.cxx @@ -0,0 +1,232 @@ +// +// "$Id$" +// +// OpenGL drawing support routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Functions from <FL/gl.h> +// See also Fl_Gl_Window and gl_start.cxx + +#include "flstring.h" +#if HAVE_GL + +#include <FL/Fl.H> +#include <FL/gl.h> +#include <FL/x.H> +#include <FL/fl_draw.H> +#include "Fl_Gl_Choice.H" +#include "Fl_Font.H" + +#if USE_XFT +extern XFontStruct* fl_xxfont(); +#endif // USE_XFT + +int gl_height() {return fl_height();} +int gl_descent() {return fl_descent();} +double gl_width(const char* s) {return fl_width(s);} +double gl_width(const char* s, int n) {return fl_width(s,n);} +double gl_width(uchar c) {return fl_width(c);} + +void gl_font(int fontid, int size) { + fl_font(fontid, size); + if (!fl_fontsize->listbase) { +#ifdef WIN32 + int base = fl_fontsize->metr.tmFirstChar; + int count = fl_fontsize->metr.tmLastChar-base+1; + HFONT oldFid = (HFONT)SelectObject(fl_gc, fl_fontsize->fid); + fl_fontsize->listbase = glGenLists(256); + wglUseFontBitmaps(fl_gc, base, count, fl_fontsize->listbase+base); + SelectObject(fl_gc, oldFid); +#elif defined(__APPLE_QD__) + // undefined characters automatically receive an empty GL list in aglUseFont + fl_fontsize->listbase = glGenLists(256); + aglUseFont(aglGetCurrentContext(), fl_fontsize->font, fl_fontsize->face, + fl_fontsize->size, 0, 256, fl_fontsize->listbase); +#elif defined(__APPLE_QUARTZ__) + short font, face, size; + uchar fn[256]; + fn[0]=strlen(fl_fontsize->q_name); + strcpy((char*)(fn+1), fl_fontsize->q_name); + GetFNum(fn, &font); + face = 0; + size = fl_fontsize->size; + fl_fontsize->listbase = glGenLists(256); + aglUseFont(aglGetCurrentContext(), font, face, + size, 0, 256, fl_fontsize->listbase); +#else +# if USE_XFT + fl_xfont = fl_xxfont(); +# endif // USE_XFT + int base = fl_xfont->min_char_or_byte2; + int count = fl_xfont->max_char_or_byte2-base+1; + fl_fontsize->listbase = glGenLists(256); + glXUseXFont(fl_xfont->fid, base, count, fl_fontsize->listbase+base); +#endif + } + glListBase(fl_fontsize->listbase); +} + + +void gl_remove_displaylist_fonts() +{ +# if HAVE_GL + + // clear variables used mostly in fl_font + fl_font_ = 0; + fl_size_ = 0; + + for (int j = 0 ; j < FL_FREE_FONT ; ++j) + { + Fl_FontSize* past = 0; + Fl_Fontdesc* s = fl_fonts + j ; + Fl_FontSize* f = s->first; + while (f != 0) { + if(f->listbase) { + if(f == s->first) { + s->first = f->next; + } + else { + past->next = f->next; + } + + // It would be nice if this next line was in a descturctor somewhere + glDeleteLists(f->listbase, 256); + + Fl_FontSize* tmp = f; + f = f->next; + delete tmp; + } + else { + past = f; + f = f->next; + } + } + } + +#endif +} + +#ifdef __APPLE__ +const char *fl_iso2macRoman(const char*, int); +#endif + +void gl_draw(const char* str, int n) { +#ifdef __APPLE__ + const char *txt = fl_iso2macRoman(str, n); + glCallLists(n, GL_UNSIGNED_BYTE, txt); +#else + glCallLists(n, GL_UNSIGNED_BYTE, str); +#endif +} + +void gl_draw(const char* str, int n, int x, int y) { + glRasterPos2i(x, y); + gl_draw(str, n); +} + +void gl_draw(const char* str, int n, float x, float y) { + glRasterPos2f(x, y); + gl_draw(str, n); +} + +void gl_draw(const char* str) { + gl_draw(str, strlen(str)); +} + +void gl_draw(const char* str, int x, int y) { + gl_draw(str, strlen(str), x, y); +} + +void gl_draw(const char* str, float x, float y) { + gl_draw(str, strlen(str), x, y); +} + +static void gl_draw_invert(const char* str, int n, int x, int y) { + glRasterPos2i(x, -y); + gl_draw(str, n); +} + +void gl_draw( + const char* str, // the (multi-line) string + int x, int y, int w, int h, // bounding box + Fl_Align align) { + fl_draw(str, x, -y-h, w, h, align, gl_draw_invert); +} + +void gl_measure(const char* str, int& x, int& y) {fl_measure(str,x,y);} + +void gl_rect(int x, int y, int w, int h) { + if (w < 0) {w = -w; x = x-w;} + if (h < 0) {h = -h; y = y-h;} + glBegin(GL_LINE_STRIP); + glVertex2i(x+w-1, y+h-1); + glVertex2i(x+w-1, y); + glVertex2i(x, y); + glVertex2i(x, y+h-1); + glVertex2i(x+w, y+h-1); + glEnd(); +} + +#if HAVE_GL_OVERLAY +extern uchar fl_overlay; +extern int fl_overlay_depth; +#endif + +void gl_color(Fl_Color i) { +#if HAVE_GL_OVERLAY +#ifdef WIN32 + if (fl_overlay && fl_overlay_depth) { + if (fl_overlay_depth < 8) { + // only black & white produce the expected colors. This could + // be improved by fixing the colormap set in Fl_Gl_Overlay.cxx + int size = 1<<fl_overlay_depth; + if (!i) glIndexi(size-2); + else if (i >= size-2) glIndexi(size-1); + else glIndexi(i); + } else { + glIndexi(i ? i : FL_GRAY_RAMP); + } + return; + } +#else + if (fl_overlay) {glIndexi(int(fl_xpixel(i))); return;} +#endif +#endif + uchar red, green, blue; + Fl::get_color(i, red, green, blue); + glColor3ub(red, green, blue); +} + +void gl_draw_image(const uchar* b, int x, int y, int w, int h, int d, int ld) { + if (!ld) ld = w*d; + glPixelStorei(GL_UNPACK_ROW_LENGTH, ld/d); + glRasterPos2i(x,y); + glDrawPixels(w,h,d<4?GL_RGB:GL_RGBA,GL_UNSIGNED_BYTE,(const ulong*)b); +} + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/gl_start.cxx b/Utilities/FLTK/src/gl_start.cxx new file mode 100644 index 0000000000..8714d2fea3 --- /dev/null +++ b/Utilities/FLTK/src/gl_start.cxx @@ -0,0 +1,136 @@ +// +// "$Id$" +// +// OpenGL context routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// You MUST use gl_visual() to select the default visual before doing +// show() of any windows. Mesa will crash if you try to use a visual +// not returned by glxChooseVisual. + +// This does not work with Fl_Double_Window's! It will try to draw +// into the front buffer. Depending on the system this will either +// crash or do nothing (when pixmaps are being used as back buffer +// and GL is being done by hardware), work correctly (when GL is done +// with software, such as Mesa), or draw into the front buffer and +// be erased when the buffers are swapped (when double buffer hardware +// is being used) + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#if HAVE_GL + +#include <FL/Fl.H> +#include <FL/Fl_Window.H> +#include <FL/x.H> +#include <FL/fl_draw.H> +#include "Fl_Gl_Choice.H" + +extern int fl_clip_state_number; // in fl_rect.cxx + +static GLContext context; +static int clip_state_number=-1; +static int pw, ph; + +#ifdef WIN32 +static Fl_Gl_Choice* gl_choice; +#endif + +#ifdef __APPLE__ +static Fl_Gl_Choice* gl_choice; +#endif + +Fl_Region XRectangleRegion(int x, int y, int w, int h); // in fl_rect.cxx + +void gl_start() { + if (!context) { +#ifdef WIN32 + if (!gl_choice) Fl::gl_visual(0); + context = fl_create_gl_context(Fl_Window::current(), gl_choice); +#elif defined(__APPLE_QD__) + // \todo Mac : We need to check the code and verify it with Apple Sample code. The 'shiny'-test should at least work with the software OpenGL emulator + context = fl_create_gl_context(Fl_Window::current(), gl_choice); +#elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + context = fl_create_gl_context(Fl_Window::current(), gl_choice); +#else + context = fl_create_gl_context(fl_visual); +#endif + } + fl_set_gl_context(Fl_Window::current(), context); +#if !defined(WIN32) && !defined(__APPLE__) + glXWaitX(); +#endif + if (pw != Fl_Window::current()->w() || ph != Fl_Window::current()->h()) { + pw = Fl_Window::current()->w(); + ph = Fl_Window::current()->h(); + glLoadIdentity(); + glViewport(0, 0, pw, ph); + glOrtho(0, pw, 0, ph, -1, 1); + glDrawBuffer(GL_FRONT); + } + if (clip_state_number != fl_clip_state_number) { + clip_state_number = fl_clip_state_number; + int x, y, w, h; + if (fl_clip_box(0, 0, Fl_Window::current()->w(), Fl_Window::current()->h(), + x, y, w, h)) { + fl_clip_region(XRectangleRegion(x,y,w,h)); + glScissor(x, Fl_Window::current()->h()-(y+h), w, h); + glEnable(GL_SCISSOR_TEST); + } else { + glDisable(GL_SCISSOR_TEST); + } + } +} + +void gl_finish() { + glFlush(); +#if !defined(WIN32) && !defined(__APPLE__) + glXWaitGL(); +#endif +} + +int Fl::gl_visual(int mode, int *alist) { + Fl_Gl_Choice *c = Fl_Gl_Choice::find(mode,alist); + if (!c) return 0; +#ifdef WIN32 + gl_choice = c; +#elif defined(__APPLE_QD__) + gl_choice = c; +#elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + gl_choice = c; +#else + fl_visual = c->vis; + fl_colormap = c->colormap; +#endif + return 1; +} + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/glut_compatability.cxx b/Utilities/FLTK/src/glut_compatability.cxx new file mode 100644 index 0000000000..2ab4844d1c --- /dev/null +++ b/Utilities/FLTK/src/glut_compatability.cxx @@ -0,0 +1,421 @@ +// +// "$Id$" +// +// GLUT emulation routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Emulation of Glut using fltk. + +// GLUT is Copyright (c) Mark J. Kilgard, 1994, 1995, 1996. +// "This program is freely distributable without licensing fees and is +// provided without guarantee or warrantee expressed or implied. This +// program is -not- in the public domain." + +// Although I have copied the GLUT API, none of my code is based on +// any Glut implementation details and is therefore covered by the LGPL. + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#if HAVE_GL + +#include <FL/glut.H> + +#define MAXWINDOWS 32 +static Fl_Glut_Window *windows[MAXWINDOWS+1]; + +Fl_Glut_Window *glut_window; +int glut_menu; +void (*glut_menustate_function)(int); +void (*glut_menustatus_function)(int,int,int); + +static void default_reshape(int w, int h) {glViewport(0,0,w,h);} +static void default_display() {} + +void Fl_Glut_Window::make_current() { + glut_window = this; + if (shown()) Fl_Gl_Window::make_current(); +} + +static int indraw; +void Fl_Glut_Window::draw() { + glut_window = this; + indraw = 1; + if (!valid()) {reshape(w(),h()); valid(1);} + display(); + indraw = 0; +} + +void glutSwapBuffers() { + if (!indraw) glut_window->swap_buffers(); +} + +void Fl_Glut_Window::draw_overlay() { + glut_window = this; + if (!valid()) {reshape(w(),h()); valid(1);} + overlaydisplay(); +} + +static void domenu(int, int, int); + +int Fl_Glut_Window::handle(int event) { + make_current(); + int ex = Fl::event_x(); + int ey = Fl::event_y(); + int button; + switch (event) { + + case FL_PUSH: + if (keyboard || special) Fl::focus(this); + button = Fl::event_button()-1; + if (button<0) button = 0; + if (button>2) button = 2; + if (menu[button]) {domenu(menu[button],ex,ey); return 1;} + mouse_down |= 1<<button; + if (mouse) {mouse(button,GLUT_DOWN,ex,ey); return 1;} + if (motion) return 1; + break; + + case FL_MOUSEWHEEL: + button = Fl::event_dy(); + while (button < 0) {mouse(3,GLUT_DOWN,ex,ey); ++button;} + while (button > 0) {mouse(4,GLUT_DOWN,ex,ey); --button;} + return 1; + break; + + case FL_RELEASE: + for (button = 0; button < 3; button++) if (mouse_down & (1<<button)) { + if (mouse) mouse(button,GLUT_UP,ex,ey); + } + mouse_down = 0; + return 1; + + case FL_ENTER: + if (entry) {entry(GLUT_ENTERED); return 1;} + if (passivemotion) return 1; + break; + + case FL_LEAVE: + if (entry) {entry(GLUT_LEFT); return 1;} + if (passivemotion) return 1; + break; + + case FL_DRAG: + if (motion) {motion(ex, ey); return 1;} + break; + + case FL_MOVE: + if (passivemotion) {passivemotion(ex, ey); return 1;} + break; + + case FL_FOCUS: + if (keyboard || special) return 1; + break; + + case FL_SHORTCUT: + if (!keyboard && !special) break; + + case FL_KEYBOARD: + if (Fl::event_text()[0]) { + if (keyboard) {keyboard(Fl::event_text()[0],ex,ey); return 1;} + break; + } else { + if (special) { + int k = Fl::event_key(); + if (k > FL_F && k <= FL_F_Last) k -= FL_F; + special(k,ex,ey); + return 1; + } + break; + } + + case FL_HIDE: + if (visibility) visibility(GLUT_NOT_VISIBLE); + break; + + case FL_SHOW: + if (visibility) visibility(GLUT_VISIBLE); + break; + } + + return Fl_Gl_Window::handle(event); +} + +static int glut_mode = GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH; + +void Fl_Glut_Window::_init() { + for (number=1; number<MAXWINDOWS; number++) if (!windows[number]) break; + windows[number] = this; + menu[0] = menu[1] = menu[2] = 0; + reshape = default_reshape; + display = default_display; + overlaydisplay = default_display; + keyboard = 0; + mouse = 0; + motion = 0; + passivemotion = 0; + entry = 0; + visibility = 0; + special = 0; + mouse_down = 0; + mode(glut_mode); +} + +Fl_Glut_Window::Fl_Glut_Window(int W, int H, const char *t) : + Fl_Gl_Window(W,H,t) {_init();} + +Fl_Glut_Window::Fl_Glut_Window(int X,int Y,int W,int H, const char *t) : + Fl_Gl_Window(X,Y,W,H,t) {_init();} + +static int initargc; +static char **initargv; + +void glutInit(int *argc, char **argv) { + initargc = *argc; + initargv = new char*[*argc+1]; + int i,j; + for (i=0; i<=*argc; i++) initargv[i] = argv[i]; + for (i=j=1; i<*argc; ) { + if (Fl::arg(*argc,argv,i)); + else argv[j++] = argv[i++]; + } + argv[j] = 0; + *argc = j; +} + +void glutInitDisplayMode(unsigned int mode) { + glut_mode = mode; +} + +void glutMainLoop() {Fl::run();} + +//////////////////////////////////////////////////////////////// + +static int initx, inity, initw=300, inith=300, initpos; + +void glutInitWindowPosition(int x, int y) { + initx = x; inity = y; initpos = 1; +} + +void glutInitWindowSize(int w, int h) { + initw = w; inith = h; +} + +int glutCreateWindow(char *title) { + Fl_Glut_Window *W; + if (initpos) { + W = new Fl_Glut_Window(initx,inity,initw,inith,title); + initpos = 0; + } else { + W = new Fl_Glut_Window(initw,inith,title); + } + W->resizable(W); + if (initargc) { + W->show(initargc,initargv); + initargc = 0; + } else { + W->show(); + } + W->make_current(); + return W->number; +} + +int glutCreateSubWindow(int win, int x, int y, int w, int h) { + Fl_Glut_Window *W = new Fl_Glut_Window(x,y,w,h,0); + windows[win]->add(W); + if (windows[win]->shown()) W->show(); + W->make_current(); + return W->number; +} + +Fl_Glut_Window::~Fl_Glut_Window() { + if (glut_window == this) glut_window = 0; + windows[number] = 0; +} + +void glutDestroyWindow(int win) { + // should destroy children!!! + delete windows[win]; +} + +void glutSetWindow(int win) { + windows[win]->make_current(); +} + +//////////////////////////////////////////////////////////////// +#include <FL/Fl_Menu_Item.H> + +struct menu { + void (*cb)(int); + Fl_Menu_Item *m; + int size; + int alloc; +}; + +#define MAXMENUS 32 +static menu menus[MAXMENUS+1]; + +static void domenu(int n, int ex, int ey) { + glut_menu = n; + menu *m = &menus[n]; + if (glut_menustate_function) glut_menustate_function(1); + if (glut_menustatus_function) glut_menustatus_function(1,ex,ey); + const Fl_Menu_Item* g = m->m->popup(Fl::event_x(), Fl::event_y(), 0); + if (g && g->callback_) ((void (*)(int))(g->callback_))(int(g->argument())); + if (glut_menustatus_function) glut_menustatus_function(0,ex,ey); + if (glut_menustate_function) glut_menustate_function(0); +} + +int glutCreateMenu(void (*cb)(int)) { + int i; + for (i=1; i<MAXMENUS; i++) if (!menus[i].cb) break; + menu *m = &menus[i]; + m->cb = cb; + return glut_menu = i; +} + +void glutDestroyMenu(int n) { + menu *m = &menus[n]; + delete[] m->m; + m->m = 0; + m->cb = 0; + m->size = m->alloc = 0; +} + +static Fl_Menu_Item* additem(menu *m) { + if (m->size+1 >= m->alloc) { + m->alloc = m->size*2+10; + Fl_Menu_Item* nm = new Fl_Menu_Item[m->alloc]; + for (int i=0; i<m->size; i++) nm[i] = m->m[i]; + delete[] m->m; + m->m = nm; + } + int n = m->size++; + m->m[n+1].text = 0; + Fl_Menu_Item* i = &(m->m[n]); + i->shortcut_ = 0; + i->flags = 0; + i->labeltype_ = i->labelfont_ = i->labelsize_ = i->labelcolor_ = 0; + return i; +} + +void glutAddMenuEntry(char *label, int value) { + menu *m = &menus[glut_menu]; + Fl_Menu_Item* i = additem(m); + i->text = label; + i->callback_ = (Fl_Callback*)(m->cb); + i->user_data_ = (void *)value; +} + +void glutAddSubMenu(char *label, int submenu) { + menu *m = &menus[glut_menu]; + Fl_Menu_Item* i = additem(m); + i->text = label; + i->callback_ = 0; + i->user_data_ = (void *)(menus[submenu].m); + i->flags = FL_PUP_SUBMENU; +} + +void glutChangeToMenuEntry(int item, char *label, int value) { + menu *m = &menus[glut_menu]; + Fl_Menu_Item* i = &m->m[item-1]; + i->text = label; + i->callback_ = (Fl_Callback*)(m->cb); + i->user_data_ = (void *)value; + i->flags = 0; +} + +void glutChangeToSubMenu(int item, char *label, int submenu) { + menu *m = &menus[glut_menu]; + Fl_Menu_Item* i = &m->m[item-1]; + i->text = label; + i->callback_ = 0; + i->user_data_ = (void *)(menus[submenu].m); + i->flags = FL_PUP_SUBMENU; +} + +void glutRemoveMenuItem(int item) { + menu *m = &menus[glut_menu]; + if (item > m->size || item < 1) return; + for (int i = item-1; i <= m->size; i++) m->m[i] = m->m[i+1]; + m->size--; +} + +//////////////////////////////////////////////////////////////// + +int glutGet(GLenum type) { + switch (type) { + case GLUT_RETURN_ZERO: return 0; + case GLUT_WINDOW_X: return glut_window->x(); + case GLUT_WINDOW_Y: return glut_window->y(); + case GLUT_WINDOW_WIDTH: return glut_window->w(); + case GLUT_WINDOW_HEIGHT: return glut_window->h(); + case GLUT_WINDOW_PARENT: + if (glut_window->parent()) + return ((Fl_Glut_Window *)(glut_window->parent()))->number; + else + return 0; +//case GLUT_WINDOW_NUM_CHILDREN: +//case GLUT_WINDOW_CURSOR: return + case GLUT_SCREEN_WIDTH: return Fl::w(); + case GLUT_SCREEN_HEIGHT: return Fl::h(); +//case GLUT_SCREEN_WIDTH_MM: +//case GLUT_SCREEN_HEIGHT_MM: + case GLUT_MENU_NUM_ITEMS: return menus[glut_menu].size; + case GLUT_DISPLAY_MODE_POSSIBLE: return Fl_Gl_Window::can_do(glut_mode); + case GLUT_INIT_WINDOW_X: return initx; + case GLUT_INIT_WINDOW_Y: return inity; + case GLUT_INIT_WINDOW_WIDTH: return initw; + case GLUT_INIT_WINDOW_HEIGHT: return inith; + case GLUT_INIT_DISPLAY_MODE: return glut_mode; +//case GLUT_ELAPSED_TIME: + case GLUT_WINDOW_BUFFER_SIZE: + if (glutGet(GLUT_WINDOW_RGBA)) + return glutGet(GLUT_WINDOW_RED_SIZE)+ + glutGet(GLUT_WINDOW_GREEN_SIZE)+ + glutGet(GLUT_WINDOW_BLUE_SIZE)+ + glutGet(GLUT_WINDOW_ALPHA_SIZE); + else + return glutGet(GLUT_WINDOW_COLORMAP_SIZE); + default: {GLint p; glGetIntegerv(type, &p); return p;} + } +} + +int glutLayerGet(GLenum type) { + switch (type) { + case GLUT_OVERLAY_POSSIBLE: return glut_window->can_do_overlay(); +//case GLUT_LAYER_IN_USE: +//case GLUT_HAS_OVERLAY: + case GLUT_TRANSPARENT_INDEX: return 0; // true for SGI + case GLUT_NORMAL_DAMAGED: return glut_window->damage(); + case GLUT_OVERLAY_DAMAGED: return 1; // kind of works... + default: return 0; + } +} + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/glut_font.cxx b/Utilities/FLTK/src/glut_font.cxx new file mode 100644 index 0000000000..d5662dca37 --- /dev/null +++ b/Utilities/FLTK/src/glut_font.cxx @@ -0,0 +1,62 @@ +// +// "$Id$" +// +// GLUT bitmap font routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// (sort of) emulation of Glut's bitmap drawing functions, using FL's +// font stuff. Not all the fonts match! + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#if HAVE_GL + +#include <FL/glut.H> +#include <FL/gl.h> + +Glut_Bitmap_Font glutBitmap9By15 = {FL_SCREEN, 15}; +Glut_Bitmap_Font glutBitmap8By13 = {FL_SCREEN, 13}; +Glut_Bitmap_Font glutBitmapTimesRoman10 = {FL_TIMES, 10}; +Glut_Bitmap_Font glutBitmapTimesRoman24 = {FL_TIMES, 24}; +Glut_Bitmap_Font glutBitmapHelvetica10 = {FL_HELVETICA, 10}; +Glut_Bitmap_Font glutBitmapHelvetica12 = {FL_HELVETICA, 12}; +Glut_Bitmap_Font glutBitmapHelvetica18 = {FL_HELVETICA, 18}; + +void glutBitmapCharacter(void* font, int character) { + gl_font(((Glut_Bitmap_Font *)font)->font,((Glut_Bitmap_Font *)font)->size); + char a[1]; a[0] = character; + gl_draw(a,1); +} + +int glutBitmapWidth(void* font, int character) { + gl_font(((Glut_Bitmap_Font *)font)->font,((Glut_Bitmap_Font *)font)->size); + return int(gl_width(character)+.5); +} + +#endif + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/makefile.wat b/Utilities/FLTK/src/makefile.wat new file mode 100644 index 0000000000..6266889eb6 --- /dev/null +++ b/Utilities/FLTK/src/makefile.wat @@ -0,0 +1,226 @@ +# +# "$Id: makefile.wat 4359 2005-05-19 16:07:13Z mike $" +# +# Library makefile for the Fast Light Tool Kit (FLTK). +# +# Copyright 1998-2004 by Bill Spitzak and others. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. +# +# Please report all bugs and problems to "fltk-bugs@fltk.org". +# + +CPPFILES = & + Fl.obj & + Fl_Adjuster.obj & + Fl_Bitmap.obj & + Fl_Browser.obj & + Fl_Browser_.obj & + Fl_Browser_load.obj & + Fl_Box.obj & + Fl_Button.obj & + Fl_Chart.obj & + Fl_Check_Browser.obj & + Fl_Check_Button.obj & + Fl_Choice.obj & + Fl_Clock.obj & + Fl_Color_Chooser.obj & + Fl_Counter.obj & + Fl_Dial.obj & + Fl_Double_Window.obj & + Fl_File_Browser.obj & + Fl_File_Chooser.obj & + Fl_File_Chooser2.obj & + Fl_File_Icon.obj & + Fl_File_Input.obj & + Fl_Group.obj & + Fl_Help_View.obj & + Fl_Image.obj & + Fl_Input.obj & + Fl_Input_.obj & + Fl_Light_Button.obj & + Fl_Menu.obj & + Fl_Menu_.obj & + Fl_Menu_Bar.obj & + Fl_Sys_Menu_Bar.obj & + Fl_Menu_Button.obj & + Fl_Menu_Window.obj & + Fl_Menu_add.obj & + Fl_Menu_global.obj & + Fl_Multi_Label.obj & + Fl_Overlay_Window.obj & + Fl_Pack.obj & + Fl_Pixmap.obj & + Fl_Positioner.obj & + Fl_Preferences.obj & + Fl_Progress.obj & + Fl_Repeat_Button.obj & + Fl_Return_Button.obj & + Fl_Roller.obj & + Fl_Round_Button.obj & + Fl_Scroll.obj & + Fl_Scrollbar.obj & + Fl_Shared_Image.obj & + Fl_Single_Window.obj & + Fl_Slider.obj & + Fl_Tabs.obj & + Fl_Text_Buffer.obj & + Fl_Text_Display.obj & + Fl_Text_Editor.obj & + Fl_Tile.obj & + Fl_Tiled_Image.obj & + Fl_Tooltip.obj & + Fl_Valuator.obj & + Fl_Value_Input.obj & + Fl_Value_Output.obj & + Fl_Value_Slider.obj & + Fl_Widget.obj & + Fl_Window.obj & + Fl_Window_fullscreen.obj & + Fl_Window_hotspot.obj & + Fl_Window_iconize.obj & + Fl_Wizard.obj & + Fl_XBM_Image.obj & + Fl_XPM_Image.obj & + Fl_abort.obj & + Fl_add_idle.obj & + Fl_arg.obj & + Fl_compose.obj & + Fl_display.obj & + Fl_get_key.obj & + Fl_get_system_colors.obj & + Fl_grab.obj & + Fl_lock.obj & + Fl_own_colormap.obj & + Fl_visual.obj & + Fl_x.obj & + filename_absolute.obj & + filename_expand.obj & + filename_ext.obj & + filename_isdir.obj & + filename_list.obj & + filename_match.obj & + filename_setext.obj & + fl_arc.obj & + fl_arci.obj & + fl_ask.obj & + fl_boxtype.obj & + fl_color.obj & + fl_cursor.obj & + fl_curve.obj & + fl_diamond_box.obj & + fl_dnd.obj & + fl_draw.obj & + fl_draw_image.obj & + fl_draw_pixmap.obj & + fl_engraved_label.obj & + fl_file_dir.obj & + fl_font.obj & + fl_labeltype.obj & + fl_line_style.obj & + fl_oval_box.obj & + fl_overlay.obj & + fl_overlay_visual.obj & + fl_plastic.obj & + fl_read_image.obj & + fl_rect.obj & + fl_round_box.obj & + fl_rounded_box.obj & + fl_set_font.obj & + fl_set_fonts.obj & + fl_scroll_area.obj & + fl_shadow_box.obj & + fl_shortcut.obj & + fl_show_colormap.obj & + fl_symbols.obj & + fl_vertex.obj + +FLCPPFILES = & + forms_compatability.obj & + forms_bitmap.obj & + forms_free.obj & + forms_fselect.obj & + forms_pixmap.obj & + forms_timer.obj + +GLCPPFILES = & + Fl_Gl_Choice.obj & + Fl_Gl_Overlay.obj & + Fl_Gl_Window.obj & + gl_draw.obj & + gl_start.obj & + glut_compatability.obj & + glut_font.obj + +IMGCPPFILES = & + fl_images_core.obj & + Fl_BMP_Image.obj & + Fl_File_Icon2.obj & + Fl_GIF_Image.obj & + Fl_Help_Dialog.obj & + Fl_JPEG_Image.obj & + Fl_PNG_Image.obj & + Fl_PNM_Image.obj + +CFILES = fl_call_main.obj flstring.obj scandir.obj numericsort.obj vsnprintf.obj + +################################################################ + +!include ../watcom.mif + +OBJECTS = $(CPPFILES) $(CFILES) +FLOBJECTS = $(FLCPPFILES) +GLOBJECTS = $(GLCPPFILES) +IMGOBJECTS = $(IMGCPPFILES) + +# The four basic fltk libraries are defined in ../watcom.mif, so that appliactions +# can also use them. +all: $(LIBNAME) & + $(LIBNAMEFL) & + $(LIBNAMEGL) & + $(LIBNAMEIMG) + +# $(DSONAME) & +# $(FLDSONAME) & +# $(GLDSONAME) & +# $(IMGDSONAME) + + +$(LIBNAME): $(OBJECTS) + $(LIB) $(LIBOPTS) $@ $< + +$(LIBNAMEFL): $(FLOBJECTS) + $(LIB) $(LIBOPTS) $@ $< + +$(LIBNAMEGL): $(GLOBJECTS) + $(LIB) $(LIBOPTS) $@ $< + +$(LIBNAMEIMG): $(IMGOBJECTS) + $(LIB) $(LIBOPTS) $@ $< + +# +# Clean all directories +# +clean : .SYMBOLIC + @echo Cleaning up. +CLEANEXTS = exe map sym obj lk1 + @for %a in ($(CLEANEXTS)) do -rm -f $(ODIR)\*.%a + -rm -f *.err + -rm -f $(LIBNAME) + -rm -f $(LIBNAMEFL) + -rm -f $(LIBNAMEGL) + -rm -f $(LIBNAMEIMG) + diff --git a/Utilities/FLTK/src/mediumarrow.h b/Utilities/FLTK/src/mediumarrow.h new file mode 100644 index 0000000000..8a1fe8cbcf --- /dev/null +++ b/Utilities/FLTK/src/mediumarrow.h @@ -0,0 +1,6 @@ +#define mediumarrow_width 16 +#define mediumarrow_height 16 +static unsigned char mediumarrow_bits[] = { + 0x40, 0x00, 0x60, 0x00, 0x70, 0x00, 0x78, 0x00, 0xfc, 0x3f, 0x78, 0x00, + 0x70, 0x00, 0x60, 0x02, 0x40, 0x06, 0x00, 0x0e, 0x00, 0x1e, 0xfc, 0x3f, + 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x02}; diff --git a/Utilities/FLTK/src/new.xbm b/Utilities/FLTK/src/new.xbm new file mode 100644 index 0000000000..25a56c5939 --- /dev/null +++ b/Utilities/FLTK/src/new.xbm @@ -0,0 +1,6 @@ +#define new_width 16 +#define new_height 16 +static unsigned char new_bits[] = { + 0x00, 0x00, 0x78, 0x00, 0x84, 0x00, 0x02, 0x01, 0x01, 0xfe, 0x01, 0x80, + 0x31, 0x80, 0x31, 0x80, 0xfd, 0x80, 0xfd, 0x80, 0x31, 0x80, 0x31, 0x80, + 0x01, 0x80, 0x01, 0x80, 0xff, 0xff, 0x00, 0x00}; diff --git a/Utilities/FLTK/src/ns.xbm b/Utilities/FLTK/src/ns.xbm new file mode 100644 index 0000000000..f1ea18e1b4 --- /dev/null +++ b/Utilities/FLTK/src/ns.xbm @@ -0,0 +1,8 @@ +#define ns_width 16 +#define ns_height 16 +#define ns_x_hot 8 +#define ns_y_hot 8 +static unsigned char ns_bits[] = { + 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0x80, 0x01, 0x80, 0x01, + 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, + 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00}; diff --git a/Utilities/FLTK/src/ns_mask.xbm b/Utilities/FLTK/src/ns_mask.xbm new file mode 100644 index 0000000000..a69f261bb4 --- /dev/null +++ b/Utilities/FLTK/src/ns_mask.xbm @@ -0,0 +1,8 @@ +#define ns_mask_width 16 +#define ns_mask_height 16 +#define ns_mask_x_hot 8 +#define ns_mask_y_hot 8 +static unsigned char ns_mask_bits[] = { + 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf0, 0x0f, 0xc0, 0x03, + 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xf0, 0x0f, + 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01}; diff --git a/Utilities/FLTK/src/numericsort.c b/Utilities/FLTK/src/numericsort.c new file mode 100644 index 0000000000..95e878100c --- /dev/null +++ b/Utilities/FLTK/src/numericsort.c @@ -0,0 +1,112 @@ +/* + * "$Id$" + * + * Numeric sorting routine for the Fast Light Tool Kit (FLTK). + * + * Copyright 1998-2005 by Bill Spitzak and others. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems on the following page: + * + * http://www.fltk.org/str.php + */ + +/* My own scandir sorting function, useful for the film industry where + we have many files with numbers in their names: */ + +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" +#include <stdlib.h> +#include <sys/types.h> + +#include <FL/filename.H> + +#if !defined(WIN32) || defined(__CYGWIN__) +# ifdef HAVE_DIRENT_H +# include <dirent.h> +# else +# define dirent direct +# if HAVE_SYS_NDIR_H +# include <sys/ndir.h> +# endif /* HAVE_SYS_NDIR_H */ +# if HAVE_SYS_DIR_H +# include <sys/dir.h> +# endif /* HAVE_SYS_DIR_H */ +# if HAVE_NDIR_H +# include <ndir.h> +# endif /* HAVE_NDIR_H */ +# endif /* HAVE_DIRENT_H */ +#endif /* !WIN32 || __CYGWIN__ */ + +/* + * 'numericsort()' - Compare two directory entries, possibly with + * a case-insensitive comparison... + */ + +static int numericsort(struct dirent **A, struct dirent **B, int cs) { + const char* a = (*A)->d_name; + const char* b = (*B)->d_name; + int ret = 0; + for (;;) { + if (isdigit(*a & 255) && isdigit(*b & 255)) { + int diff,magdiff; + while (*a == '0') a++; + while (*b == '0') b++; + while (isdigit(*a & 255) && *a == *b) {a++; b++;} + diff = (isdigit(*a & 255) && isdigit(*b & 255)) ? *a - *b : 0; + magdiff = 0; + while (isdigit(*a & 255)) {magdiff++; a++;} + while (isdigit(*b & 255)) {magdiff--; b++;} + if (magdiff) {ret = magdiff; break;} /* compare # of significant digits*/ + if (diff) {ret = diff; break;} /* compare first non-zero digit */ + } else { + if (cs) { + /* compare case-sensitive */ + if ((ret = *a-*b)) break; + } else { + /* compare case-insensitve */ + if ((ret = tolower(*a & 255)-tolower(*b & 255))) break; + } + + if (!*a) break; + a++; b++; + } + } + if (!ret) return 0; + else return (ret < 0) ? -1 : 1; +} + +/* + * 'fl_casenumericsort()' - Compare directory entries with case-sensitivity. + */ + +int fl_casenumericsort(struct dirent **A, struct dirent **B) { + return numericsort(A, B, 0); +} + +/* + * 'fl_numericsort()' - Compare directory entries with case-sensitivity. + */ + +int fl_numericsort(struct dirent **A, struct dirent **B) { + return numericsort(A, B, 1); +} + +/* + * End of "$Id$". + */ diff --git a/Utilities/FLTK/src/scandir.c b/Utilities/FLTK/src/scandir.c new file mode 100644 index 0000000000..197f63fd6c --- /dev/null +++ b/Utilities/FLTK/src/scandir.c @@ -0,0 +1,124 @@ +/* Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA. */ + +#if defined(WIN32) && !defined(__CYGWIN__) +# include "scandir_win32.c" +#else + +# include "flstring.h" + +# if !HAVE_SCANDIR +# include <stdlib.h> +# include <sys/types.h> +# include <errno.h> + +# if HAVE_DIRENT_H +# include <dirent.h> +# define NAMLEN(dirent) strlen((dirent)->d_name) +# else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if HAVE_SYS_NDIR_H +# include <sys/ndir.h> +# endif +# if HAVE_SYS_DIR_H +# include <sys/dir.h> +# endif +# if HAVE_NDIR_H +# include <ndir.h> +# endif +# endif + +int +fl_scandir(const char *dir, struct dirent ***namelist, + int (*select)(struct dirent *), + int (*compar)(struct dirent **, struct dirent **)) +{ + DIR *dp = opendir (dir); + struct dirent **v = NULL; + size_t vsize = 0, i; + struct dirent *d; + int save; + + if (dp == NULL) + return -1; + + save = errno; + errno = 0; + + i = 0; + while ((d = readdir (dp)) != NULL) + if (select == NULL || (*select) (d)) + { + size_t dsize; + + if (i == vsize) + { + struct dirent **newv; + if (vsize == 0) + vsize = 10; + else + vsize *= 2; + newv = (struct dirent **) realloc (v, vsize * sizeof (*v)); + if (newv == NULL) + { + lose: + errno = ENOMEM; + break; + } + v = newv; + } + +# define _D_EXACT_NAMLEN(d) (strlen ((d)->d_name)) +# define _D_ALLOC_NAMLEN(d) (sizeof (d)->d_name > 1 ? sizeof (d)->d_name : \ + _D_EXACT_NAMLEN (d) + 1) + + dsize = &d->d_name[_D_ALLOC_NAMLEN (d)] - (char *) d; + v[i] = (struct dirent *) malloc (dsize); + if (v[i] == NULL) + goto lose; + + memcpy (v[i++], d, dsize); + } + + if (errno != 0) + { + save = errno; + (void) closedir (dp); + while (i > 0) + free (v[--i]); + free (v); + errno = save; + return -1; + } + + (void) closedir (dp); + errno = save; + + /* Sort the list if we have a comparison function to sort with. */ + if (compar) qsort (v, i, sizeof (*v), (int (*)(const void *, const void *))compar); + *namelist = v; + return i; +} + +# endif +#endif + +/* + * End of "$Id$". + */ diff --git a/Utilities/FLTK/src/scandir_win32.c b/Utilities/FLTK/src/scandir_win32.c new file mode 100644 index 0000000000..00d0b8e6a7 --- /dev/null +++ b/Utilities/FLTK/src/scandir_win32.c @@ -0,0 +1,115 @@ +/* + * "$Id$" + * + * WIN32 scandir function for the Fast Light Tool Kit (FLTK). + * + * Copyright 1998-2005 by Bill Spitzak and others. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems on the following page: + * + * http://www.fltk.org/str.php + */ + +#ifndef __CYGWIN__ +/* Emulation of posix scandir() call */ + +#include <FL/filename.H> +#include "flstring.h" +#include <windows.h> +#include <stdlib.h> + +int fl_scandir(const char *dirname, struct dirent ***namelist, + int (*select)(struct dirent *), + int (*compar)(struct dirent **, struct dirent **)) { + int len; + char *findIn, *d, is_dir = 0; + WIN32_FIND_DATA find; + HANDLE h; + int nDir = 0, NDir = 0; + struct dirent **dir = 0, *selectDir; + unsigned long ret; + + len = strlen(dirname); + findIn = (char *)malloc((size_t)(len+5)); + + if (!findIn) return -1; + + strcpy(findIn, dirname); + for (d = findIn; *d; d++) if (*d=='/') *d='\\'; + if ((len==0)) { strcpy(findIn, ".\\*"); } + if ((len==2)&&findIn[1]==':'&&isalpha(findIn[0])) { *d++ = '\\'; *d = 0; } + if ((len==1)&& (d[-1]=='.')) { strcpy(findIn, ".\\*"); is_dir = 1; } + if ((len>0) && (d[-1]=='\\')) { *d++ = '*'; *d = 0; is_dir = 1; } + if ((len>1) && (d[-1]=='.') && (d[-2]=='\\')) { d[-1] = '*'; is_dir = 1; } + if (!is_dir) { /* this file may still be a directory that we need to list */ + DWORD attr = GetFileAttributes(findIn); + if (attr&FILE_ATTRIBUTE_DIRECTORY) + strcpy(d, "\\*"); + } + if ((h=FindFirstFile(findIn, &find))==INVALID_HANDLE_VALUE) { + free(findIn); + ret = GetLastError(); + if (ret != ERROR_NO_MORE_FILES) { + nDir = -1; + } + *namelist = dir; + return nDir; + } + do { + selectDir=(struct dirent*)malloc(sizeof(struct dirent)+strlen(find.cFileName)+2); + strcpy(selectDir->d_name, find.cFileName); + if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + /* Append a trailing slash to directory names... */ + strcat(selectDir->d_name, "/"); + } + if (!select || (*select)(selectDir)) { + if (nDir==NDir) { + struct dirent **tempDir = (struct dirent **)calloc(sizeof(struct dirent*), (size_t)(NDir+33)); + if (NDir) memcpy(tempDir, dir, sizeof(struct dirent*)*NDir); + if (dir) free(dir); + dir = tempDir; + NDir += 32; + } + dir[nDir] = selectDir; + nDir++; + dir[nDir] = 0; + } else { + free(selectDir); + } + } while (FindNextFile(h, &find)); + ret = GetLastError(); + if (ret != ERROR_NO_MORE_FILES) { + /* don't return an error code, because the dir list may still be valid + up to this point */ + } + FindClose(h); + + free (findIn); + + if (compar) qsort(dir, (size_t)nDir, sizeof(*dir), + (int(*)(const void*, const void*))compar); + + *namelist = dir; + return nDir; +} + +#endif + +/* + * End of "$Id$". + */ diff --git a/Utilities/FLTK/src/screen_xywh.cxx b/Utilities/FLTK/src/screen_xywh.cxx new file mode 100644 index 0000000000..6ee7136ab4 --- /dev/null +++ b/Utilities/FLTK/src/screen_xywh.cxx @@ -0,0 +1,242 @@ +// +// "$Id$" +// +// Screen/monitor bounding box API for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2005 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + + +#include <FL/Fl.H> +#include <FL/x.H> +/*OTB Modifications: conflict name with OTB/Utilities/ITK/Utilities/nifti/znzlib/config.h*/ +/*#include <config.h>*/ +#include "fltk-config.h" + +// Number of screens... +static int num_screens = 0; + +#ifdef WIN32 +# if !defined(HMONITOR_DECLARED) && (_WIN32_WINNT < 0x0500) +# define COMPILE_MULTIMON_STUBS +# include <multimon.h> +# endif // !HMONITOR_DECLARED && _WIN32_WINNT < 0x0500 + +// BOOL EnumDisplayMonitors(HDC, LPCRECT, MONITORENUMPROC, LPARAM) +typedef BOOL (*fl_edm_func)(HDC, LPCRECT, MONITORENUMPROC, LPARAM); +// BOOL GetMonitorInfo(HMONITOR, LPMONITORINFO) +typedef BOOL (*fl_gmi_func)(HMONITOR, LPMONITORINFO); + +static fl_gmi_func fl_gmi = NULL; // used to get a proc pointer for GetMonitorInfoA + +static RECT screens[16]; + +static BOOL CALLBACK screen_cb(HMONITOR mon, HDC, LPRECT, LPARAM) { + if (num_screens >= 16) return TRUE; + + MONITORINFO mi; + mi.cbSize = sizeof(mi); + +// GetMonitorInfo(mon, &mi); + fl_gmi(mon, &mi); + + screens[num_screens] = mi.rcWork; + num_screens ++; + return TRUE; +} + +static void screen_init() { + // Since not all versions of Windows include multiple monitor support, + // we do a run-time check for the required functions... + HMODULE hMod = GetModuleHandle("USER32.DLL"); + + if (hMod) { + // check that EnumDisplayMonitors is available + fl_edm_func fl_edm = (fl_edm_func)GetProcAddress(hMod, "EnumDisplayMonitors"); + + if (fl_edm) { + // We do have EnumDisplayMonitors, so lets find out how many monitors... + num_screens = GetSystemMetrics(SM_CMONITORS); + + if (num_screens > 1) { + // If there is more than 1 monitor, enumerate them... + fl_gmi = (fl_gmi_func)GetProcAddress(hMod, "GetMonitorInfoA"); + + if (fl_gmi) { + // We have GetMonitorInfoA, enumerate all the screens... + num_screens = 0; +// EnumDisplayMonitors(0,0,screen_cb,0); + fl_edm(0, 0, screen_cb, 0); + return; + } + } + } + } + + // If we get here, assume we have 1 monitor... + num_screens = 1; +} +#elif defined(__APPLE__) +XRectangle screens[16]; + +static void screen_init() { + GDHandle gd; + + for (gd = GetDeviceList(), num_screens = 0; gd; gd = GetNextDevice(gd)) { + GDPtr gp = *gd; + screens[num_screens].x = gp->gdRect.left; + screens[num_screens].y = gp->gdRect.top; + screens[num_screens].width = gp->gdRect.right - gp->gdRect.left; + screens[num_screens].height = gp->gdRect.bottom - gp->gdRect.top; + + num_screens ++; + if (num_screens >= 16) break; + } +} +#elif HAVE_XINERAMA +# include <X11/extensions/Xinerama.h> + +// Screen data... +static XineramaScreenInfo *screens; + +static void screen_init() { + if (!fl_display) fl_open_display(); + + if (XineramaIsActive(fl_display)) { + screens = XineramaQueryScreens(fl_display, &num_screens); + } else num_screens = 1; +} +#else +static void screen_init() { + num_screens = 1; +} +#endif // WIN32 + + +// Return the number of screens... +int Fl::screen_count() { + if (!num_screens) screen_init(); + + return num_screens; +} + +// Return the screen bounding rect for the given mouse position... +void Fl::screen_xywh(int &x, int &y, int &w, int &h, int mx, int my) { + if (!num_screens) screen_init(); + +#ifdef WIN32 + if (num_screens > 1) { + int i; + + for (i = 0; i < num_screens; i ++) { + if (mx >= screens[i].left && mx < screens[i].right && + my >= screens[i].top && my < screens[i].bottom) { + x = screens[i].left; + y = screens[i].top; + w = screens[i].right - screens[i].left; + h = screens[i].bottom - screens[i].top; + return; + } + } + } +#elif defined(__APPLE__) + if (num_screens > 1) { + int i; + + for (i = 0; i < num_screens; i ++) { + if (mx >= screens[i].x && + mx < (screens[i].x + screens[i].width) && + my >= screens[i].y && + my < (screens[i].y + screens[i].height)) { + x = screens[i].x; + y = screens[i].y; + w = screens[i].width; + h = screens[i].height; + return; + } + } + } +#elif HAVE_XINERAMA + if (num_screens > 1) { + int i; + + for (i = 0; i < num_screens; i ++) { + if (mx >= screens[i].x_org && + mx < (screens[i].x_org + screens[i].width) && + my >= screens[i].y_org && + my < (screens[i].y_org + screens[i].height)) { + x = screens[i].x_org; + y = screens[i].y_org; + w = screens[i].width; + h = screens[i].height; + return; + } + } + } +#endif // WIN32 + + x = Fl::x(); + y = Fl::y(); + w = Fl::w(); + h = Fl::h(); +} + +// Return the screen bounding rect for the given screen... +void Fl::screen_xywh(int &x, int &y, int &w, int &h, int n) { + if (!num_screens) screen_init(); + +#ifdef WIN32 + if (num_screens > 1 && n >= 0 && n < num_screens) { + x = screens[n].left; + y = screens[n].top; + w = screens[n].right - screens[n].left; + h = screens[n].bottom - screens[n].top; + return; + } +#elif defined(__APPLE__) + if (num_screens > 1 && n >= 0 && n < num_screens) { + x = screens[n].x; + y = screens[n].y; + w = screens[n].width; + h = screens[n].height; + return; + } +#elif HAVE_XINERAMA + if (num_screens > 1 && n >= 0 && n < num_screens) { + x = screens[n].x_org; + y = screens[n].y_org; + w = screens[n].width; + h = screens[n].height; + return; + } +#endif // WIN32 + + x = Fl::x(); + y = Fl::y(); + w = Fl::w(); + h = Fl::h(); +} + + +// +// End of "$Id$". +// diff --git a/Utilities/FLTK/src/slowarrow.h b/Utilities/FLTK/src/slowarrow.h new file mode 100644 index 0000000000..46a572c97d --- /dev/null +++ b/Utilities/FLTK/src/slowarrow.h @@ -0,0 +1,6 @@ +#define slowarrow_width 16 +#define slowarrow_height 16 +static unsigned char slowarrow_bits[] = { + 0x40, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0xf0, 0x0f, 0x60, 0x00, + 0x60, 0x00, 0x40, 0x02, 0x40, 0x02, 0x00, 0x06, 0x00, 0x06, 0xf0, 0x0f, + 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0x02}; diff --git a/Utilities/FLTK/src/tile.xpm b/Utilities/FLTK/src/tile.xpm new file mode 100644 index 0000000000..872e0f70c5 --- /dev/null +++ b/Utilities/FLTK/src/tile.xpm @@ -0,0 +1,91 @@ +/* XPM */ +static char tile_cmap[3][32] = { +"O c #FFFFFF", +"o c #EFEFEF", +". c #E8E8E8" +}; +static const char * tile_xpm[] = { +"64 64 3 1", +tile_cmap[0], +tile_cmap[1], +tile_cmap[2], + +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"................................................................", +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", + +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"................................................................", +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", + +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"................................................................", +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", + +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"................................................................", +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", + +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"................................................................", +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", + +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"................................................................", +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", + +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"................................................................", +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", + +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"................................................................", +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", + +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"................................................................", +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", + +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"................................................................", +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", + +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"................................................................", +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", + +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"................................................................", +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", + +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"................................................................", +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", + +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"................................................................", +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", + +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"................................................................", +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", + +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"................................................................", +"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", +"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"}; diff --git a/Utilities/FLTK/src/up.xbm b/Utilities/FLTK/src/up.xbm new file mode 100644 index 0000000000..1a4f4b7e7d --- /dev/null +++ b/Utilities/FLTK/src/up.xbm @@ -0,0 +1,6 @@ +#define up_width 16 +#define up_height 16 +static unsigned char up_bits[] = { + 0x00, 0x00, 0x78, 0x00, 0x84, 0x00, 0x02, 0x01, 0x31, 0xfe, 0x79, 0x80, + 0xfd, 0x80, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, + 0x01, 0x80, 0x01, 0x80, 0xff, 0xff, 0x00, 0x00}; diff --git a/Utilities/FLTK/src/vsnprintf.c b/Utilities/FLTK/src/vsnprintf.c new file mode 100644 index 0000000000..8d1752b919 --- /dev/null +++ b/Utilities/FLTK/src/vsnprintf.c @@ -0,0 +1,271 @@ +/* + * "$Id$" + * + * snprintf() and vsnprintf() functions for the Fast Light Tool Kit (FLTK). + * + * Copyright 1998-2005 by Bill Spitzak and others. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems on the following page: + * + * http://www.fltk.org/str.php + */ + +#include <stdio.h> +#include "flstring.h" + +#ifdef HAVE_SYS_STDTYPES_H +# include <sys/stdtypes.h> +#endif /* HAVE_SYS_STDTYPES_H */ + +#ifdef __cplusplus +extern "C" { +#endif + +int fl_vsnprintf(char* buffer, size_t bufsize, const char* format, va_list ap) { + char *bufptr, /* Pointer to position in buffer */ + *bufend, /* Pointer to end of buffer */ + sign, /* Sign of format width */ + size, /* Size character (h, l, L) */ + type; /* Format type character */ + int width, /* Width of field */ + prec; /* Number of characters of precision */ + char tformat[100], /* Temporary format string for sprintf() */ + *tptr, /* Pointer into temporary format */ + temp[1024]; /* Buffer for formatted numbers */ + char *s; /* Pointer to string */ + int slen; /* Length of string */ + int bytes; /* Total number of bytes needed */ + + + /* + * Loop through the format string, formatting as needed... + */ + + bufptr = buffer; + bufend = buffer + bufsize - 1; + bytes = 0; + + while (*format) { + if (*format == '%') { + tptr = tformat; + *tptr++ = *format++; + + if (*format == '%') { + if (bufptr && bufptr < bufend) *bufptr++ = *format; + bytes ++; + format ++; + continue; + } else if (strchr(" -+#\'", *format)) { + *tptr++ = *format; + sign = *format++; + } else sign = 0; + + if (*format == '*') { + /* Get width from argument... */ + format ++; + width = va_arg(ap, int); + snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", width); + tptr += strlen(tptr); + } else { + width = 0; + while (isdigit(*format & 255)) { + if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; + width = width * 10 + *format++ - '0'; + } + } + + if (*format == '.') { + if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; + format ++; + + if (*format == '*') { + /* Get precision from argument... */ + format ++; + prec = va_arg(ap, int); + snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", prec); + tptr += strlen(tptr); + } else { + prec = 0; + while (isdigit(*format & 255)) { + if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; + prec = prec * 10 + *format++ - '0'; + } + } + } else prec = -1; + + if (*format == 'l' && format[1] == 'l') { + size = 'L'; + if (tptr < (tformat + sizeof(tformat) - 2)) { + *tptr++ = 'l'; + *tptr++ = 'l'; + } + format += 2; + } else if (*format == 'h' || *format == 'l' || *format == 'L') { + if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; + size = *format++; + } + + if (!*format) break; + + if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; + type = *format++; + *tptr = '\0'; + + switch (type) { + case 'E' : /* Floating point formats */ + case 'G' : + case 'e' : + case 'f' : + case 'g' : + if ((width + 2) > sizeof(temp)) break; + + sprintf(temp, tformat, va_arg(ap, double)); + + bytes += strlen(temp); + + if (bufptr) { + if ((bufptr + strlen(temp)) > bufend) { + strncpy(bufptr, temp, (size_t)(bufend - bufptr)); + bufptr = bufend; + } else { + strcpy(bufptr, temp); + bufptr += strlen(temp); + } + } + break; + + case 'B' : /* Integer formats */ + case 'X' : + case 'b' : + case 'd' : + case 'i' : + case 'o' : + case 'u' : + case 'x' : + if ((width + 2) > sizeof(temp)) break; + + sprintf(temp, tformat, va_arg(ap, int)); + + bytes += strlen(temp); + + if (bufptr) { + if ((bufptr + strlen(temp)) > bufend) { + strncpy(bufptr, temp, (size_t)(bufend - bufptr)); + bufptr = bufend; + } else { + strcpy(bufptr, temp); + bufptr += strlen(temp); + } + } + break; + + case 'p' : /* Pointer value */ + if ((width + 2) > sizeof(temp)) break; + + sprintf(temp, tformat, va_arg(ap, void *)); + + bytes += strlen(temp); + + if (bufptr) { + if ((bufptr + strlen(temp)) > bufend) { + strncpy(bufptr, temp, (size_t)(bufend - bufptr)); + bufptr = bufend; + } else { + strcpy(bufptr, temp); + bufptr += strlen(temp); + } + } + break; + + case 'c' : /* Character or character array */ + bytes += width; + + if (bufptr) { + if (width <= 1) *bufptr++ = va_arg(ap, int); + else { + if ((bufptr + width) > bufend) width = bufend - bufptr; + + memcpy(bufptr, va_arg(ap, char *), (size_t)width); + bufptr += width; + } + } + break; + + case 's' : /* String */ + if ((s = va_arg(ap, char *)) == NULL) s = "(null)"; + + slen = strlen(s); + if (slen > width && prec != width) width = slen; + + bytes += width; + + if (bufptr) { + if ((bufptr + width) > bufend) width = bufend - bufptr; + + if (slen > width) slen = width; + + if (sign == '-') { + strncpy(bufptr, s, (size_t)slen); + memset(bufptr + slen, ' ', (size_t)(width - slen)); + } else { + memset(bufptr, ' ', (size_t)(width - slen)); + strncpy(bufptr + width - slen, s, (size_t)slen); + } + + bufptr += width; + } + break; + + case 'n' : /* Output number of chars so far */ + *(va_arg(ap, int *)) = bytes; + break; + } + } else { + bytes ++; + + if (bufptr && bufptr < bufend) *bufptr++ = *format; + format ++; + } + } + + /* + * Nul-terminate the string and return the number of characters needed. + */ + + if (bufptr) *bufptr = '\0'; + + return (bytes); +} + +int fl_snprintf(char* str, size_t size, const char* fmt, ...) { + int ret; + va_list ap; + va_start(ap, fmt); + ret = vsnprintf(str, size, fmt, ap); + va_end(ap); + return ret; +} + +#ifdef __cplusplus +} +#endif + +/* + * End of "$Id$". + */ + diff --git a/Utilities/FLTK/zlib/CMakeLists.txt b/Utilities/FLTK/zlib/CMakeLists.txt new file mode 100644 index 0000000000..006a7634f5 --- /dev/null +++ b/Utilities/FLTK/zlib/CMakeLists.txt @@ -0,0 +1,15 @@ +PROJECT(FLTKZLIB) +INCLUDE_REGULAR_EXPRESSION("^(deflate|inf|trees|zconf|zlib|zutil).*$") + +INCLUDE_DIRECTORIES(${FLTKZLIB_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${FLTKZLIB_BINARY_DIR}) + +# source files for zlib +SET(ZLIB_SRCS +adler32.c compress.c crc32.c deflate.c gzio.c inffast.c +inflate.c inftrees.c trees.c uncompr.c zutil.c +) + +ADD_LIBRARY(fltk_zlib ${ZLIB_SRCS}) +INSTALL_TARGETS(/lib fltk_zlib) + diff --git a/Utilities/FLTK/zlib/ChangeLog b/Utilities/FLTK/zlib/ChangeLog new file mode 100644 index 0000000000..553774c0ca --- /dev/null +++ b/Utilities/FLTK/zlib/ChangeLog @@ -0,0 +1,722 @@ + + ChangeLog file for zlib + +Changes in 1.2.1 (17 November 2003) +- Remove a tab in contrib/gzappend/gzappend.c +- Update some interfaces in contrib for new zlib functions +- Update zlib version number in some contrib entries +- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] +- Support shared libraries on Hurd and KFreeBSD [Brown] +- Fix error in NO_DIVIDE option of adler32.c + +Changes in 1.2.0.8 (4 November 2003) +- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas +- Add experimental NO_DIVIDE #define in adler32.c + - Possibly faster on some processors (let me know if it is) +- Correct Z_BLOCK to not return on first inflate call if no wrap +- Fix strm->data_type on inflate() return to correctly indicate EOB +- Add deflatePrime() function for appending in the middle of a byte +- Add contrib/gzappend for an example of appending to a stream +- Update win32/DLL_FAQ.txt [Truta] +- Delete Turbo C comment in README [Truta] +- Improve some indentation in zconf.h [Truta] +- Fix infinite loop on bad input in configure script [Church] +- Fix gzeof() for concatenated gzip files [Johnson] +- Add example to contrib/visual-basic.txt [Michael B.] +- Add -p to mkdir's in Makefile.in [vda] +- Fix configure to properly detect presence or lack of printf functions +- Add AS400 support [Monnerat] +- Add a little Cygwin support [Wilson] + +Changes in 1.2.0.7 (21 September 2003) +- Correct some debug formats in contrib/infback9 +- Cast a type in a debug statement in trees.c +- Change search and replace delimiter in configure from % to # [Beebe] +- Update contrib/untgz to 0.2 with various fixes [Truta] +- Add build support for Amiga [Nikl] +- Remove some directories in old that have been updated to 1.2 +- Add dylib building for Mac OS X in configure and Makefile.in +- Remove old distribution stuff from Makefile +- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X +- Update links in README + +Changes in 1.2.0.6 (13 September 2003) +- Minor FAQ updates +- Update contrib/minizip to 1.00 [Vollant] +- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] +- Update POSTINC comment for 68060 [Nikl] +- Add contrib/infback9 with deflate64 decoding (unsupported) +- For MVS define NO_vsnprintf and undefine FAR [van Burik] +- Add pragma for fdopen on MVS [van Burik] + +Changes in 1.2.0.5 (8 September 2003) +- Add OF to inflateBackEnd() declaration in zlib.h +- Remember start when using gzdopen in the middle of a file +- Use internal off_t counters in gz* functions to properly handle seeks +- Perform more rigorous check for distance-too-far in inffast.c +- Add Z_BLOCK flush option to return from inflate at block boundary +- Set strm->data_type on return from inflate + - Indicate bits unused, if at block boundary, and if in last block +- Replace size_t with ptrdiff_t in crc32.c, and check for correct size +- Add condition so old NO_DEFLATE define still works for compatibility +- FAQ update regarding the Windows DLL [Truta] +- INDEX update: add qnx entry, remove aix entry [Truta] +- Install zlib.3 into mandir [Wilson] +- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] +- Adapt the zlib interface to the new DLL convention guidelines [Truta] +- Introduce ZLIB_WINAPI macro to allow the export of functions using + the WINAPI calling convention, for Visual Basic [Vollant, Truta] +- Update msdos and win32 scripts and makefiles [Truta] +- Export symbols by name, not by ordinal, in win32/zlib.def [Truta] +- Add contrib/ada [Anisimkov] +- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] +- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] +- Add contrib/masm686 [Truta] +- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm + [Truta, Vollant] +- Update contrib/delphi; rename to contrib/pascal; add example [Truta] +- Remove contrib/delphi2; add a new contrib/delphi [Truta] +- Avoid inclusion of the nonstandard <memory.h> in contrib/iostream, + and fix some method prototypes [Truta] +- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip + [Truta] +- Avoid the use of backslash (\) in contrib/minizip [Vollant] +- Fix file time handling in contrib/untgz; update makefiles [Truta] +- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines + [Vollant] +- Remove contrib/vstudio/vc15_16 [Vollant] +- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] +- Update README.contrib [Truta] +- Invert the assignment order of match_head and s->prev[...] in + INSERT_STRING [Truta] +- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings + [Truta] +- Compare function pointers with 0, not with NULL or Z_NULL [Truta] +- Fix prototype of syncsearch in inflate.c [Truta] +- Introduce ASMINF macro to be enabled when using an ASM implementation + of inflate_fast [Truta] +- Change NO_DEFLATE to NO_GZCOMPRESS [Truta] +- Modify test_gzio in example.c to take a single file name as a + parameter [Truta] +- Exit the example.c program if gzopen fails [Truta] +- Add type casts around strlen in example.c [Truta] +- Remove casting to sizeof in minigzip.c; give a proper type + to the variable compared with SUFFIX_LEN [Truta] +- Update definitions of STDC and STDC99 in zconf.h [Truta] +- Synchronize zconf.h with the new Windows DLL interface [Truta] +- Use SYS16BIT instead of __32BIT__ to distinguish between + 16- and 32-bit platforms [Truta] +- Use far memory allocators in small 16-bit memory models for + Turbo C [Truta] +- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in + zlibCompileFlags [Truta] +- Cygwin has vsnprintf [Wilson] +- In Windows16, OS_CODE is 0, as in MSDOS [Truta] +- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] + +Changes in 1.2.0.4 (10 August 2003) +- Minor FAQ updates +- Be more strict when checking inflateInit2's windowBits parameter +- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well +- Add gzip wrapper option to deflateInit2 using windowBits +- Add updated QNX rule in configure and qnx directory [Bonnefoy] +- Make inflate distance-too-far checks more rigorous +- Clean up FAR usage in inflate +- Add casting to sizeof() in gzio.c and minigzip.c + +Changes in 1.2.0.3 (19 July 2003) +- Fix silly error in gzungetc() implementation [Vollant] +- Update contrib/minizip and contrib/vstudio [Vollant] +- Fix printf format in example.c +- Correct cdecl support in zconf.in.h [Anisimkov] +- Minor FAQ updates + +Changes in 1.2.0.2 (13 July 2003) +- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons +- Attempt to avoid warnings in crc32.c for pointer-int conversion +- Add AIX to configure, remove aix directory [Bakker] +- Add some casts to minigzip.c +- Improve checking after insecure sprintf() or vsprintf() calls +- Remove #elif's from crc32.c +- Change leave label to inf_leave in inflate.c and infback.c to avoid + library conflicts +- Remove inflate gzip decoding by default--only enable gzip decoding by + special request for stricter backward compatibility +- Add zlibCompileFlags() function to return compilation information +- More typecasting in deflate.c to avoid warnings +- Remove leading underscore from _Capital #defines [Truta] +- Fix configure to link shared library when testing +- Add some Windows CE target adjustments [Mai] +- Remove #define ZLIB_DLL in zconf.h [Vollant] +- Add zlib.3 [Rodgers] +- Update RFC URL in deflate.c and algorithm.txt [Mai] +- Add zlib_dll_FAQ.txt to contrib [Truta] +- Add UL to some constants [Truta] +- Update minizip and vstudio [Vollant] +- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h +- Expand use of NO_DUMMY_DECL to avoid all dummy structures +- Added iostream3 to contrib [Schwardt] +- Replace rewind() with fseek() for WinCE [Truta] +- Improve setting of zlib format compression level flags + - Report 0 for huffman and rle strategies and for level == 0 or 1 + - Report 2 only for level == 6 +- Only deal with 64K limit when necessary at compile time [Truta] +- Allow TOO_FAR check to be turned off at compile time [Truta] +- Add gzclearerr() function [Souza] +- Add gzungetc() function + +Changes in 1.2.0.1 (17 March 2003) +- Add Z_RLE strategy for run-length encoding [Truta] + - When Z_RLE requested, restrict matches to distance one + - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE +- Correct FASTEST compilation to allow level == 0 +- Clean up what gets compiled for FASTEST +- Incorporate changes to zconf.in.h [Vollant] + - Refine detection of Turbo C need for dummy returns + - Refine ZLIB_DLL compilation + - Include additional header file on VMS for off_t typedef +- Try to use _vsnprintf where it supplants vsprintf [Vollant] +- Add some casts in inffast.c +- Enchance comments in zlib.h on what happens if gzprintf() tries to + write more than 4095 bytes before compression +- Remove unused state from inflateBackEnd() +- Remove exit(0) from minigzip.c, example.c +- Get rid of all those darn tabs +- Add "check" target to Makefile.in that does the same thing as "test" +- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in +- Update contrib/inflate86 [Anderson] +- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] +- Add msdos and win32 directories with makefiles [Truta] +- More additions and improvements to the FAQ + +Changes in 1.2.0 (9 March 2003) +- New and improved inflate code + - About 20% faster + - Does not allocate 32K window unless and until needed + - Automatically detects and decompresses gzip streams + - Raw inflate no longer needs an extra dummy byte at end + - Added inflateBack functions using a callback interface--even faster + than inflate, useful for file utilities (gzip, zip) + - Added inflateCopy() function to record state for random access on + externally generated deflate streams (e.g. in gzip files) + - More readable code (I hope) +- New and improved crc32() + - About 50% faster, thanks to suggestions from Rodney Brown +- Add deflateBound() and compressBound() functions +- Fix memory leak in deflateInit2() +- Permit setting dictionary for raw deflate (for parallel deflate) +- Fix const declaration for gzwrite() +- Check for some malloc() failures in gzio.c +- Fix bug in gzopen() on single-byte file 0x1f +- Fix bug in gzread() on concatenated file with 0x1f at end of buffer + and next buffer doesn't start with 0x8b +- Fix uncompress() to return Z_DATA_ERROR on truncated input +- Free memory at end of example.c +- Remove MAX #define in trees.c (conflicted with some libraries) +- Fix static const's in deflate.c, gzio.c, and zutil.[ch] +- Declare malloc() and free() in gzio.c if STDC not defined +- Use malloc() instead of calloc() in zutil.c if int big enough +- Define STDC for AIX +- Add aix/ with approach for compiling shared library on AIX +- Add HP-UX support for shared libraries in configure +- Add OpenUNIX support for shared libraries in configure +- Use $cc instead of gcc to build shared library +- Make prefix directory if needed when installing +- Correct Macintosh avoidance of typedef Byte in zconf.h +- Correct Turbo C memory allocation when under Linux +- Use libz.a instead of -lz in Makefile (assure use of compiled library) +- Update configure to check for snprintf or vsnprintf functions and their + return value, warn during make if using an insecure function +- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that + is lost when library is used--resolution is to build new zconf.h +- Documentation improvements (in zlib.h): + - Document raw deflate and inflate + - Update RFCs URL + - Point out that zlib and gzip formats are different + - Note that Z_BUF_ERROR is not fatal + - Document string limit for gzprintf() and possible buffer overflow + - Note requirement on avail_out when flushing + - Note permitted values of flush parameter of inflate() +- Add some FAQs (and even answers) to the FAQ +- Add contrib/inflate86/ for x86 faster inflate +- Add contrib/blast/ for PKWare Data Compression Library decompression +- Add contrib/puff/ simple inflate for deflate format description + +Changes in 1.1.4 (11 March 2002) +- ZFREE was repeated on same allocation on some error conditions. + This creates a security problem described in + http://www.zlib.org/advisory-2002-03-11.txt +- Returned incorrect error (Z_MEM_ERROR) on some invalid data +- Avoid accesses before window for invalid distances with inflate window + less than 32K. +- force windowBits > 8 to avoid a bug in the encoder for a window size + of 256 bytes. (A complete fix will be available in 1.1.5). + +Changes in 1.1.3 (9 July 1998) +- fix "an inflate input buffer bug that shows up on rare but persistent + occasions" (Mark) +- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) +- fix gzseek(..., SEEK_SET) in write mode +- fix crc check after a gzeek (Frank Faubert) +- fix miniunzip when the last entry in a zip file is itself a zip file + (J Lillge) +- add contrib/asm586 and contrib/asm686 (Brian Raiter) + See http://www.muppetlabs.com/~breadbox/software/assembly.html +- add support for Delphi 3 in contrib/delphi (Bob Dellaca) +- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) +- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) +- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) +- added a FAQ file + +- Support gzdopen on Mac with Metrowerks (Jason Linhart) +- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) +- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) +- avoid some warnings with Borland C (Tom Tanner) +- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) +- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) +- allow several arguments to configure (Tim Mooney, Frodo Looijaard) +- use libdir and includedir in Makefile.in (Tim Mooney) +- support shared libraries on OSF1 V4 (Tim Mooney) +- remove so_locations in "make clean" (Tim Mooney) +- fix maketree.c compilation error (Glenn, Mark) +- Python interface to zlib now in Python 1.5 (Jeremy Hylton) +- new Makefile.riscos (Rich Walker) +- initialize static descriptors in trees.c for embedded targets (Nick Smith) +- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) +- add the OS/2 files in Makefile.in too (Andrew Zabolotny) +- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) +- fix maketree.c to allow clean compilation of inffixed.h (Mark) +- fix parameter check in deflateCopy (Gunther Nikl) +- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) +- Many portability patches by Christian Spieler: + . zutil.c, zutil.h: added "const" for zmem* + . Make_vms.com: fixed some typos + . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists + . msdos/Makefile.msc: remove "default rtl link library" info from obj files + . msdos/Makefile.*: use model-dependent name for the built zlib library + . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: + new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) +- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) +- replace __far with _far for better portability (Christian Spieler, Tom Lane) +- fix test for errno.h in configure (Tim Newsham) + +Changes in 1.1.2 (19 March 98) +- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) + See http://www.winimage.com/zLibDll/unzip.html +- preinitialize the inflate tables for fixed codes, to make the code + completely thread safe (Mark) +- some simplifications and slight speed-up to the inflate code (Mark) +- fix gzeof on non-compressed files (Allan Schrum) +- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) +- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) +- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) +- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) +- do not wrap extern "C" around system includes (Tom Lane) +- mention zlib binding for TCL in README (Andreas Kupries) +- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) +- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) +- allow "configure --prefix $HOME" (Tim Mooney) +- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) +- move Makefile.sas to amiga/Makefile.sas + +Changes in 1.1.1 (27 Feb 98) +- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) +- remove block truncation heuristic which had very marginal effect for zlib + (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the + compression ratio on some files. This also allows inlining _tr_tally for + matches in deflate_slow. +- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) + +Changes in 1.1.0 (24 Feb 98) +- do not return STREAM_END prematurely in inflate (John Bowler) +- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) +- compile with -DFASTEST to get compression code optimized for speed only +- in minigzip, try mmap'ing the input file first (Miguel Albrecht) +- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain + on Sun but significant on HP) + +- add a pointer to experimental unzip library in README (Gilles Vollant) +- initialize variable gcc in configure (Chris Herborth) + +Changes in 1.0.9 (17 Feb 1998) +- added gzputs and gzgets functions +- do not clear eof flag in gzseek (Mark Diekhans) +- fix gzseek for files in transparent mode (Mark Diekhans) +- do not assume that vsprintf returns the number of bytes written (Jens Krinke) +- replace EXPORT with ZEXPORT to avoid conflict with other programs +- added compress2 in zconf.h, zlib.def, zlib.dnt +- new asm code from Gilles Vollant in contrib/asm386 +- simplify the inflate code (Mark): + . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() + . ZALLOC the length list in inflate_trees_fixed() instead of using stack + . ZALLOC the value area for huft_build() instead of using stack + . Simplify Z_FINISH check in inflate() + +- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 +- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) +- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with + the declaration of FAR (Gilles VOllant) +- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) +- read_buf buf parameter of type Bytef* instead of charf* +- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) +- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) +- fix check for presence of directories in "make install" (Ian Willis) + +Changes in 1.0.8 (27 Jan 1998) +- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) +- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) +- added compress2() to allow setting the compression level +- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) +- use constant arrays for the static trees in trees.c instead of computing + them at run time (thanks to Ken Raeburn for this suggestion). To create + trees.h, compile with GEN_TREES_H and run "make test". +- check return code of example in "make test" and display result +- pass minigzip command line options to file_compress +- simplifying code of inflateSync to avoid gcc 2.8 bug + +- support CC="gcc -Wall" in configure -s (QingLong) +- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) +- fix test for shared library support to avoid compiler warnings +- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) +- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) +- do not use fdopen for Metrowerks on Mac (Brad Pettit)) +- add checks for gzputc and gzputc in example.c +- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) +- use const for the CRC table (Ken Raeburn) +- fixed "make uninstall" for shared libraries +- use Tracev instead of Trace in infblock.c +- in example.c use correct compressed length for test_sync +- suppress +vnocompatwarnings in configure for HPUX (not always supported) + +Changes in 1.0.7 (20 Jan 1998) +- fix gzseek which was broken in write mode +- return error for gzseek to negative absolute position +- fix configure for Linux (Chun-Chung Chen) +- increase stack space for MSC (Tim Wegner) +- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) +- define EXPORTVA for gzprintf (Gilles Vollant) +- added man page zlib.3 (Rick Rodgers) +- for contrib/untgz, fix makedir() and improve Makefile + +- check gzseek in write mode in example.c +- allocate extra buffer for seeks only if gzseek is actually called +- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) +- add inflateSyncPoint in zconf.h +- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def + +Changes in 1.0.6 (19 Jan 1998) +- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and + gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) +- Fix a deflate bug occuring only with compression level 0 (thanks to + Andy Buckler for finding this one). +- In minigzip, pass transparently also the first byte for .Z files. +- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() +- check Z_FINISH in inflate (thanks to Marc Schluper) +- Implement deflateCopy (thanks to Adam Costello) +- make static libraries by default in configure, add --shared option. +- move MSDOS or Windows specific files to directory msdos +- suppress the notion of partial flush to simplify the interface + (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) +- suppress history buffer provided by application to simplify the interface + (this feature was not implemented anyway in 1.0.4) +- next_in and avail_in must be initialized before calling inflateInit or + inflateInit2 +- add EXPORT in all exported functions (for Windows DLL) +- added Makefile.nt (thanks to Stephen Williams) +- added the unsupported "contrib" directory: + contrib/asm386/ by Gilles Vollant <info@winimage.com> + 386 asm code replacing longest_match(). + contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu> + A C++ I/O streams interface to the zlib gz* functions + contrib/iostream2/ by Tyge L�vset <Tyge.Lovset@cmr.no> + Another C++ I/O streams interface + contrib/untgz/ by "Pedro A. Aranda Guti\irrez" <paag@tid.es> + A very simple tar.gz file extractor using zlib + contrib/visual-basic.txt by Carlos Rios <c_rios@sonda.cl> + How to use compress(), uncompress() and the gz* functions from VB. +- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression + level) in minigzip (thanks to Tom Lane) + +- use const for rommable constants in deflate +- added test for gzseek and gztell in example.c +- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) +- add undocumented function zError to convert error code to string + (for Tim Smithers) +- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. +- Use default memcpy for Symantec MSDOS compiler. +- Add EXPORT keyword for check_func (needed for Windows DLL) +- add current directory to LD_LIBRARY_PATH for "make test" +- create also a link for libz.so.1 +- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) +- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) +- added -soname for Linux in configure (Chun-Chung Chen, +- assign numbers to the exported functions in zlib.def (for Windows DLL) +- add advice in zlib.h for best usage of deflateSetDictionary +- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) +- allow compilation with ANSI keywords only enabled for TurboC in large model +- avoid "versionString"[0] (Borland bug) +- add NEED_DUMMY_RETURN for Borland +- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). +- allow compilation with CC +- defined STDC for OS/2 (David Charlap) +- limit external names to 8 chars for MVS (Thomas Lund) +- in minigzip.c, use static buffers only for 16-bit systems +- fix suffix check for "minigzip -d foo.gz" +- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) +- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) +- added makelcc.bat for lcc-win32 (Tom St Denis) +- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) +- Avoid expanded $Id: ChangeLog 3809 2004-09-08 16:04:43Z easysw $. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. +- check for unistd.h in configure (for off_t) +- remove useless check parameter in inflate_blocks_free +- avoid useless assignment of s->check to itself in inflate_blocks_new +- do not flush twice in gzclose (thanks to Ken Raeburn) +- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h +- use NO_ERRNO_H instead of enumeration of operating systems with errno.h +- work around buggy fclose on pipes for HP/UX +- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) +- fix configure if CC is already equal to gcc + +Changes in 1.0.5 (3 Jan 98) +- Fix inflate to terminate gracefully when fed corrupted or invalid data +- Use const for rommable constants in inflate +- Eliminate memory leaks on error conditions in inflate +- Removed some vestigial code in inflate +- Update web address in README + +Changes in 1.0.4 (24 Jul 96) +- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF + bit, so the decompressor could decompress all the correct data but went + on to attempt decompressing extra garbage data. This affected minigzip too. +- zlibVersion and gzerror return const char* (needed for DLL) +- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) +- use z_error only for DEBUG (avoid problem with DLLs) + +Changes in 1.0.3 (2 Jul 96) +- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS + small and medium models; this makes the library incompatible with previous + versions for these models. (No effect in large model or on other systems.) +- return OK instead of BUF_ERROR if previous deflate call returned with + avail_out as zero but there is nothing to do +- added memcmp for non STDC compilers +- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) +- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) +- better check for 16-bit mode MSC (avoids problem with Symantec) + +Changes in 1.0.2 (23 May 96) +- added Windows DLL support +- added a function zlibVersion (for the DLL support) +- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) +- Bytef is define's instead of typedef'd only for Borland C +- avoid reading uninitialized memory in example.c +- mention in README that the zlib format is now RFC1950 +- updated Makefile.dj2 +- added algorithm.doc + +Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] +- fix array overlay in deflate.c which sometimes caused bad compressed data +- fix inflate bug with empty stored block +- fix MSDOS medium model which was broken in 0.99 +- fix deflateParams() which could generated bad compressed data. +- Bytef is define'd instead of typedef'ed (work around Borland bug) +- added an INDEX file +- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), + Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) +- speed up adler32 for modern machines without auto-increment +- added -ansi for IRIX in configure +- static_init_done in trees.c is an int +- define unlink as delete for VMS +- fix configure for QNX +- add configure branch for SCO and HPUX +- avoid many warnings (unused variables, dead assignments, etc...) +- no fdopen for BeOS +- fix the Watcom fix for 32 bit mode (define FAR as empty) +- removed redefinition of Byte for MKWERKS +- work around an MWKERKS bug (incorrect merge of all .h files) + +Changes in 0.99 (27 Jan 96) +- allow preset dictionary shared between compressor and decompressor +- allow compression level 0 (no compression) +- add deflateParams in zlib.h: allow dynamic change of compression level + and compression strategy. +- test large buffers and deflateParams in example.c +- add optional "configure" to build zlib as a shared library +- suppress Makefile.qnx, use configure instead +- fixed deflate for 64-bit systems (detected on Cray) +- fixed inflate_blocks for 64-bit systems (detected on Alpha) +- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) +- always return Z_BUF_ERROR when deflate() has nothing to do +- deflateInit and inflateInit are now macros to allow version checking +- prefix all global functions and types with z_ with -DZ_PREFIX +- make falloc completely reentrant (inftrees.c) +- fixed very unlikely race condition in ct_static_init +- free in reverse order of allocation to help memory manager +- use zlib-1.0/* instead of zlib/* inside the tar.gz +- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith + -Wconversion -Wstrict-prototypes -Wmissing-prototypes" +- allow gzread on concatenated .gz files +- deflateEnd now returns Z_DATA_ERROR if it was premature +- deflate is finally (?) fully deterministic (no matches beyond end of input) +- Document Z_SYNC_FLUSH +- add uninstall in Makefile +- Check for __cpluplus in zlib.h +- Better test in ct_align for partial flush +- avoid harmless warnings for Borland C++ +- initialize hash_head in deflate.c +- avoid warning on fdopen (gzio.c) for HP cc -Aa +- include stdlib.h for STDC compilers +- include errno.h for Cray +- ignore error if ranlib doesn't exist +- call ranlib twice for NeXTSTEP +- use exec_prefix instead of prefix for libz.a +- renamed ct_* as _tr_* to avoid conflict with applications +- clear z->msg in inflateInit2 before any error return +- initialize opaque in example.c, gzio.c, deflate.c and inflate.c +- fixed typo in zconf.h (_GNUC__ => __GNUC__) +- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) +- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) +- in fcalloc, normalize pointer if size > 65520 bytes +- don't use special fcalloc for 32 bit Borland C++ +- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... +- use Z_BINARY instead of BINARY +- document that gzclose after gzdopen will close the file +- allow "a" as mode in gzopen. +- fix error checking in gzread +- allow skipping .gz extra-field on pipes +- added reference to Perl interface in README +- put the crc table in FAR data (I dislike more and more the medium model :) +- added get_crc_table +- added a dimension to all arrays (Borland C can't count). +- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast +- guard against multiple inclusion of *.h (for precompiled header on Mac) +- Watcom C pretends to be Microsoft C small model even in 32 bit mode. +- don't use unsized arrays to avoid silly warnings by Visual C++: + warning C4746: 'inflate_mask' : unsized array treated as '__far' + (what's wrong with far data in far model?). +- define enum out of inflate_blocks_state to allow compilation with C++ + +Changes in 0.95 (16 Aug 95) +- fix MSDOS small and medium model (now easier to adapt to any compiler) +- inlined send_bits +- fix the final (:-) bug for deflate with flush (output was correct but + not completely flushed in rare occasions). +- default window size is same for compression and decompression + (it's now sufficient to set MAX_WBITS in zconf.h). +- voidp -> voidpf and voidnp -> voidp (for consistency with other + typedefs and because voidnp was not near in large model). + +Changes in 0.94 (13 Aug 95) +- support MSDOS medium model +- fix deflate with flush (could sometimes generate bad output) +- fix deflateReset (zlib header was incorrectly suppressed) +- added support for VMS +- allow a compression level in gzopen() +- gzflush now calls fflush +- For deflate with flush, flush even if no more input is provided. +- rename libgz.a as libz.a +- avoid complex expression in infcodes.c triggering Turbo C bug +- work around a problem with gcc on Alpha (in INSERT_STRING) +- don't use inline functions (problem with some gcc versions) +- allow renaming of Byte, uInt, etc... with #define. +- avoid warning about (unused) pointer before start of array in deflate.c +- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c +- avoid reserved word 'new' in trees.c + +Changes in 0.93 (25 June 95) +- temporarily disable inline functions +- make deflate deterministic +- give enough lookahead for PARTIAL_FLUSH +- Set binary mode for stdin/stdout in minigzip.c for OS/2 +- don't even use signed char in inflate (not portable enough) +- fix inflate memory leak for segmented architectures + +Changes in 0.92 (3 May 95) +- don't assume that char is signed (problem on SGI) +- Clear bit buffer when starting a stored block +- no memcpy on Pyramid +- suppressed inftest.c +- optimized fill_window, put longest_match inline for gcc +- optimized inflate on stored blocks. +- untabify all sources to simplify patches + +Changes in 0.91 (2 May 95) +- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h +- Document the memory requirements in zconf.h +- added "make install" +- fix sync search logic in inflateSync +- deflate(Z_FULL_FLUSH) now works even if output buffer too short +- after inflateSync, don't scare people with just "lo world" +- added support for DJGPP + +Changes in 0.9 (1 May 95) +- don't assume that zalloc clears the allocated memory (the TurboC bug + was Mark's bug after all :) +- let again gzread copy uncompressed data unchanged (was working in 0.71) +- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented +- added a test of inflateSync in example.c +- moved MAX_WBITS to zconf.h because users might want to change that. +- document explicitly that zalloc(64K) on MSDOS must return a normalized + pointer (zero offset) +- added Makefiles for Microsoft C, Turbo C, Borland C++ +- faster crc32() + +Changes in 0.8 (29 April 95) +- added fast inflate (inffast.c) +- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this + is incompatible with previous versions of zlib which returned Z_OK. +- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) + (actually that was not a compiler bug, see 0.81 above) +- gzread no longer reads one extra byte in certain cases +- In gzio destroy(), don't reference a freed structure +- avoid many warnings for MSDOS +- avoid the ERROR symbol which is used by MS Windows + +Changes in 0.71 (14 April 95) +- Fixed more MSDOS compilation problems :( There is still a bug with + TurboC large model. + +Changes in 0.7 (14 April 95) +- Added full inflate support. +- Simplified the crc32() interface. The pre- and post-conditioning + (one's complement) is now done inside crc32(). WARNING: this is + incompatible with previous versions; see zlib.h for the new usage. + +Changes in 0.61 (12 April 95) +- workaround for a bug in TurboC. example and minigzip now work on MSDOS. + +Changes in 0.6 (11 April 95) +- added minigzip.c +- added gzdopen to reopen a file descriptor as gzFile +- added transparent reading of non-gziped files in gzread. +- fixed bug in gzread (don't read crc as data) +- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). +- don't allocate big arrays in the stack (for MSDOS) +- fix some MSDOS compilation problems + +Changes in 0.5: +- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but + not yet Z_FULL_FLUSH. +- support decompression but only in a single step (forced Z_FINISH) +- added opaque object for zalloc and zfree. +- added deflateReset and inflateReset +- added a variable zlib_version for consistency checking. +- renamed the 'filter' parameter of deflateInit2 as 'strategy'. + Added Z_FILTERED and Z_HUFFMAN_ONLY constants. + +Changes in 0.4: +- avoid "zip" everywhere, use zlib instead of ziplib. +- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush + if compression method == 8. +- added adler32 and crc32 +- renamed deflateOptions as deflateInit2, call one or the other but not both +- added the method parameter for deflateInit2. +- added inflateInit2 +- simplied considerably deflateInit and inflateInit by not supporting + user-provided history buffer. This is supported only in deflateInit2 + and inflateInit2. + +Changes in 0.3: +- prefix all macro names with Z_ +- use Z_FINISH instead of deflateEnd to finish compression. +- added Z_HUFFMAN_ONLY +- added gzerror() diff --git a/Utilities/FLTK/zlib/FAQ b/Utilities/FLTK/zlib/FAQ new file mode 100644 index 0000000000..47a7d60c6d --- /dev/null +++ b/Utilities/FLTK/zlib/FAQ @@ -0,0 +1,100 @@ + + Frequently Asked Questions about zlib + + +If your question is not there, please check the zlib home page +http://www.zlib.org which may have more recent information. +The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html + + + 1. Is zlib Y2K-compliant? + + Yes. zlib doesn't handle dates. + + 2. Where can I get a Windows DLL version? + + The zlib sources can be compiled without change to produce a DLL. If you + want a precompiled DLL, see http://www.winimage.com/zLibDll/ . Questions + about the zlib DLL should be sent to Gilles Vollant (info@winimage.com). + + 3. Where can I get a Visual Basic interface to zlib? + + See + * http://www.winimage.com/zLibDll/cmp-z-it.zip + * http://www.dogma.net/markn/articles/zlibtool/zlibtool.htm + * contrib/visual-basic.txt in the zlib distribution + + 4. compress() returns Z_BUF_ERROR + + Make sure that before the call of compress, the length of the compressed + buffer is equal to the total size of the compressed buffer and not + zero. For Visual Basic, check that this parameter is passed by reference + ("as any"), not by value ("as long"). + + 5. deflate() or inflate() returns Z_BUF_ERROR + + Before making the call, make sure that avail_in and avail_out are not + zero. When setting the parameter flush equal to Z_FINISH, also make sure + that avail_out is big enough to allow processing all pending input. + + 6. Where's the zlib documentation (man pages, etc.)? + + It's in zlib.h for the moment, and Francis S. Lin has converted it to a + web page zlib.html. Volunteers to transform this to Unix-style man pages, + please contact Jean-loup Gailly (jloup@gzip.org). Examples of zlib usage + are in the files example.c and minigzip.c. + + 7. Why don't you use GNU autoconf or libtool or ...? + + Because we would like to keep zlib as a very small and simple + package. zlib is rather portable and doesn't need much configuration. + + 8. I found a bug in zlib. + + Most of the time, such problems are due to an incorrect usage of + zlib. Please try to reproduce the problem with a small program and send + the corresponding source to us at zlib@gzip.org . Do not send + multi-megabyte data files without prior agreement. + + 9. Why do I get "undefined reference to gzputc"? + + If "make test" produces something like + + example.o(.text+0x154): undefined reference to `gzputc' + + check that you don't have old files libz.* in /usr/lib, /usr/local/lib or + /usr/X11R6/lib. Remove any old versions, then do "make install". + +10. I need a Delphi interface to zlib. + + See the directories contrib/delphi and contrib/delphi2 in the zlib + distribution. + +11. Can zlib handle .zip archives? + + See the directory contrib/minizip in the zlib distribution. + +12. Can zlib handle .Z files? + + No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt + the code of uncompress on your own. + +13. How can I make a Unix shared library? + + make clean + ./configure -s + make + +14. Why does "make test" fail on Mac OS X? + + Mac OS X already includes zlib as a shared library, and so -lz links the + shared library instead of the one that the "make" compiled. For zlib + 1.1.3, the two are incompatible due to different compile-time + options. Simply change the -lz in the Makefile to libz.a, and it will use + the compiled library instead of the shared one and the "make test" will + succeed. + +15. I have a question about OttoPDF + + We are not the authors of OttoPDF. The real author is on the OttoPDF web + site Joel Hainley jhainley@myndkryme.com. diff --git a/Utilities/FLTK/zlib/INDEX b/Utilities/FLTK/zlib/INDEX new file mode 100644 index 0000000000..a9de7844d1 --- /dev/null +++ b/Utilities/FLTK/zlib/INDEX @@ -0,0 +1,48 @@ +ChangeLog history of changes +FAQ Frequently Asked Questions about zlib +INDEX this file +Makefile makefile for Unix (generated by configure) +Makefile.in makefile for Unix (template for configure) +README guess what +algorithm.txt description of the (de)compression algorithm +configure configure script for Unix +zconf.in.h template for zconf.h (used by configure) + +msdos/ makefiles for MSDOS +old/ makefiles for various architectures and zlib documentation + files that have not yet been updated for zlib 1.2.x +qnx/ makefiles for QNX +win32/ makefiles for Windows + + zlib public header files (must be kept): +zconf.h +zlib.h + + private source files used to build the zlib library: +adler32.c +compress.c +crc32.c +crc32.h +deflate.c +deflate.h +gzio.c +infback.c +inffast.c +inffast.h +inffixed.h +inflate.c +inflate.h +inftrees.c +inftrees.h +trees.c +trees.h +uncompr.c +zutil.c +zutil.h + + source files for sample programs: +example.c +minigzip.c + + unsupported contribution by third parties +See contrib/README.contrib diff --git a/Utilities/FLTK/zlib/Makefile b/Utilities/FLTK/zlib/Makefile new file mode 100644 index 0000000000..398504bd67 --- /dev/null +++ b/Utilities/FLTK/zlib/Makefile @@ -0,0 +1,107 @@ +# +# "$Id: Makefile 4052 2005-02-24 21:55:12Z mike $" +# +# GNU ZIP library makefile for the Fast Light Toolkit (FLTK). +# +# Copyright 1997-2005 by Easy Software Products. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. +# +# Please report all bugs and problems to "fltk-bugs@fltk.org". +# + +include ../makeinclude + + +# +# Object files... +# + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o \ + trees.o zutil.o inflate.o inftrees.o inffast.o + +LIBZ = ../lib/libfltk_z$(LIBEXT) + + +# +# Make all targets... +# + +all: $(LIBZ) + + +# +# Clean all targets and object files... +# + +clean: + $(RM) $(OBJS) + $(RM) $(LIBZ) + + +# +# Install everything... +# + +install: $(LIBZ) + echo "Installing libfltk_z$(LIBEXT) in $(libdir)..." + -$(MKDIR) $(libdir) + $(RM) $(libdir)/libfltk_z$(LIBEXT) + $(CP) $(LIBZ) $(libdir) + $(RANLIB) $(libdir)/libfltk_z$(LIBEXT) + echo "Installing zlib headers in $(includedir)/FL/images..." + -$(MKDIR) $(includedir)/FL/images + $(CP) zconf.h zlib.h zutil.h $(includedir)/FL/images + + +# +# Uninstall everything... +# + +uninstall: + echo "Uninstalling libfltk_z$(LIBEXT) in $(libdir)..." + $(RM) $(libdir)/libfltk_z$(LIBEXT) + echo "Uninstalling zlib headers in $(includedir)/FL/images..." + $(RM) $(includedir)/FL/images/zconf.h + $(RM) $(includedir)/FL/images/zlib.h + $(RM) $(includedir)/FL/images/zutil.h + + +# +# libfltk_z.a +# + +$(LIBZ): $(OBJS) + echo Archiving $@... + $(RM) $@ + $(LIBCOMMAND) $@ $(OBJS) + $(RANLIB) $@ + +# +# Make dependencies... +# + +depend: $(OBJS:.o=.c) + makedepend -Y -I.. -f makedepend $(OBJS:.o=.c) + +include makedepend + +$(OBJS): ../makeinclude + + +# +# End of "$Id: Makefile 4052 2005-02-24 21:55:12Z mike $". +# diff --git a/Utilities/FLTK/zlib/README b/Utilities/FLTK/zlib/README new file mode 100644 index 0000000000..0f1205481c --- /dev/null +++ b/Utilities/FLTK/zlib/README @@ -0,0 +1,126 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.1 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) +and rfc1952.txt (gzip format). These documents are also available in other +formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example +of the library is given in the file example.c which also tests that the library +is working correctly. Another example is given in the file minigzip.c. The +compression library itself is composed of all source files except example.c and +minigzip.c. + +To compile all files and run the test program, follow the instructions given at +the top of Makefile. In short "make test; make install" should work for most +machines. For Unix: "./configure; make test; make install" For MSDOS, use one +of the special makefiles such as Makefile.msc. For VMS, use Make_vms.com or +descrip.mms. + +Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant +<info@winimage.com> for the Windows DLL version. The zlib home page is +http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem, +please check this site to verify that you have the latest version of zlib; +otherwise get the latest version and check whether the problem still exists or +not. + +PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking +for help. + +Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available in +http://dogma.net/markn/articles/zlibtool/zlibtool.htm + +The changes made in version 1.2.1 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory "contrib". + +A Java implementation of zlib is available in the Java Development Kit +http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html +See the zlib home page http://www.zlib.org for details. + +A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is in the +CPAN (Comprehensive Perl Archive Network) sites +http://www.cpan.org/modules/by-module/Compress/ + +A Python interface to zlib written by A.M. Kuchling <amk@magnet.com> is +available in Python 1.5 and later versions, see +http://www.python.org/doc/lib/module-zlib.html + +A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com> is +availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant <info@winimage.com>, is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. + +- For PalmOs, see http://palmzlib.sourceforge.net/ + +- When building a shared, i.e. dynamic library on Mac OS X, the library must be + installed before testing (do "make install" before "make test"), since the + library location is specified in the library. + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate + and zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; + they are too numerous to cite here. + +Copyright notice: + + (C) 1995-2003 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* +receiving lengthy legal documents to sign. The sources are provided +for free but without warranty of any kind. The library has been +entirely written by Jean-loup Gailly and Mark Adler; it does not +include third-party code. + +If you redistribute modified sources, we would appreciate that you include +in the file ChangeLog history information documenting your changes. Please +read the FAQ for more information on the distribution of modified source +versions. diff --git a/Utilities/FLTK/zlib/adler32.c b/Utilities/FLTK/zlib/adler32.c new file mode 100644 index 0000000000..624a1696eb --- /dev/null +++ b/Utilities/FLTK/zlib/adler32.c @@ -0,0 +1,74 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? (int)len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + MOD(s1); + MOD(s2); + } + return (s2 << 16) | s1; +} diff --git a/Utilities/FLTK/zlib/algorithm.txt b/Utilities/FLTK/zlib/algorithm.txt new file mode 100644 index 0000000000..b022dde312 --- /dev/null +++ b/Utilities/FLTK/zlib/algorithm.txt @@ -0,0 +1,209 @@ +1. Compression algorithm (deflate) + +The deflation algorithm used by gzip (also zip and zlib) is a variation of +LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in +the input data. The second occurrence of a string is replaced by a +pointer to the previous string, in the form of a pair (distance, +length). Distances are limited to 32K bytes, and lengths are limited +to 258 bytes. When a string does not occur anywhere in the previous +32K bytes, it is emitted as a sequence of literal bytes. (In this +description, `string' must be taken as an arbitrary sequence of bytes, +and is not restricted to printable characters.) + +Literals or match lengths are compressed with one Huffman tree, and +match distances are compressed with another tree. The trees are stored +in a compact form at the start of each block. The blocks can have any +size (except that the compressed data for one block must fit in +available memory). A block is terminated when deflate() determines that +it would be useful to start another block with fresh trees. (This is +somewhat similar to the behavior of LZW-based _compress_.) + +Duplicated strings are found using a hash table. All input strings of +length 3 are inserted in the hash table. A hash index is computed for +the next 3 bytes. If the hash chain for this index is not empty, all +strings in the chain are compared with the current input string, and +the longest match is selected. + +The hash chains are searched starting with the most recent strings, to +favor small distances and thus take advantage of the Huffman encoding. +The hash chains are singly linked. There are no deletions from the +hash chains, the algorithm simply discards matches that are too old. + +To avoid a worst-case situation, very long hash chains are arbitrarily +truncated at a certain length, determined by a runtime option (level +parameter of deflateInit). So deflate() does not always find the longest +possible match but generally finds a match which is long enough. + +deflate() also defers the selection of matches with a lazy evaluation +mechanism. After a match of length N has been found, deflate() searches for +a longer match at the next input byte. If a longer match is found, the +previous match is truncated to a length of one (thus producing a single +literal byte) and the process of lazy evaluation begins again. Otherwise, +the original match is kept, and the next match search is attempted only N +steps later. + +The lazy match evaluation is also subject to a runtime parameter. If +the current match is long enough, deflate() reduces the search for a longer +match, thus speeding up the whole process. If compression ratio is more +important than speed, deflate() attempts a complete second search even if +the first match is already long enough. + +The lazy match evaluation is not performed for the fastest compression +modes (level parameter 1 to 3). For these fast modes, new strings +are inserted in the hash table only when no match was found, or +when the match is not too long. This degrades the compression ratio +but saves time since there are both fewer insertions and fewer searches. + + +2. Decompression algorithm (inflate) + +2.1 Introduction + +The key question is how to represent a Huffman code (or any prefix code) so +that you can decode fast. The most important characteristic is that shorter +codes are much more common than longer codes, so pay attention to decoding the +short codes fast, and let the long codes take longer to decode. + +inflate() sets up a first level table that covers some number of bits of +input less than the length of longest code. It gets that many bits from the +stream, and looks it up in the table. The table will tell if the next +code is that many bits or less and how many, and if it is, it will tell +the value, else it will point to the next level table for which inflate() +grabs more bits and tries to decode a longer code. + +How many bits to make the first lookup is a tradeoff between the time it +takes to decode and the time it takes to build the table. If building the +table took no time (and if you had infinite memory), then there would only +be a first level table to cover all the way to the longest code. However, +building the table ends up taking a lot longer for more bits since short +codes are replicated many times in such a table. What inflate() does is +simply to make the number of bits in the first table a variable, and then +to set that variable for the maximum speed. + +For inflate, which has 286 possible codes for the literal/length tree, the size +of the first table is nine bits. Also the distance trees have 30 possible +values, and the size of the first table is six bits. Note that for each of +those cases, the table ended up one bit longer than the ``average'' code +length, i.e. the code length of an approximately flat code which would be a +little more than eight bits for 286 symbols and a little less than five bits +for 30 symbols. + + +2.2 More details on the inflate table lookup + +Ok, you want to know what this cleverly obfuscated inflate tree actually +looks like. You are correct that it's not a Huffman tree. It is simply a +lookup table for the first, let's say, nine bits of a Huffman symbol. The +symbol could be as short as one bit or as long as 15 bits. If a particular +symbol is shorter than nine bits, then that symbol's translation is duplicated +in all those entries that start with that symbol's bits. For example, if the +symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a +symbol is nine bits long, it appears in the table once. + +If the symbol is longer than nine bits, then that entry in the table points +to another similar table for the remaining bits. Again, there are duplicated +entries as needed. The idea is that most of the time the symbol will be short +and there will only be one table look up. (That's whole idea behind data +compression in the first place.) For the less frequent long symbols, there +will be two lookups. If you had a compression method with really long +symbols, you could have as many levels of lookups as is efficient. For +inflate, two is enough. + +So a table entry either points to another table (in which case nine bits in +the above example are gobbled), or it contains the translation for the symbol +and the number of bits to gobble. Then you start again with the next +ungobbled bit. + +You may wonder: why not just have one lookup table for how ever many bits the +longest symbol is? The reason is that if you do that, you end up spending +more time filling in duplicate symbol entries than you do actually decoding. +At least for deflate's output that generates new trees every several 10's of +kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code +would take too long if you're only decoding several thousand symbols. At the +other extreme, you could make a new table for every bit in the code. In fact, +that's essentially a Huffman tree. But then you spend two much time +traversing the tree while decoding, even for short symbols. + +So the number of bits for the first lookup table is a trade of the time to +fill out the table vs. the time spent looking at the second level and above of +the table. + +Here is an example, scaled down: + +The code being decoded, with 10 symbols, from 1 to 6 bits long: + +A: 0 +B: 10 +C: 1100 +D: 11010 +E: 11011 +F: 11100 +G: 11101 +H: 11110 +I: 111110 +J: 111111 + +Let's make the first table three bits long (eight entries): + +000: A,1 +001: A,1 +010: A,1 +011: A,1 +100: B,2 +101: B,2 +110: -> table X (gobble 3 bits) +111: -> table Y (gobble 3 bits) + +Each entry is what the bits decode as and how many bits that is, i.e. how +many bits to gobble. Or the entry points to another table, with the number of +bits to gobble implicit in the size of the table. + +Table X is two bits long since the longest code starting with 110 is five bits +long: + +00: C,1 +01: C,1 +10: D,2 +11: E,2 + +Table Y is three bits long since the longest code starting with 111 is six +bits long: + +000: F,2 +001: F,2 +010: G,2 +011: G,2 +100: H,2 +101: H,2 +110: I,3 +111: J,3 + +So what we have here are three tables with a total of 20 entries that had to +be constructed. That's compared to 64 entries for a single table. Or +compared to 16 entries for a Huffman tree (six two entry tables and one four +entry table). Assuming that the code ideally represents the probability of +the symbols, it takes on the average 1.25 lookups per symbol. That's compared +to one lookup for the single table, or 1.66 lookups per symbol for the +Huffman tree. + +There, I think that gives you a picture of what's going on. For inflate, the +meaning of a particular symbol is often more than just a letter. It can be a +byte (a "literal"), or it can be either a length or a distance which +indicates a base value and a number of bits to fetch after the code that is +added to the base value. Or it might be the special end-of-block code. The +data structures created in inftrees.c try to encode all that information +compactly in the tables. + + +Jean-loup Gailly Mark Adler +jloup@gzip.org madler@alumni.caltech.edu + + +References: + +[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data +Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, +pp. 337-343. + +``DEFLATE Compressed Data Format Specification'' available in +http://www.ietf.org/rfc/rfc1951.txt diff --git a/Utilities/FLTK/zlib/compress.c b/Utilities/FLTK/zlib/compress.c new file mode 100644 index 0000000000..24ef029191 --- /dev/null +++ b/Utilities/FLTK/zlib/compress.c @@ -0,0 +1,79 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; +} diff --git a/Utilities/FLTK/zlib/crc32.c b/Utilities/FLTK/zlib/crc32.c new file mode 100644 index 0000000000..689b2883b4 --- /dev/null +++ b/Utilities/FLTK/zlib/crc32.c @@ -0,0 +1,311 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results about a factor + * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +#ifdef MAKECRCH +# include <stdio.h> +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include <limits.h> +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +#ifdef DYNAMIC_CRC_TABLE + +local int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ + +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, and + then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ diff --git a/Utilities/FLTK/zlib/crc32.h b/Utilities/FLTK/zlib/crc32.h new file mode 100644 index 0000000000..8053b6117c --- /dev/null +++ b/Utilities/FLTK/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/Utilities/FLTK/zlib/deflate.c b/Utilities/FLTK/zlib/deflate.c new file mode 100644 index 0000000000..0525b2f33c --- /dev/null +++ b/Utilities/FLTK/zlib/deflate.c @@ -0,0 +1,1502 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.1 Copyright 1995-2003 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifndef FASTEST +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif +#endif +local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds + * for every combination of windowBits and memLevel, as well as wrap. + * But even the conservative upper bound of about 14% expansion does not + * seem onerous for output buffer allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong destLen; + + /* conservative upper bound */ + destLen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; + + /* if can't get parameters, return conservative bound */ + if (strm == Z_NULL || strm->state == Z_NULL) + return destLen; + + /* if not default parameters, return conservative bound */ + s = strm->state; + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return destLen; + + /* default settings: return tight bound for that case */ + return compressBound(sourceLen); +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, 255); + s->status = BUSY_STATE; + strm->adler = crc32(0L, Z_NULL, 0); + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + *dest = *source; + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ +#endif /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 or strategy == Z_RLE only + */ +local uInt longest_match_fast(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ +#ifdef FASTEST + if ((s->strategy < Z_HUFFMAN_ONLY) || + (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { + s->match_length = longest_match_fast (s, hash_head); + } +#else + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } +#endif + /* longest_match() or longest_match_fast() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } + /* longest_match() or longest_match_fast() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ diff --git a/Utilities/FLTK/zlib/deflate.h b/Utilities/FLTK/zlib/deflate.h new file mode 100644 index 0000000000..e31f66be52 --- /dev/null +++ b/Utilities/FLTK/zlib/deflate.h @@ -0,0 +1,326 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + Byte data_type; /* UNKNOWN, BINARY or ASCII */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/Utilities/FLTK/zlib/gzio.c b/Utilities/FLTK/zlib/gzio.c new file mode 100644 index 0000000000..4afd102b3f --- /dev/null +++ b/Utilities/FLTK/zlib/gzio.c @@ -0,0 +1,1005 @@ +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. + */ + +/* @(#) $Id$ */ + +#include <stdio.h> + +#include "zutil.h" + +#ifdef NO_DEFLATE /* for compatiblity with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#ifdef __MVS__ +# pragma map (fdopen , "\174\174FDOPEN") + FILE *fdopen(int, const char *); +#endif + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern void free OF((voidpf ptr)); +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + z_off_t start; /* start of compressed data in file (header skipped) */ + z_off_t in; /* bytes into deflate or inflate */ + z_off_t out; /* bytes out of deflate or inflate */ + int back; /* one character push-back */ + int last; /* true if push-back is last character */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->in = 0; + s->out = 0; + s->back = EOF; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else if (*p == 'R') { + strategy = Z_RLE; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->start = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * start anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->start = ftell(s->file) - s->stream.avail_in; + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[20]; + + if (fd < 0) return (gzFile)Z_NULL; + sprintf(name, "<fd:%d>", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ +local int get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Assure two bytes in the buffer so we can peek ahead -- handle case + where first byte of header is at the end of the buffer after the last + gzip segment */ + len = s->stream.avail_in; + if (len < 2) { + if (len) s->inbuf[0] = s->stream.next_in[0]; + errno = 0; + len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); + if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; + s->stream.avail_in += len; + s->stream.next_in = s->inbuf; + if (s->stream.avail_in < 2) { + s->transparent = s->stream.avail_in; + return; + } + } + + /* Peek ahead to check the gzip magic header */ + if (s->stream.next_in[0] != gz_magic[0] || + s->stream.next_in[1] != gz_magic[1]) { + s->transparent = 1; + return; + } + s->stream.avail_in -= 2; + s->stream.next_in += 2; + + /* Check the rest of the gzip header */ + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + if (s->stream.avail_out && s->back != EOF) { + *next_out++ = s->back; + s->stream.next_out++; + s->stream.avail_out--; + s->back = EOF; + s->out++; + if (s->last) { + s->z_err = Z_STREAM_END; + return 1; + } + } + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, + s->file); + } + len -= s->stream.avail_out; + s->in += len; + s->out += len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may be + * different from s->out in case of concatenated .gz files. + * Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + inflateReset(&(s->stream)); + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Push one byte back onto the stream. +*/ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; + s->back = c; + s->out--; + s->last = (s->z_err == Z_STREAM_END); + if (s->last) s->z_err = Z_OK; + s->z_eof = 0; + return c; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_GZCOMPRESS +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include <stdarg.h> + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + buf[sizeof(buf) - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(buf, format, va); + va_end(va); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = vsprintf(buf, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(buf, sizeof(buf), format, va); + va_end(va); + len = strlen(buf); +# else + len = vsnprintf(buf, sizeof(buf), format, va); + va_end(va); +# endif +#endif + if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + + buf[sizeof(buf) - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(buf); +# else + len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), flush); + s->out -= s->stream.avail_out; + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_GZCOMPRESS */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + if (s->inbuf == Z_NULL) return -1L; + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return s->in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->in = s->out = offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if (offset >= s->out) { + offset -= s->out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + if (s->outbuf == Z_NULL) return -1L; + } + if (offset && s->back != EOF) { + s->back = EOF; + s->out++; + offset--; + if (s->last) s->z_err = Z_STREAM_END; + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return s->out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + if (!s->transparent) (void)inflateReset(&s->stream); + s->in = 0; + s->out = 0; + return fseek(s->file, s->start, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + /* With concatenated compressed files that can have embedded + * crc trailers, z_eof is no longer the only/best indicator of EOF + * on a gz_stream. Handle end-of-stream error explicitly here. + */ + if (s == NULL || s->mode != 'r') return 0; + if (s->z_eof) return 1; + return s->z_err == Z_STREAM_END; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + int err; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return Z_STREAM_ERROR; +#else + err = do_flush (file, Z_FINISH); + if (err != Z_OK) return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, (uLong)(s->in & 0xffffffff)); +#endif + } + return destroy((gz_stream*)file); +} + +/* =========================================================================== + Returns the error message for the last error which occured on the + given compressed file. errnum is set to zlib error number. If an + error occured in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ +const char * ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); + strcpy(s->msg, s->path); + strcat(s->msg, ": "); + strcat(s->msg, m); + return (const char*)s->msg; +} + +/* =========================================================================== + Clear the error and end-of-file flags, and do the same for the real file. +*/ +void ZEXPORT gzclearerr (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return; + if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; + s->z_eof = 0; + clearerr(s->file); +} diff --git a/Utilities/FLTK/zlib/inffast.c b/Utilities/FLTK/zlib/inffast.c new file mode 100644 index 0000000000..c716440a92 --- /dev/null +++ b/Utilities/FLTK/zlib/inffast.c @@ -0,0 +1,305 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - 68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/Utilities/FLTK/zlib/inffast.h b/Utilities/FLTK/zlib/inffast.h new file mode 100644 index 0000000000..1e88d2d97b --- /dev/null +++ b/Utilities/FLTK/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/Utilities/FLTK/zlib/inffixed.h b/Utilities/FLTK/zlib/inffixed.h new file mode 100644 index 0000000000..75ed4b5978 --- /dev/null +++ b/Utilities/FLTK/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/Utilities/FLTK/zlib/inflate.c b/Utilities/FLTK/zlib/inflate.c new file mode 100644 index 0000000000..a53b5c7446 --- /dev/null +++ b/Utilities/FLTK/zlib/inflate.c @@ -0,0 +1,1270 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common write == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->wsize = 0; + state->whave = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) windowBits &= 15; +#endif + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include <stdio.h> + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + if (BITS(4) + 8 > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + state->mode = LIT; + break; + } + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->mode != DICT) return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) return Z_DATA_ERROR; + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + *dest = *source; + *copy = *state; + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) + zmemcpy(window, state->window, 1U << state->wbits); + copy->window = window; + dest->state = (voidpf)copy; + return Z_OK; +} diff --git a/Utilities/FLTK/zlib/inflate.h b/Utilities/FLTK/zlib/inflate.h new file mode 100644 index 0000000000..9a12c8fd29 --- /dev/null +++ b/Utilities/FLTK/zlib/inflate.h @@ -0,0 +1,117 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ +#ifdef GUNZIP + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ +#endif + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ +#ifdef GUNZIP + LENGTH, /* i: waiting for 32-bit length (gzip) */ +#endif + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/Utilities/FLTK/zlib/inftrees.c b/Utilities/FLTK/zlib/inftrees.c new file mode 100644 index 0000000000..0b791afd97 --- /dev/null +++ b/Utilities/FLTK/zlib/inftrees.c @@ -0,0 +1,321 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.1 Copyright 1995-2003 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 76, 66}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) return -1; /* no codes! */ + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += 1U << curr; + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + curr = root; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/Utilities/FLTK/zlib/inftrees.h b/Utilities/FLTK/zlib/inftrees.h new file mode 100644 index 0000000000..82d365a7e9 --- /dev/null +++ b/Utilities/FLTK/zlib/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1004 code structures (850 for length/literals + and 154 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 1440 +#define MAXD 154 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/Utilities/FLTK/zlib/makedepend b/Utilities/FLTK/zlib/makedepend new file mode 100644 index 0000000000..5712851699 --- /dev/null +++ b/Utilities/FLTK/zlib/makedepend @@ -0,0 +1,13 @@ +# DO NOT DELETE + +adler32.o: zlib.h zconf.h +compress.o: zlib.h zconf.h +crc32.o: zutil.h zlib.h zconf.h crc32.h +gzio.o: zutil.h zlib.h zconf.h +uncompr.o: zlib.h zconf.h +deflate.o: deflate.h zutil.h zlib.h zconf.h +trees.o: deflate.h zutil.h zlib.h zconf.h trees.h +zutil.o: zutil.h zlib.h zconf.h +inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h inffixed.h +inftrees.o: zutil.h zlib.h zconf.h inftrees.h +inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h diff --git a/Utilities/FLTK/zlib/makefile.wat b/Utilities/FLTK/zlib/makefile.wat new file mode 100644 index 0000000000..00a8755b74 --- /dev/null +++ b/Utilities/FLTK/zlib/makefile.wat @@ -0,0 +1,60 @@ +# +# "$Id: makefile.wat 4359 2005-05-19 16:07:13Z mike $" +# +# GNU ZIP library makefile for the Fast Light Toolkit (FLTK). +# +# Copyright 1997-2004 by Easy Software Products. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. +# +# Please report all bugs and problems to "fltk-bugs@fltk.org". +# + +LIBNAMEROOT=ftlk_z + +!include ../watcom.mif + + +# +# Object files... +# + +LIBOBJS = adler32.obj compress.obj crc32.obj gzio.obj uncompr.obj deflate.obj & + trees.obj zutil.obj inflate.obj inftrees.obj inffast.obj + + +# +# Make all targets... +# + +all: $(LIBNAME) + +$(LIBNAME): $(LIBOBJS) + $(LIB) $(LIBOPTS) $@ $< + +# +# Clean all directories +# +clean : .SYMBOLIC + @echo Cleaning up. +CLEANEXTS = obj + @for %a in ($(CLEANEXTS)) do -rm -f $(ODIR)\*.%a + -rm -f *.err + -rm -f $(LIBNAME) + +# +# End of "$Id: makefile.wat 4359 2005-05-19 16:07:13Z mike $". +# diff --git a/Utilities/FLTK/zlib/trees.c b/Utilities/FLTK/zlib/trees.c new file mode 100644 index 0000000000..bb09554938 --- /dev/null +++ b/Utilities/FLTK/zlib/trees.c @@ -0,0 +1,1215 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2003 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include <ctype.h> +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1<<extra_lbits[code]); n++) { + _length_code[length++] = (uch)code; + } + } + Assert (length == 256, "tr_static_init: length != 256"); + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: + */ + _length_code[length-1] = (uch)code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<<extra_dbits[code]); n++) { + _dist_code[dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: dist != 256"); + dist >>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include <stdio.h> +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, + "inconsistent bit counts"); + Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); + + for (n = 0; n <= max_code; n++) { + int len = tree[n].Len; + if (len == 0) continue; + /* Now reverse the bits */ + tree[n].Code = bi_reverse(next_code[len]++, len); + + Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", + n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); + } +} + +/* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ +local void build_tree(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is ascii or binary */ + if (s->data_type == Z_UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +local void set_data_type(s) + deflate_state *s; +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/Utilities/FLTK/zlib/trees.h b/Utilities/FLTK/zlib/trees.h new file mode 100644 index 0000000000..72facf900f --- /dev/null +++ b/Utilities/FLTK/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/Utilities/FLTK/zlib/uncompr.c b/Utilities/FLTK/zlib/uncompr.c new file mode 100644 index 0000000000..b59e3d0def --- /dev/null +++ b/Utilities/FLTK/zlib/uncompr.c @@ -0,0 +1,61 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/Utilities/FLTK/zlib/zconf.h b/Utilities/FLTK/zlib/zconf.h new file mode 100644 index 0000000000..3cea897eda --- /dev/null +++ b/Utilities/FLTK/zlib/zconf.h @@ -0,0 +1,323 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflatePrime z_deflatePrime +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include <windows.h> + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include <sys/types.h> /* for off_t */ +# include <unistd.h> /* for SEEK_* and off_t */ +# ifdef VMS +# include <unixio.h> /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +#define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/Utilities/FLTK/zlib/zlib.3 b/Utilities/FLTK/zlib/zlib.3 new file mode 100644 index 0000000000..890098449d --- /dev/null +++ b/Utilities/FLTK/zlib/zlib.3 @@ -0,0 +1,159 @@ +.TH ZLIB 3 "17 November 2003" +.SH NAME +zlib \- compression/decompression library +.SH SYNOPSIS +[see +.I zlib.h +for full description] +.SH DESCRIPTION +The +.I zlib +library is a general purpose data compression library. +The code is thread safe. +It provides in-memory compression and decompression functions, +including integrity checks of the uncompressed data. +This version of the library supports only one compression method (deflation) +but other algorithms will be added later +and will have the same stream interface. +.LP +Compression can be done in a single step if the buffers are large enough +(for example if an input file is mmap'ed), +or can be done by repeated calls of the compression function. +In the latter case, +the application must provide more input and/or consume the output +(providing more output space) before each call. +.LP +The library also supports reading and writing files in +.IR gzip (1) +(.gz) format +with an interface similar to that of stdio. +.LP +The library does not install any signal handler. +The decoder checks the consistency of the compressed data, +so the library should never crash even in case of corrupted input. +.LP +All functions of the compression library are documented in the file +.IR zlib.h . +The distribution source includes examples of use of the library +in the files +.I example.c +and +.IR minigzip.c . +.LP +Changes to this version are documented in the file +.I ChangeLog +that accompanies the source, +and are concerned primarily with bug fixes and portability enhancements. +.LP +A Java implementation of +.I zlib +is available in the Java Development Kit 1.1: +.IP +http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html +.LP +A Perl interface to +.IR zlib , +written by Paul Marquess (pmqs@cpan.org), +is available at CPAN (Comprehensive Perl Archive Network) sites, +including: +.IP +http://www.cpan.org/modules/by-module/Compress/ +.LP +A Python interface to +.IR zlib , +written by A.M. Kuchling (amk@magnet.com), +is available in Python 1.5 and later versions: +.IP +http://www.python.org/doc/lib/module-zlib.html +.LP +A +.I zlib +binding for +.IR tcl (1), +written by Andreas Kupries (a.kupries@westend.com), +is availlable at: +.IP +http://www.westend.com/~kupries/doc/trf/man/man.html +.LP +An experimental package to read and write files in .zip format, +written on top of +.I zlib +by Gilles Vollant (info@winimage.com), +is available at: +.IP +http://www.winimage.com/zLibDll/unzip.html +and also in the +.I contrib/minizip +directory of the main +.I zlib +web site. +.SH "SEE ALSO" +The +.I zlib +web site can be found at either of these locations: +.IP +http://www.zlib.org +.br +http://www.gzip.org/zlib/ +.LP +The data format used by the zlib library is described by RFC +(Request for Comments) 1950 to 1952 in the files: +.IP +http://www.ietf.org/rfc/rfc1950.txt (concerning zlib format) +.br +http://www.ietf.org/rfc/rfc1951.txt (concerning deflate format) +.br +http://www.ietf.org/rfc/rfc1952.txt (concerning gzip format) +.LP +These documents are also available in other formats from: +.IP +ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html +.LP +Mark Nelson (markn@ieee.org) wrote an article about +.I zlib +for the Jan. 1997 issue of Dr. Dobb's Journal; +a copy of the article is available at: +.IP +http://dogma.net/markn/articles/zlibtool/zlibtool.htm +.SH "REPORTING PROBLEMS" +Before reporting a problem, +please check the +.I zlib +web site to verify that you have the latest version of +.IR zlib ; +otherwise, +obtain the latest version and see if the problem still exists. +Please read the +.I zlib +FAQ at: +.IP +http://www.gzip.org/zlib/zlib_faq.html +.LP +before asking for help. +Send questions and/or comments to zlib@gzip.org, +or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). +.SH AUTHORS +Version 1.2.1 +Copyright (C) 1995-2003 Jean-loup Gailly (jloup@gzip.org) +and Mark Adler (madler@alumni.caltech.edu). +.LP +This software is provided "as-is," +without any express or implied warranty. +In no event will the authors be held liable for any damages +arising from the use of this software. +See the distribution directory with respect to requirements +governing redistribution. +The deflate format used by +.I zlib +was defined by Phil Katz. +The deflate and +.I zlib +specifications were written by L. Peter Deutsch. +Thanks to all the people who reported problems and suggested various +improvements in +.IR zlib ; +who are too numerous to cite here. +.LP +UNIX manual page by R. P. C. Rodgers, +U.S. National Library of Medicine (rodgers@nlm.nih.gov). +.\" end of man page diff --git a/Utilities/FLTK/zlib/zlib.h b/Utilities/FLTK/zlib/zlib.h new file mode 100644 index 0000000000..92edf96ff3 --- /dev/null +++ b/Utilities/FLTK/zlib/zlib.h @@ -0,0 +1,1200 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.1, November 17th, 2003 + + Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.1" +#define ZLIB_VERNUM 0x1210 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by the in-memory functions is the zlib + format, which is a zlib wrapper documented in RFC 1950, wrapped around a + deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + This library does not provide any functions to write gzip files in memory. + However such functions could be easily written using zlib's deflate function, + the documentation in the gzip RFC, and the examples in gzio.c. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it get to the next deflate block boundary. When decoding the zlib + or gzip format, this will cause inflate() to return immediately after the + header and before the first block. When doing a raw inflate, inflate() will + go ahead and process the first block, and will return when it gets to the end + of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_stream FAR *strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/Utilities/FLTK/zlib/zutil.c b/Utilities/FLTK/zlib/zutil.c new file mode 100644 index 0000000000..0ef4f99f57 --- /dev/null +++ b/Utilities/FLTK/zlib/zutil.c @@ -0,0 +1,319 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef STDC +extern void exit OF((int)); +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch (sizeof(uInt)) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch (sizeof(uLong)) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (sizeof(voidpf)) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (sizeof(z_off_t)) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1 << 16; +#endif +#ifdef NO_GZIP + flags += 1 << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1 << 20; +#endif +#ifdef FASTEST + flags += 1 << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1 << 25; +# ifdef HAS_vsprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1 << 26; +# endif +# endif +#else + flags += 1 << 24; +# ifdef NO_snprintf + flags += 1 << 25; +# ifdef HAS_sprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1 << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* does not exist on WCE */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/Utilities/FLTK/zlib/zutil.h b/Utilities/FLTK/zlib/zutil.h new file mode 100644 index 0000000000..87b70acec2 --- /dev/null +++ b/Utilities/FLTK/zlib/zutil.h @@ -0,0 +1,258 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# include <stddef.h> +# include <string.h> +# include <stdlib.h> +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include <errno.h> +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include <alloc.h> +# endif +# else /* MSC or DJGPP */ +# include <malloc.h> +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include <unix.h> /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif + +#ifdef HAVE_STRERROR + extern char *strerror OF((int)); +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include <stdio.h> + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ -- GitLab