Code

Node tool: correctly save node skewing to undo history
[inkscape.git] / src / sp-offset.cpp
index e682f394bb74c41029ce91c6aec088aa84c729ba..51bb1e1ccc190c845e808588b3f47b2a26a99114 100644 (file)
@@ -1,5 +1,3 @@
-#define __SP_OFFSET_C__
-
 /** \file
  * Implementation of <path sodipodi:type="inkscape:offset">.
  */
@@ -8,6 +6,7 @@
  * Authors: (of the sp-spiral.c upon which this file was constructed):
  *   Mitsuru Oka <oka326@parkcity.ne.jp>
  *   Lauris Kaplinski <lauris@kaplinski.com>
+ *   Abhishek Sharma
  *
  * Copyright (C) 1999-2002 Lauris Kaplinski
  * Copyright (C) 2000-2001 Ximian, Inc.
@@ -19,6 +18,8 @@
 # include "config.h"
 #endif
 
+#include <cstring>
+#include <string>
 
 #include "svg/svg.h"
 #include "attributes.h"
 #include "livarot/Shape.h"
 
 #include "enums.h"
-#include "prefs-utils.h"
+#include "preferences.h"
 #include "sp-text.h"
 #include "sp-offset.h"
 #include "sp-use-reference.h"
 #include "uri.h"
 
-#include "libnr/n-art-bpath.h"
 #include <libnr/nr-matrix-fns.h>
+#include <2geom/pathvector.h>
 
 #include "xml/repr.h"
 
@@ -73,7 +74,7 @@ static void sp_offset_finalize(GObject *obj);
 
 static void sp_offset_build (SPObject * object, SPDocument * document,
                              Inkscape::XML::Node * repr);
