% File: latex.sl -*- mode: SLang -*- % % Copyright (c) % 2007 Jörg Sommer % $Id: latex_pst.sl 199 2007-08-23 23:28:52Z joerg $ % % -*- This file is part of Jörg's LaTeX Mode (JLM) -*- % % Description: This file contains all functions related to PSTricks. % % License: This program is free software; you can redistribute it and/or % modify it under the terms of the GNU General Public License as % published by the Free Software Foundation; either version 2 of % the License, or (at your option) any later version. % % This program is distributed in the hope that it will be % useful, but WITHOUT ANY WARRANTY; without even the implied % warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR % PURPOSE. See the GNU General Public License for more details. %%%%%%%%%% % % A point in PSTricks % typedef struct { x, y, mark } Pst_Point_Type; static define pst_point_as_string(pnt) { return "(" + string(pnt.x) + "," + string(pnt.y) + ")"; } __add_string(Pst_Point_Type, &pst_point_as_string()); static define pst_new_point() % (x, y[, mark]) { variable pnt = @Pst_Point_Type; if (_NARGS > 2) pnt.mark = (); pnt.y = (); pnt.x = (); return pnt; } static define pst_add_points(a, b) { return pst_new_point(a.x + b.x, a.y + b.y); } __add_binary("+", Pst_Point_Type, &pst_add_points(), Pst_Point_Type, Pst_Point_Type); static define pst_point_min(pnt1, pnt2) { return pst_new_point( min([pnt1.x, pnt2.x]), min([pnt1.y, pnt2.y]) ); } static define pst_point_max(pnt1, pnt2) { return pst_new_point( max([pnt1.x, pnt2.x]), max([pnt1.y, pnt2.y]) ); } static define pst_looking_at_point() { % return re_looking_at("[ \t\n]*('); return looking_at_char('('); } static define pst_skip_point() { return andelse {fsearch_char(')')} {right(1)}; } static define pst_update_point(pnt, new_pnt) { if (pnt.mark == NULL) throw UsageError, "pnt is not a real point"; push_spot(); EXIT_BLOCK { pop_spot(); } goto_user_mark(pnt.mark); % insert before delete to make a spot after the deleted string is left % there insert( pst_point_as_string(new_pnt) ); push_mark(); () = pst_skip_point(); del_region(); pnt.x = new_pnt.x; pnt.y = new_pnt.y; } static define pst_read_point() { !if ( pst_looking_at_point() ) throw UsageError, "No at a point"; variable mark = create_user_mark(); () = right(1); push_mark(); !if ( pst_skip_point() ) { pop_mark(0); goto_user_mark(mark); throw DataError, "This doesn't look like a PSTricks point ($what_line,"$ + string(what_column()) + ")"; } variable x, y; if ( sscanf(str_delete_chars(bufsubstr(), "\s"R), "%g,%g", &x, &y) != 2 ) { goto_user_mark(mark); throw DataError, "This doesn't look like a PSTricks point ($what_line,"$ + string(what_column()) + ")"; } return pst_new_point(x, y, mark); } private define pst_extract_points_from_region() { check_region(1); EXIT_BLOCK { pop_spot(); } variable end_mark = create_user_mark(); pop_mark(1); variable point_list = list_new(); while (create_user_mark() < end_mark) { skip_chars("^\\{"R); if ( is_commented() ) { eol(); continue; } if ( looking_at("\\{") or looking_at("\\\\") ) { () = right(2); continue; } if ( looking_at_char('{') ) { fsearch_matching_brace(); continue; } () = right(1); push_mark(); skip_chars(TeX_Command_Chars); !if ( is_list_element("rput,psframe,psline,pscircle,psbezier,psdot,psdots,psaxes", bufsubstr(), ',') ) continue; (,) = cmd_parse_args(1,0); !if ( pst_looking_at_point() ) throw DataError, "Malformed pstricks command in line $what_line"$; do { list_append(point_list, pst_read_point()); } while ( pst_looking_at_point() ); } return point_list; } %%%%%%%%%% % % PSTricks % static variable PST_Origin = pst_new_point(0,0); static define pst_enlarge_pic(point) { push_spot(); EXIT_BLOCK { pop_spot(); } boenv(); !if ( looking_at("\\begin{pspicture}") ) throw UsageError, "This is not a pspicture environment"; () = right(17); if ( pst_looking_at_point() ) { variable old_point = pst_read_point(), tmp_point; if ( pst_looking_at_point() ) { tmp_point = pst_point_min(old_point, point); if (tmp_point.x < old_point.x or tmp_point.y < old_point.y) { if (tmp_point.x == PST_Origin.x and tmp_point.y == PST_Origin.y) { push_spot(); goto_user_mark(old_point.mark); push_mark(); pst_skip_point(); del_region(); pop_spot(); } else pst_update_point(old_point, tmp_point); } old_point = pst_read_point(); } else if (point.x < PST_Origin.x or point.y < PST_Origin.y) { push_spot(); goto_user_mark(old_point.mark); insert( pst_point_as_string(pst_point_min(PST_Origin, point)) ); pop_spot(); } tmp_point = pst_point_max(old_point, point); if (old_point.x < tmp_point.x or old_point.y < tmp_point.y) { if (tmp_point.x == PST_Origin.x and tmp_point.y == PST_Origin.y) { push_spot(); goto_user_mark(old_point.mark); push_mark(); pst_skip_point(); del_region(); pop_spot(); } else pst_update_point(old_point, tmp_point); } } else { if (point.x < PST_Origin.x or point.y < PST_Origin.y) insert( pst_point_as_string(pst_point_min(point, PST_Origin)) + pst_point_as_string(pst_point_max(point, PST_Origin)) ); else if (point.x > PST_Origin.x or point.y > PST_Origin.y) insert( pst_point_as_string(point) ); } } static define pst_update_pic_size() { push_spot(); EXIT_BLOCK { pop_spot(); } boenv(); !if ( looking_at("\\begin{pspicture}") ) throw UsageError, "This is not a pspicture environment"; () = right(17); while ( pst_looking_at_point() ) () = pst_skip_point(); push_mark(); eoenv(); variable min = PST_Origin, max = PST_Origin; foreach ( pst_extract_points_from_region() ) { dup; min = pst_point_min((), min); max = pst_point_max((), max); } pst_enlarge_pic(min); pst_enlarge_pic(max); } static define pst_move_points() { variable offset; try offset = read_mini("Offset to move points; use X for (X,X) or (X,Y)", "", ""); catch UserBreakError: return; variable x, y; if ( andelse {sscanf(offset, "%g", &x) != 1} {sscanf(offset, "(%g,%g)", &x, &y) != 2}) throw UsageError, "Invalid input for offset"; !if ( __is_initialized(&y) ) y = x; offset = pst_new_point(x, y); variable max = PST_Origin, min = PST_Origin, p; foreach p ( pst_extract_points_from_region() ) { variable new_p = p + offset; min = pst_point_min(min, new_p); max = pst_point_max(max, new_p); pst_update_point(p, new_p); } pst_enlarge_pic(min); pst_enlarge_pic(max); }