-static Inkscape::XML::Node *sp_offset_write (SPObject * object, Inkscape::XML::Node * repr,
+static Inkscape::XML::Node *sp_offset_write (SPObject * object, Inkscape::XML::Document *doc, Inkscape::XML::Node * repr,
                                 guint flags);
 static void sp_offset_set (SPObject * object, unsigned int key,
                            const gchar * value);
@@ -81,17 +82,15 @@ static void sp_offset_update (SPObject * object, SPCtx * ctx, guint flags);
 static void sp_offset_release (SPObject * object);
 
 static gchar *sp_offset_description (SPItem * item);
-static void sp_offset_snappoints(SPItem const *item, SnapPointsIter p);
+static void sp_offset_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
 static void sp_offset_set_shape (SPShape * shape);
 
-Path *bpath_to_liv_path (NArtBpath * bpath);
-
 static void refresh_offset_source(SPOffset* offset);
 
 static void sp_offset_start_listening(SPOffset *offset,SPObject* to);
 static void sp_offset_quit_listening(SPOffset *offset);
 static void sp_offset_href_changed(SPObject *old_ref, SPObject *ref, SPOffset *offset);
-static void sp_offset_move_compensate(NR::Matrix const *mp, SPItem *original, SPOffset *self);
+static void sp_offset_move_compensate(Geom::Matrix const *mp, SPItem *original, SPOffset *self);
 static void sp_offset_delete_self(SPObject *deleted, SPOffset *self);
 static void sp_offset_source_modified (SPObject *iSource, guint flags, SPItem *item);
 
@@ -217,39 +216,42 @@ sp_offset_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *rep
     if (((SPObjectClass *) parent_class)->build)
         ((SPObjectClass *) parent_class)->build (object, document, repr);
 
-    if (object->repr->attribute("inkscape:radius")) {
-        sp_object_read_attr (object, "inkscape:radius");
+    //XML Tree being used directly here while it shouldn't be.
+    if (object->getRepr()->attribute("inkscape:radius")) {
+        object->readAttr( "inkscape:radius" );
     } else {
-        gchar const *oldA = object->repr->attribute("sodipodi:radius");
-        object->repr->setAttribute("inkscape:radius",oldA);
-        object->repr->setAttribute("sodipodi:radius",NULL);
+        //XML Tree being used directly here (as object->getRepr) 
+        //in all the below lines in the block while it shouldn't be.
+        gchar const *oldA = object->getRepr()->attribute("sodipodi:radius");
+        object->getRepr()->setAttribute("inkscape:radius",oldA);
+        object->getRepr()->setAttribute("sodipodi:radius",NULL);
 
-        sp_object_read_attr (object, "inkscape:radius");
+        object->readAttr( "inkscape:radius" );
     }
-    if (object->repr->attribute("inkscape:original")) {
-        sp_object_read_attr (object, "inkscape:original");
+    if (object->getRepr()->attribute("inkscape:original")) {
+        object->readAttr( "inkscape:original" );
     } else {
-        gchar const *oldA = object->repr->attribute("sodipodi:original");
-        object->repr->setAttribute("inkscape:original",oldA);
-        object->repr->setAttribute("sodipodi:original",NULL);
+        gchar const *oldA = object->getRepr()->attribute("sodipodi:original");
+        object->getRepr()->setAttribute("inkscape:original",oldA);
+        object->getRepr()->setAttribute("sodipodi:original",NULL);
 
-        sp_object_read_attr (object, "inkscape:original");
+        object->readAttr( "inkscape:original" );
     }
-    if (object->repr->attribute("xlink:href")) {
-        sp_object_read_attr(object, "xlink:href");
+    if (object->getRepr()->attribute("xlink:href")) {
+        object->readAttr( "xlink:href" );
     } else {
-        gchar const *oldA = object->repr->attribute("inkscape:href");
+        gchar const *oldA = object->getRepr()->attribute("inkscape:href");
         if (oldA) {
             size_t lA = strlen(oldA);
-            char *nA=(char*)malloc((lA+1)*sizeof(char));
+            char *nA=(char*)malloc((1+lA+1)*sizeof(char));
             memcpy(nA+1,oldA,lA*sizeof(char));
             nA[0]='#';
             nA[lA+1]=0;
-            object->repr->setAttribute("xlink:href",nA);
+            object->getRepr()->setAttribute("xlink:href",nA);
             free(nA);
-            object->repr->setAttribute("inkscape:href",NULL);
+            object->getRepr()->setAttribute("inkscape:href",NULL);
         }
-        sp_object_read_attr (object, "xlink:href");
+        object->readAttr( "xlink:href" );
     }
 }
 
@@ -257,12 +259,11 @@ sp_offset_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *rep
  * Virtual write: write offset attributes to corresponding repr.
  */
 static Inkscape::XML::Node *
-sp_offset_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
+sp_offset_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
 {
     SPOffset *offset = SP_OFFSET (object);
 
     if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
-        Inkscape::XML::Document *xml_doc = SP_OBJECT_REPR(object)->document();
         repr = xml_doc->createElement("svg:path");
     }
 
@@ -279,18 +280,18 @@ sp_offset_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
 
 
     // Make sure the object has curve
-    SPCurve *curve = sp_shape_get_curve (SP_SHAPE (offset));
+    SPCurve *curve = SP_SHAPE (offset)->getCurve();
     if (curve == NULL) {
         sp_offset_set_shape (SP_SHAPE (offset));
     }
 
     // write that curve to "d"
-    char *d = sp_svg_write_path (SP_CURVE_BPATH(((SPShape *) offset)->curve));
+    char *d = sp_svg_write_path (((SPShape *) offset)->curve->get_pathvector());
     repr->setAttribute("d", d);
     g_free (d);
 
     if (((SPObjectClass *) (parent_class))->write)
-        ((SPObjectClass *) (parent_class))->write (object, repr,
+        ((SPObjectClass *) (parent_class))->write (object, xml_doc, repr,
                                                    flags | SP_SHAPE_WRITE_PATH);
 
     return repr;
@@ -346,16 +347,12 @@ sp_offset_set(SPObject *object, unsigned key, gchar const *value)
                     offset->original = NULL;
                     offset->originalPath = NULL;
                 }
-                NArtBpath *bpath;
-                SPCurve *curve;
 
                 offset->original = strdup (value);
 
-                bpath = sp_svg_read_path (offset->original);
-                curve = sp_curve_new_from_bpath (bpath);       // curve se chargera de detruire bpath
-                g_assert (curve != NULL);
-                offset->originalPath = bpath_to_liv_path (SP_CURVE_BPATH(curve));
-                sp_curve_unref (curve);
+                Geom::PathVector pv = sp_svg_read_pathv(offset->original);
+                offset->originalPath = new Path;
+                reinterpret_cast<Path *>(offset->originalPath)->LoadPathVector(pv);
 
                 offset->knotSet = false;
                 if ( offset->isUpdating == false ) object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
@@ -410,7 +407,7 @@ sp_offset_update(SPObject *object, SPCtx *ctx, guint flags)
     if (flags &
         (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG |
          SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
-        sp_shape_set_shape ((SPShape *) object);
+        ((SPShape *) object)->setShape ();
     }
     offset->isUpdating=false;
 
@@ -437,75 +434,6 @@ sp_offset_description(SPItem *item)
     }
 }
 
-/**
- * Converts an NArtBpath (like the one stored in a SPCurve) into a
- * livarot Path. Duplicate of splivarot.
- */
-Path *
-bpath_to_liv_path(NArtBpath *bpath)
-{
-    if (bpath == NULL)
-        return NULL;
-
-    Path *dest = new Path;
-    dest->SetBackData (false);
-    {
-        int i;
-        bool closed = false;
-        float lastX = 0.0;
-        float lastY = 0.0;
-
-        for (i = 0; bpath[i].code != NR_END; i++)
-        {
-            switch (bpath[i].code)
-            {
-                case NR_LINETO:
-                    lastX = bpath[i].x3;
-                    lastY = bpath[i].y3;
-                    {
-                        NR::Point  tmp(lastX,lastY);
-                        dest->LineTo (tmp);
-                    }
-                    break;
-
-                case NR_CURVETO:
-                {
-                    NR::Point  tmp(bpath[i].x3, bpath[i].y3);
-                    NR::Point  tms;
-                    tms[0]=3 * (bpath[i].x1 - lastX);
-                    tms[1]=3 * (bpath[i].y1 - lastY);
-                    NR::Point  tme;
-                    tme[0]=3 * (bpath[i].x3 - bpath[i].x2);
-                    tme[1]= 3 * (bpath[i].y3 - bpath[i].y2);
-                    dest->CubicTo (tmp,tms,tme);
-                }
-                lastX = bpath[i].x3;
-                lastY = bpath[i].y3;
-                break;
-
-                case NR_MOVETO_OPEN:
-                case NR_MOVETO:
-                    if (closed)
-                        dest->Close ();
-                    closed = (bpath[i].code == NR_MOVETO);
-                    lastX = bpath[i].x3;
-                    lastY = bpath[i].y3;
-                    {
-                        NR::Point tmp(lastX,lastY);
-                        dest->MoveTo(tmp);
-                    }
-                    break;
-                default:
-                    break;
-            }
-        }
-        if (closed)
-            dest->Close ();
-    }
-
-    return dest;
-}
-
 /**
  * Compute and set shape's offset.
  */
@@ -528,13 +456,14 @@ sp_offset_set_shape(SPShape *shape)
         // just put the source shape as the offseted one, no one will notice
         // it's also useless to compute the offset with a 0 radius
 
-        const char *res_d = SP_OBJECT(shape)->repr->attribute("inkscape:original");
+        //XML Tree being used directly here while it shouldn't be.
+        const char *res_d = SP_OBJECT(shape)->getRepr()->attribute("inkscape:original");
         if ( res_d ) {
-            NArtBpath *bpath = sp_svg_read_path (res_d);
-            SPCurve *c = sp_curve_new_from_bpath (bpath);
+            Geom::PathVector pv = sp_svg_read_pathv(res_d);
+            SPCurve *c = new SPCurve(pv);
             g_assert(c != NULL);
-            sp_shape_set_curve_insync ((SPShape *) offset, c, TRUE);
-            sp_curve_unref (c);
+            ((SPShape *) offset)->setCurveInsync (c, TRUE);
+            c->unref();
         }
         return;
     }
@@ -584,10 +513,10 @@ sp_offset_set_shape(SPShape *shape)
         theRes->ConvertToForme (orig, 1, originaux);
 
         SPItem *item = shape;
-        NR::Maybe<NR::Rect> bbox = sp_item_bbox_desktop (item);
-        if ( bbox && !bbox->isEmpty() ) {
+        Geom::OptRect bbox = item->getBboxDesktop ();
+        if ( bbox ) {
             gdouble size = L2(bbox->dimensions());
-            gdouble const exp = NR::expansion(item->transform);
+            gdouble const exp = item->transform.descrim();
             if (exp != 0)
                 size /= exp;
             orig->Coalesce (size * 0.001);
@@ -779,11 +708,11 @@ sp_offset_set_shape(SPShape *shape)
         }
         delete orig;
 
-        NArtBpath *bpath = sp_svg_read_path (res_d);
-        SPCurve *c = sp_curve_new_from_bpath (bpath);
+        Geom::PathVector pv = sp_svg_read_pathv(res_d);
+        SPCurve *c = new SPCurve(pv);
         g_assert(c != NULL);
-        sp_shape_set_curve_insync ((SPShape *) offset, c, TRUE);
-        sp_curve_unref (c);
+        ((SPShape *) offset)->setCurveInsync (c, TRUE);
+        c->unref();
 
         free (res_d);
     }
@@ -792,10 +721,10 @@ sp_offset_set_shape(SPShape *shape)
 /**
  * Virtual snappoints function.
  */
-static void sp_offset_snappoints(SPItem const *item, SnapPointsIter p)
+static void sp_offset_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs)
 {
     if (((SPItemClass *) parent_class)->snappoints) {
-        ((SPItemClass *) parent_class)->snappoints (item, p);
+        ((SPItemClass *) parent_class)->snappoints (item, p, snapprefs);
     }
 }
 
@@ -820,9 +749,9 @@ static void sp_offset_snappoints(SPItem const *item, SnapPointsIter p)
  *    -- njh
  */
 bool
-vectors_are_clockwise (NR::Point A, NR::Point B, NR::Point C)
+vectors_are_clockwise (Geom::Point A, Geom::Point B, Geom::Point C)
 {
-    using NR::rot90;
+    using Geom::rot90;
     double ab_s = dot(A, rot90(B));
     double ab_c = dot(A, B);
     double bc_s = dot(B, rot90(C));
@@ -868,7 +797,7 @@ vectors_are_clockwise (NR::Point A, NR::Point B, NR::Point C)
  * 'px inside source'.
  */
 double
-sp_offset_distance_to_original (SPOffset * offset, NR::Point px)
+sp_offset_distance_to_original (SPOffset * offset, Geom::Point px)
 {
     if (offset == NULL || offset->originalPath == NULL
         || ((Path *) offset->originalPath)->descr_cmd.size() <= 1)
@@ -906,14 +835,14 @@ sp_offset_distance_to_original (SPOffset * offset, NR::Point px)
         {
             if (theRes->getPoint(i).totalDegree() > 0)
            {
-                NR::Point nx = theRes->getPoint(i).x;
-                NR::Point nxpx = px-nx;
+                Geom::Point nx = theRes->getPoint(i).x;
+                Geom::Point nxpx = px-nx;
                 double ndist = sqrt (dot(nxpx,nxpx));
                 if (ptSet == false || fabs (ndist) < fabs (ptDist))
                 {
                     // we have a new minimum distance
                     // now we need to wheck if px is inside or outside (for the sign)
-                    nx = px - theRes->getPoint(i).x;
+                    nx = px - to_2geom(theRes->getPoint(i).x);
                     double nlen = sqrt (dot(nx , nx));
                     nx /= nlen;
                     int pb, cb, fb;
@@ -923,7 +852,7 @@ sp_offset_distance_to_original (SPOffset * offset, NR::Point px)
                     do
                     {
                         // one angle
-                        NR::Point prx, nex;
+                        Geom::Point prx, nex;
                         prx = theRes->getEdge(pb).dx;
                         nlen = sqrt (dot(prx, prx));
                         prx /= nlen;
@@ -959,18 +888,18 @@ sp_offset_distance_to_original (SPOffset * offset, NR::Point px)
                     }
                     while (cb >= 0 && pb >= 0 && pb != fb);
                 }
-           }
+            }
         }
         // loop over the edges to try to improve the distance
         for (int i = 0; i < theRes->numberOfEdges(); i++)
         {
-            NR::Point sx = theRes->getPoint(theRes->getEdge(i).st).x;
-            NR::Point ex = theRes->getPoint(theRes->getEdge(i).en).x;
-            NR::Point nx = ex - sx;
+            Geom::Point sx = theRes->getPoint(theRes->getEdge(i).st).x;
+            Geom::Point ex = theRes->getPoint(theRes->getEdge(i).en).x;
+            Geom::Point nx = ex - sx;
             double len = sqrt (dot(nx,nx));
             if (len > 0.0001)
-           {
-                NR::Point   pxsx=px-sx;
+            {
+                Geom::Point   pxsx=px-sx;
                 double ab = dot(nx,pxsx);
                 if (ab > 0 && ab < len * len)
                 {
@@ -982,7 +911,7 @@ sp_offset_distance_to_original (SPOffset * offset, NR::Point px)
                         arSet = true;
                     }
                 }
-           }
+            }
         }
         if (arSet || ptSet)
         {
@@ -1010,9 +939,9 @@ sp_offset_distance_to_original (SPOffset * offset, NR::Point px)
  * \return the topmost point on the offset.
  */
 void
-sp_offset_top_point (SPOffset * offset, NR::Point *px)
+sp_offset_top_point (SPOffset * offset, Geom::Point *px)
 {
-    (*px) = NR::Point(0, 0);
+    (*px) = Geom::Point(0, 0);
     if (offset == NULL)
         return;
 
@@ -1022,22 +951,23 @@ sp_offset_top_point (SPOffset * offset, NR::Point *px)
         return;
     }
 
-    SPCurve *curve = sp_shape_get_curve (SP_SHAPE (offset));
+    SPCurve *curve = SP_SHAPE (offset)->getCurve();
     if (curve == NULL)
     {
         sp_offset_set_shape (SP_SHAPE (offset));
-        curve = sp_shape_get_curve (SP_SHAPE (offset));
+        curve = SP_SHAPE (offset)->getCurve();
         if (curve == NULL)
             return;
     }
-
-    Path *finalPath = bpath_to_liv_path (SP_CURVE_BPATH(curve));
-    if (finalPath == NULL)
+    if (curve->is_empty())
     {
-        sp_curve_unref (curve);
+        curve->unref();
         return;
     }
 
+    Path *finalPath = new Path;
+    finalPath->LoadPathVector(curve->get_pathvector());
+
     Shape *theShape = new Shape;
 
     finalPath->Convert (1.0);
@@ -1051,7 +981,7 @@ sp_offset_top_point (SPOffset * offset, NR::Point *px)
 
     delete theShape;
     delete finalPath;
-    sp_curve_unref (curve);
+    curve->unref();
 }
 
 // the listening functions
@@ -1094,23 +1024,24 @@ sp_offset_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPOffset *offse
 }
 
 static void
-sp_offset_move_compensate(NR::Matrix const *mp, SPItem *original, SPOffset *self)
+sp_offset_move_compensate(Geom::Matrix const *mp, SPItem */*original*/, SPOffset *self)
 {
-    guint mode = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_PARALLEL);
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    guint mode = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_PARALLEL);
     if (mode == SP_CLONE_COMPENSATION_NONE) return;
 
-    NR::Matrix m(*mp);
-    if (!(m.is_translation())) return;
+    Geom::Matrix m(*mp);
+    if (!(m.isTranslation())) return;
 
     // calculate the compensation matrix and the advertized movement matrix
     SPItem *item = SP_ITEM(self);
 
-    NR::Matrix compensate;
-    NR::Matrix advertized_move;
+    Geom::Matrix compensate;
+    Geom::Matrix advertized_move;
 
     if (mode == SP_CLONE_COMPENSATION_UNMOVED) {
-        compensate = NR::identity();
-        advertized_move.set_identity();
+        compensate = Geom::identity();
+        advertized_move.setIdentity();
     } else if (mode == SP_CLONE_COMPENSATION_PARALLEL) {
         compensate = m;
         advertized_move = m;
@@ -1121,14 +1052,15 @@ sp_offset_move_compensate(NR::Matrix const *mp, SPItem *original, SPOffset *self
     item->transform *= compensate;
 
     // commit the compensation
-    sp_item_write_transform(item, SP_OBJECT_REPR(item), item->transform, &advertized_move);
+    item->doWriteTransform(SP_OBJECT_REPR(item), item->transform, &advertized_move);
     SP_OBJECT(item)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
 }
 
 static void
 sp_offset_delete_self(SPObject */*deleted*/, SPOffset *offset)
 {
-    guint const mode = prefs_get_int_attribute("options.cloneorphans", "value", SP_CLONE_ORPHANS_UNLINK);
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    guint const mode = prefs->getInt("/options/cloneorphans/value", SP_CLONE_ORPHANS_UNLINK);
 
     if (mode == SP_CLONE_ORPHANS_UNLINK) {
         // leave it be. just forget about the source
@@ -1142,12 +1074,12 @@ sp_offset_delete_self(SPObject */*deleted*/, SPOffset *offset)
 }
 
 static void
-sp_offset_source_modified (SPObject *iSource, guint flags, SPItem *item)
+sp_offset_source_modified (SPObject */*iSource*/, guint /*flags*/, SPItem *item)
 {
     SPOffset *offset = SP_OFFSET(item);
     offset->sourceDirty=true;
     refresh_offset_source(offset);
-    sp_shape_set_shape ((SPShape *) offset);
+    ((SPShape *) offset)->setShape ();
 }
 
 static void
@@ -1155,7 +1087,6 @@ refresh_offset_source(SPOffset* offset)
 {
     if ( offset == NULL ) return;
     offset->sourceDirty=false;
-    Path *orig = NULL;
 
     // le mauvais cas: pas d'attribut d => il faut verifier que c'est une SPShape puis prendre le contour
     // The bad case: no d attribute.  Must check that it's an SPShape and then take the outline.
@@ -1166,17 +1097,18 @@ refresh_offset_source(SPOffset* offset)
     SPCurve *curve=NULL;
     if (!SP_IS_SHAPE (item) && !SP_IS_TEXT (item)) return;
     if (SP_IS_SHAPE (item)) {
-        curve = sp_shape_get_curve (SP_SHAPE (item));
+        curve = SP_SHAPE (item)->getCurve ();
         if (curve == NULL)
             return;
     }
     if (SP_IS_TEXT (item)) {
         curve = SP_TEXT (item)->getNormalizedBpath ();
         if (curve == NULL)
-           return;
+        return;
     }
-    orig = bpath_to_liv_path (SP_CURVE_BPATH(curve));
-    sp_curve_unref (curve);
+    Path *orig = new Path;
+    orig->LoadPathVector(curve->get_pathvector());
+    curve->unref();
 
 
     // Finish up.
@@ -1216,7 +1148,8 @@ refresh_offset_source(SPOffset* offset)
         delete res;
         delete orig;
 
-        SP_OBJECT (offset)->repr->setAttribute("inkscape:original", res_d);
+        //XML Tree being used diectly here while it shouldn't be.
+        SP_OBJECT (offset)->getRepr()->setAttribute("inkscape:original", res_d);
 
         free (res_d);
     }
@@ -1243,4 +1176,4 @@ sp_offset_get_source (SPOffset *offset)
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :